diff --git a/package-lock.json b/package-lock.json index 3f0802d..04bd4f5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,6 +14,7 @@ "@google-cloud/vision": "^4.3.2", "@google/generative-ai": "^0.21.0", "@sei-js/core": "^3.2.0", + "@sei-js/react": "^3.2.0", "@solana/spl-token": "^0.3.8", "@solana/web3.js": "^1.78.4", "@supabase/supabase-js": "^2.49.1", @@ -285,6 +286,24 @@ "resolved": "https://registry.npmjs.org/@cosmjs/utils/-/utils-0.32.4.tgz", "integrity": "sha512-D1Yc+Zy8oL/hkUkFUL/bwxvuDBzRGpc4cF7/SkdhxX4iHpSLgdOuTt1mhCh9+kl6NQREy9t7SYZ6xeW5gFe60w==" }, + "node_modules/@emotion/is-prop-valid": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.2.tgz", + "integrity": "sha512-uNsoYd37AFmaCdXlg6EYD1KaPOaRWRByMCYzbKUX4+hhMfrxdVSelShywL4JVaAeM/eHUOSprYBQls+/neX3pw==", + "dependencies": { + "@emotion/memoize": "^0.8.1" + } + }, + "node_modules/@emotion/memoize": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", + "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==" + }, + "node_modules/@emotion/unitless": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz", + "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==" + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", @@ -1269,6 +1288,14 @@ "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==", "license": "BSD-3-Clause" }, + "node_modules/@react-icons/all-files": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@react-icons/all-files/-/all-files-4.1.0.tgz", + "integrity": "sha512-hxBI2UOuVaI3O/BhQfhtb4kcGn9ft12RWAFVMUeNjqqhLsHvFtzIkFaptBJpFDANTKoDfdVoHTKZDlwKCACbMQ==", + "peerDependencies": { + "react": "*" + } + }, "node_modules/@rtsao/scc": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", @@ -1701,6 +1728,23 @@ "pbts": "bin/pbts" } }, + "node_modules/@sei-js/react": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@sei-js/react/-/react-3.2.0.tgz", + "integrity": "sha512-62E1dQu/zyDq/shoO2Pjtw5Xv3/G3gK6o2FI4lk/lxc69cs/ivR4ao8tAOItPLENGX9KCU5hlSMwXLXUgzg6ig==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "dependencies": { + "@react-icons/all-files": "^4.1.0", + "@sei-js/core": "^3.1.1", + "buffer": "^6.0.3", + "process": "^0.11.10", + "styled-components": "^6.1.1" + }, + "peerDependencies": { + "react": "^17.0.0 || ^18.0.0", + "react-dom": "^17.0.0 || ^18.0.0" + } + }, "node_modules/@solana/buffer-layout": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@solana/buffer-layout/-/buffer-layout-4.0.1.tgz", @@ -2254,6 +2298,11 @@ "@types/send": "*" } }, + "node_modules/@types/stylis": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@types/stylis/-/stylis-4.2.5.tgz", + "integrity": "sha512-1Xve+NMN7FWjY14vLoY5tL3BVEQ/n42YLwaqJIPYhotZ9uBHt87VceMwWQpzmdEt2TNXIorIFG+YeCUUW7RInw==" + }, "node_modules/@types/tough-cookie": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", @@ -3061,6 +3110,14 @@ "node": ">= 6" } }, + "node_modules/camelize": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.1.tgz", + "integrity": "sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/caniuse-lite": { "version": "1.0.30001690", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001690.tgz", @@ -3334,6 +3391,24 @@ "node": ">= 8" } }, + "node_modules/css-color-keywords": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz", + "integrity": "sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==", + "engines": { + "node": ">=4" + } + }, + "node_modules/css-to-react-native": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.2.0.tgz", + "integrity": "sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==", + "dependencies": { + "camelize": "^1.0.0", + "css-color-keywords": "^1.0.0", + "postcss-value-parser": "^4.0.2" + } + }, "node_modules/cssesc": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", @@ -3349,8 +3424,7 @@ "node_modules/csstype": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "dev": true + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" }, "node_modules/damerau-levenshtein": { "version": "1.0.8", @@ -6972,8 +7046,7 @@ "node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "node_modules/preact": { "version": "10.11.3", @@ -7524,6 +7597,11 @@ "sha.js": "bin.js" } }, + "node_modules/shallowequal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", + "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==" + }, "node_modules/sharp": { "version": "0.33.5", "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.5.tgz", @@ -7973,6 +8051,65 @@ "integrity": "sha512-PdHt7hHUJKxvTCgbKX9C1V/ftOcjJQgz8BZwNfV5c4B6dcGqlpelTbJ999jBGZ2jYiPAwcX5dP6oBwVlBlUbxw==", "license": "MIT" }, + "node_modules/styled-components": { + "version": "6.1.16", + "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-6.1.16.tgz", + "integrity": "sha512-KpWB6ORAWGmbWM10cDJfEV6sXc/uVkkkQV3SLwTNQ/E/PqWgNHIoMSLh1Lnk2FkB9+JHK7uuMq1i+9ArxDD7iQ==", + "dependencies": { + "@emotion/is-prop-valid": "1.2.2", + "@emotion/unitless": "0.8.1", + "@types/stylis": "4.2.5", + "css-to-react-native": "3.2.0", + "csstype": "3.1.3", + "postcss": "8.4.49", + "shallowequal": "1.1.0", + "stylis": "4.3.2", + "tslib": "2.6.2" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/styled-components" + }, + "peerDependencies": { + "react": ">= 16.8.0", + "react-dom": ">= 16.8.0" + } + }, + "node_modules/styled-components/node_modules/postcss": { + "version": "8.4.49", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz", + "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/styled-components/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, "node_modules/styled-jsx": { "version": "5.1.6", "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz", @@ -7996,6 +8133,11 @@ } } }, + "node_modules/stylis": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.2.tgz", + "integrity": "sha512-bhtUjWd/z6ltJiQwg0dUfxEJ+W+jdqQd8TbWLWyeIJHlnsqmGLRFFd8e5mA0AZi/zx90smXRlN66YMTcaSFifg==" + }, "node_modules/sucrase": { "version": "3.35.0", "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", diff --git a/package.json b/package.json index 7984330..08df89e 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "@google-cloud/vision": "^4.3.2", "@google/generative-ai": "^0.21.0", "@sei-js/core": "^3.2.0", + "@sei-js/react": "^3.2.0", "@solana/spl-token": "^0.3.8", "@solana/web3.js": "^1.78.4", "@supabase/supabase-js": "^2.49.1", diff --git a/src/services/blockchain/seiService.ts b/src/services/blockchain/seiService.ts index ead1f2a..0ebf6b9 100644 --- a/src/services/blockchain/seiService.ts +++ b/src/services/blockchain/seiService.ts @@ -1,7 +1,21 @@ // src/services/blockchain/seiService.ts -import { SeiWallet } from '@sei-js/core'; -import { AccountData, OfflineSigner } from '@cosmjs/proto-signing'; -import { getSigningCosmWasmClient } from '@cosmjs/cosmwasm-stargate'; +import { OfflineSigner } from '@cosmjs/proto-signing'; +import { SigningCosmWasmClient } from '@cosmjs/cosmwasm-stargate'; + +// Add type declarations for wallet extensions +declare global { + interface Window { + keplr?: { + enable: (chainId: string) => Promise; + getOfflineSigner: (chainId: string) => import('@cosmjs/proto-signing').OfflineSigner; + experimentalSuggestChain: (config: any) => Promise; + }; + leap?: { + enable: (chainId: string) => Promise; + getOfflineSigner: (chainId: string) => import('@cosmjs/proto-signing').OfflineSigner; + }; + } +} // Sei network configurations const NETWORKS = { @@ -15,7 +29,7 @@ const NETWORKS = { }; // Track connected wallet state -let currentWallet: SeiWallet | null = null; +let currentWallet: OfflineSigner | null = null; let currentAddress: string | null = null; let cosmWasmClient: any = null; @@ -48,25 +62,80 @@ export const connectSeiWallet = async (): Promise => { return null; } - // Initialize SeiWallet from @sei-js/core - const wallet = await SeiWallet.connectWallet(); - if (!wallet) { - throw new Error('Failed to connect wallet'); + // Use Keplr or Leap wallet + const network = NETWORKS.testnet; + let offlineSigner: OfflineSigner; + + if (window.keplr) { + // Suggest chain to Keplr if needed + try { + await window.keplr.experimentalSuggestChain({ + chainId: network.chainId, + chainName: 'Sei Testnet', + rpc: network.rpcUrl, + rest: network.restUrl, + bip44: { + coinType: 118, + }, + coinType: 118, + stakeCurrency: { + coinDenom: 'SEI', + coinMinimalDenom: 'usei', + coinDecimals: 6, + }, + bech32Config: { + bech32PrefixAccAddr: 'sei', + bech32PrefixAccPub: 'seipub', + bech32PrefixValAddr: 'seivaloper', + bech32PrefixValPub: 'seivaloperpub', + bech32PrefixConsAddr: 'seivalcons', + bech32PrefixConsPub: 'seivalconspub', + }, + currencies: [ + { + coinDenom: 'SEI', + coinMinimalDenom: 'usei', + coinDecimals: 6, + }, + ], + feeCurrencies: [ + { + coinDenom: 'SEI', + coinMinimalDenom: 'usei', + coinDecimals: 6, + gasPriceStep: { + low: 0.01, + average: 0.025, + high: 0.04, + }, + }, + ], + }); + } catch (error) { + console.warn('Failed to suggest chain to Keplr:', error); + } + + await window.keplr.enable(network.chainId); + offlineSigner = window.keplr.getOfflineSigner(network.chainId); + } else if (window.leap) { + await window.leap.enable(network.chainId); + offlineSigner = window.leap.getOfflineSigner(network.chainId); + } else { + throw new Error('No compatible wallet found'); } // Get the connected wallet's address - const [account] = await wallet.getAccounts(); + const [account] = await offlineSigner.getAccounts(); const address = account.address; // Store wallet and address - currentWallet = wallet; + currentWallet = offlineSigner as any; currentAddress = address; // Initialize CosmWasm client for contract interactions - const network = NETWORKS.testnet; - cosmWasmClient = await getSigningCosmWasmClient( + cosmWasmClient = await SigningCosmWasmClient.connectWithSigner( network.rpcUrl, - wallet as unknown as OfflineSigner + offlineSigner ); console.log('Sei wallet connected:', address);