From 37eb600961f66e8ae39155e01059f4b1ba84ab69 Mon Sep 17 00:00:00 2001 From: RyukTheCoder Date: Sun, 31 Dec 2023 12:14:17 +0000 Subject: [PATCH 1/3] feat: integrate shapeshift snap --- .vscode/settings.json | 2 +- wallets/provider-all/package.json | 1 + wallets/provider-all/src/index.ts | 2 + wallets/provider-shapeshift-snap/CHANGELOG.md | 0 wallets/provider-shapeshift-snap/package.json | 31 +++++ wallets/provider-shapeshift-snap/readme.md | 1 + .../provider-shapeshift-snap/src/helpers.ts | 119 ++++++++++++++++++ wallets/provider-shapeshift-snap/src/index.ts | 76 +++++++++++ .../provider-shapeshift-snap/src/signer.ts | 10 ++ .../provider-shapeshift-snap/tsconfig.json | 11 ++ wallets/shared/src/index.ts | 1 + wallets/shared/src/rango.ts | 1 + wallets/shared/src/snaps.ts | 54 ++++++++ 13 files changed, 308 insertions(+), 1 deletion(-) create mode 100644 wallets/provider-shapeshift-snap/CHANGELOG.md create mode 100644 wallets/provider-shapeshift-snap/package.json create mode 100644 wallets/provider-shapeshift-snap/readme.md create mode 100644 wallets/provider-shapeshift-snap/src/helpers.ts create mode 100644 wallets/provider-shapeshift-snap/src/index.ts create mode 100644 wallets/provider-shapeshift-snap/src/signer.ts create mode 100644 wallets/provider-shapeshift-snap/tsconfig.json create mode 100644 wallets/shared/src/snaps.ts diff --git a/.vscode/settings.json b/.vscode/settings.json index 81e23afff3..59f51dbc0a 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,6 +1,6 @@ { "editor.codeActionsOnSave": { - "source.fixAll.eslint": true + "source.fixAll.eslint": "explicit" }, "eslint.validate": [ "javascript", diff --git a/wallets/provider-all/package.json b/wallets/provider-all/package.json index f8060a5f35..d0ab585679 100644 --- a/wallets/provider-all/package.json +++ b/wallets/provider-all/package.json @@ -42,6 +42,7 @@ "@rango-dev/provider-phantom": "^0.25.1-next.1", "@rango-dev/provider-safe": "^0.18.1-next.1", "@rango-dev/provider-safepal": "^0.25.1-next.1", + "@rango-dev/provider-shapeshift-snap": "^0.25.1-next.1", "@rango-dev/provider-taho": "^0.25.1-next.1", "@rango-dev/provider-tokenpocket": "^0.25.1-next.1", "@rango-dev/provider-tron-link": "^0.25.1-next.1", diff --git a/wallets/provider-all/src/index.ts b/wallets/provider-all/src/index.ts index c154bbf7d0..5995d47783 100644 --- a/wallets/provider-all/src/index.ts +++ b/wallets/provider-all/src/index.ts @@ -19,6 +19,7 @@ import * as okx from '@rango-dev/provider-okx'; import * as phantom from '@rango-dev/provider-phantom'; import * as safe from '@rango-dev/provider-safe'; import * as safepal from '@rango-dev/provider-safepal'; +import * as shapeShiftSnap from '@rango-dev/provider-shapeshift-snap'; import * as taho from '@rango-dev/provider-taho'; import * as tokenpocket from '@rango-dev/provider-tokenpocket'; import * as tronLink from '@rango-dev/provider-tron-link'; @@ -59,5 +60,6 @@ export const allProviders = (enviroments?: Enviroments) => { frontier, taho, braavos, + shapeShiftSnap, ]; }; diff --git a/wallets/provider-shapeshift-snap/CHANGELOG.md b/wallets/provider-shapeshift-snap/CHANGELOG.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/wallets/provider-shapeshift-snap/package.json b/wallets/provider-shapeshift-snap/package.json new file mode 100644 index 0000000000..39bb56925a --- /dev/null +++ b/wallets/provider-shapeshift-snap/package.json @@ -0,0 +1,31 @@ +{ + "name": "@rango-dev/provider-shapeshift-snap", + "version": "0.25.1-next.1", + "license": "MIT", + "type": "module", + "source": "./src/index.ts", + "main": "./dist/index.js", + "exports": { + ".": "./dist/index.js" + }, + "typings": "dist/index.d.ts", + "files": [ + "dist", + "src" + ], + "scripts": { + "build": "node ../../scripts/build/command.mjs --path wallets/provider-shapeshift-snap", + "ts-check": "tsc --declaration --emitDeclarationOnly -p ./tsconfig.json", + "clean": "rimraf dist", + "format": "prettier --write '{.,src}/**/*.{ts,tsx}'", + "lint": "eslint \"**/*.{ts,tsx}\" --ignore-path ../../.eslintignore" + }, + "dependencies": { + "@rango-dev/signer-evm": "^0.25.0", + "@rango-dev/wallets-shared": "^0.25.1-next.1", + "rango-types": "^0.1.57" + }, + "publishConfig": { + "access": "public" + } +} diff --git a/wallets/provider-shapeshift-snap/readme.md b/wallets/provider-shapeshift-snap/readme.md new file mode 100644 index 0000000000..13594f4c25 --- /dev/null +++ b/wallets/provider-shapeshift-snap/readme.md @@ -0,0 +1 @@ +# @rango-dev/provider-shapeshift-snap diff --git a/wallets/provider-shapeshift-snap/src/helpers.ts b/wallets/provider-shapeshift-snap/src/helpers.ts new file mode 100644 index 0000000000..988f034919 --- /dev/null +++ b/wallets/provider-shapeshift-snap/src/helpers.ts @@ -0,0 +1,119 @@ +import type { ProviderConnectResult } from '@rango-dev/wallets-shared'; + +import { + getCoinbaseInstance, + Networks, + walletInvokeSnap, + walletRequestSnaps, +} from '@rango-dev/wallets-shared'; + +export const DEFAULT_SNAP_ID = 'npm:@shapeshiftoss/metamask-snaps'; +export const SNAP_VERSION = '1.0.0'; + +export const SHAPESHIFT_SNAP_SUPPORTED_CHAINS = [ + Networks.BTC, + Networks.BCH, + Networks.LTC, +]; + +const snapNetworksConfig: { + chainId: Networks; + method: string; + params: { + addressParams: { + coin: string; + addressNList: number[]; + scriptType: string; + }; + }; +}[] = [ + { + chainId: Networks.BTC, + method: 'btc_getPublicKeys', + params: { + addressParams: { + coin: 'Bitcoin', + // eslint-disable-next-line @typescript-eslint/no-magic-numbers + addressNList: [0x80000000 + 44, 0x80000000 + 0, 0x80000000 + 0, 0, 0], + scriptType: 'p2pkh', + }, + }, + }, + { + chainId: Networks.BCH, + method: 'bch_getPublicKeys', + params: { + addressParams: { + coin: 'BitcoinCash', + // eslint-disable-next-line @typescript-eslint/no-magic-numbers + addressNList: [0x80000000 + 44, 0x80000000 + 145, 0x80000000 + 0, 0, 0], + scriptType: 'p2pkh', + }, + }, + }, + { + chainId: Networks.LTC, + method: 'ltc_getPublicKeys', + params: { + addressParams: { + coin: 'Litecoin', + // eslint-disable-next-line @typescript-eslint/no-magic-numbers + addressNList: [0x80000000 + 44, 0x80000000 + 2, 0x80000000 + 0, 0, 0], + scriptType: 'p2pkh', + }, + }, + }, +]; + +export function metamask() { + const isCoinbaseWalletAvailable = !!getCoinbaseInstance(); + const { ethereum } = window; + + // Some wallets overriding the metamask. So we need to get it properly. + if (isCoinbaseWalletAvailable) { + // Getting intance from overrided structure from coinbase. + return getCoinbaseInstance('metamask'); + } + if (!!ethereum && ethereum.isMetaMask) { + return ethereum; + } + + return null; +} + +export const installSnap = async (instance: any) => { + return walletRequestSnaps({ + instance, + snapId: DEFAULT_SNAP_ID, + version: '1.0.0', + }); +}; + +export const getAccounts = async ( + instance: any +): Promise => { + const accountPromises = snapNetworksConfig.map(async (item) => { + const address = await walletInvokeSnap({ + instance, + params: { + snapId: DEFAULT_SNAP_ID, + request: { + method: item.method, + params: item.params, + }, + }, + }); + + return { + accounts: [address?.[0]?.xpub], + chainId: item.chainId, + }; + }); + + const accounts = await Promise.all(accountPromises); + // return accounts; + + console.log(accounts); + + return []; +}; diff --git a/wallets/provider-shapeshift-snap/src/index.ts b/wallets/provider-shapeshift-snap/src/index.ts new file mode 100644 index 0000000000..8ac0872156 --- /dev/null +++ b/wallets/provider-shapeshift-snap/src/index.ts @@ -0,0 +1,76 @@ +import type { + CanEagerConnect, + Connect, + Networks, + ProviderConnectResult, + WalletInfo, +} from '@rango-dev/wallets-shared'; +import type { BlockchainMeta, SignerFactory } from 'rango-types'; + +import { WalletTypes } from '@rango-dev/wallets-shared'; + +import { + getAccounts, + installSnap, + metamask as metamask_instance, + SHAPESHIFT_SNAP_SUPPORTED_CHAINS, +} from './helpers'; +import signer from './signer'; + +const WALLET = WalletTypes.SHAPESHIFT_SNAP; + +export const config = { + type: WALLET, +}; + +export const getInstance = metamask_instance; +export const connect: Connect = async ({ instance }: { instance: any }) => { + let accounts: ProviderConnectResult[] = []; + + const installed = await installSnap(instance); + + if (!!installed) { + accounts = await getAccounts(instance); + } + + return accounts; +}; + +export const getSigners: (provider: any) => SignerFactory = signer; + +export const canEagerConnect: CanEagerConnect = async ({ + instance, +}: { + instance: any; +}) => { + try { + const accounts = await getAccounts(instance); + if (accounts.length) { + return true; + } + return false; + } catch (error) { + return false; + } +}; + +export const getWalletInfo: (allBlockChains: BlockchainMeta[]) => WalletInfo = ( + allBlockChains +) => { + return { + name: 'ShapeShift Snap', + img: 'https://raw.githubusercontent.com/rango-exchange/assets/main/wallets/metamask/icon.svg', + installLink: { + CHROME: 'https://shapeshift.com/snap', + BRAVE: 'https://shapeshift.com/snap', + + FIREFOX: 'https://shapeshift.com/snap', + EDGE: 'https://shapeshift.com/snap', + DEFAULT: 'https://shapeshift.com/snap', + }, + color: '#dac7ae', + supportedChains: allBlockChains.filter((blockchainMeta) => + SHAPESHIFT_SNAP_SUPPORTED_CHAINS.includes(blockchainMeta.name as Networks) + ), + }; +}; diff --git a/wallets/provider-shapeshift-snap/src/signer.ts b/wallets/provider-shapeshift-snap/src/signer.ts new file mode 100644 index 0000000000..375d8864dd --- /dev/null +++ b/wallets/provider-shapeshift-snap/src/signer.ts @@ -0,0 +1,10 @@ +import type { SignerFactory } from 'rango-types'; + +import { DefaultEvmSigner } from '@rango-dev/signer-evm'; +import { DefaultSignerFactory, TransactionType as TxType } from 'rango-types'; + +export default function getSigners(provider: any): SignerFactory { + const signers = new DefaultSignerFactory(); + signers.registerSigner(TxType.EVM, new DefaultEvmSigner(provider)); + return signers; +} diff --git a/wallets/provider-shapeshift-snap/tsconfig.json b/wallets/provider-shapeshift-snap/tsconfig.json new file mode 100644 index 0000000000..7f49cdfc54 --- /dev/null +++ b/wallets/provider-shapeshift-snap/tsconfig.json @@ -0,0 +1,11 @@ +{ + // see https://www.typescriptlang.org/tsconfig to better understand tsconfigs + "extends": "../../tsconfig.lib.json", + "include": ["src", "types", "../../global-wallets-env.d.ts"], + "compilerOptions": { + "outDir": "dist", + "rootDir": "./src", + "lib": ["dom", "esnext"] + // match output dir to input dir. e.g. dist/index instead of dist/src/index + } +} diff --git a/wallets/shared/src/index.ts b/wallets/shared/src/index.ts index 68f5fd78be..52a4a6268d 100644 --- a/wallets/shared/src/index.ts +++ b/wallets/shared/src/index.ts @@ -2,3 +2,4 @@ export * from './helpers'; export * from './providers'; export * from './rango'; export * from './getCosmosAccounts'; +export * from './snaps'; diff --git a/wallets/shared/src/rango.ts b/wallets/shared/src/rango.ts index 2367cc779a..99682bc346 100644 --- a/wallets/shared/src/rango.ts +++ b/wallets/shared/src/rango.ts @@ -79,6 +79,7 @@ export enum WalletTypes { ENKRYPT = 'enkrypt', TAHO = 'taho', MY_TON_WALLET = 'mytonwallet', + SHAPESHIFT_SNAP = 'shapeShiftSnap', } export enum Networks { diff --git a/wallets/shared/src/snaps.ts b/wallets/shared/src/snaps.ts new file mode 100644 index 0000000000..984249e827 --- /dev/null +++ b/wallets/shared/src/snaps.ts @@ -0,0 +1,54 @@ +export const walletRequestSnaps = async ({ + instance, + snapId, + version, +}: { + instance: any; + snapId: string; + version?: string; +}): Promise => { + if (instance === undefined) { + throw new Error('Could not get MetaMask provider'); + } + if (instance.request === undefined) { + throw new Error('MetaMask provider does not define a .request() method'); + } + + try { + const ret = await instance.request({ + method: 'wallet_requestSnaps', + params: { + [snapId]: { version }, + }, + }); + return ret; + } catch (error) { + console.log('wallet_requestSnaps RPC call failed.', error); + return Promise.reject(error); + } +}; + +export const walletInvokeSnap = async ({ + instance, + params, +}: { + instance: any; + params?: any; +}): Promise => { + if (instance === undefined) { + throw new Error('Could not get MetaMask provider'); + } + if (instance.request === undefined) { + throw new Error('MetaMask provider does not define a .request() method'); + } + try { + const ret = await instance.request({ + method: 'wallet_invokeSnap', + params, + }); + return ret; + } catch (error) { + console.log('wallet_invokeSnap RPC call failed.', error); + return Promise.reject(error); + } +}; From 25ef097e1def7756c2a7c164cf45f25a84673b1f Mon Sep 17 00:00:00 2001 From: RyukTheCoder Date: Sun, 31 Dec 2023 21:06:17 +0000 Subject: [PATCH 2/3] feat: integrate shapeshift snap --- .../provider-shapeshift-snap/src/helpers.ts | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/wallets/provider-shapeshift-snap/src/helpers.ts b/wallets/provider-shapeshift-snap/src/helpers.ts index 988f034919..e3fe7763ca 100644 --- a/wallets/provider-shapeshift-snap/src/helpers.ts +++ b/wallets/provider-shapeshift-snap/src/helpers.ts @@ -14,6 +14,7 @@ export const SHAPESHIFT_SNAP_SUPPORTED_CHAINS = [ Networks.BTC, Networks.BCH, Networks.LTC, + Networks.DOGE, ]; const snapNetworksConfig: { @@ -63,6 +64,18 @@ const snapNetworksConfig: { }, }, }, + { + chainId: Networks.DOGE, + method: 'doge_getPublicKeys', + params: { + addressParams: { + coin: 'Dogecoin', + // eslint-disable-next-line @typescript-eslint/no-magic-numbers + addressNList: [0x80000000 + 44, 0x80000000 + 3, 0x80000000 + 0, 0, 0], + scriptType: 'p2pkh', + }, + }, + }, ]; export function metamask() { @@ -111,9 +124,5 @@ export const getAccounts = async ( }); const accounts = await Promise.all(accountPromises); - // return accounts; - - console.log(accounts); - - return []; + return accounts; }; From 795d29c2a1fed0688804368663b2fa7c3f29cfb1 Mon Sep 17 00:00:00 2001 From: RyukTheCoder Date: Sun, 14 Jan 2024 10:43:48 +0000 Subject: [PATCH 3/3] feat: integrate shapeshift snap --- .../provider-shapeshift-snap/src/helpers.ts | 183 +++++++++++++++--- wallets/provider-shapeshift-snap/src/index.ts | 21 +- .../provider-shapeshift-snap/src/signer.ts | 13 +- .../src/signer/shapeShiftSnapBaseSigner.ts | 98 ++++++++++ .../src/signer/shapeShiftSnapCosmosSigner.ts | 83 ++++++++ 5 files changed, 348 insertions(+), 50 deletions(-) create mode 100644 wallets/provider-shapeshift-snap/src/signer/shapeShiftSnapBaseSigner.ts create mode 100644 wallets/provider-shapeshift-snap/src/signer/shapeShiftSnapCosmosSigner.ts diff --git a/wallets/provider-shapeshift-snap/src/helpers.ts b/wallets/provider-shapeshift-snap/src/helpers.ts index e3fe7763ca..2e57262b43 100644 --- a/wallets/provider-shapeshift-snap/src/helpers.ts +++ b/wallets/provider-shapeshift-snap/src/helpers.ts @@ -8,29 +8,33 @@ import { } from '@rango-dev/wallets-shared'; export const DEFAULT_SNAP_ID = 'npm:@shapeshiftoss/metamask-snaps'; -export const SNAP_VERSION = '1.0.0'; +export const DEFAULT_SNAP_VERSION = '1.0.0'; export const SHAPESHIFT_SNAP_SUPPORTED_CHAINS = [ Networks.BTC, Networks.BCH, - Networks.LTC, + Networks.COSMOS, + Networks.OSMOSIS, Networks.DOGE, + Networks.ETHEREUM, + Networks.LTC, + Networks.THORCHAIN, ]; const snapNetworksConfig: { - chainId: Networks; + chainId: string; method: string; params: { addressParams: { - coin: string; - addressNList: number[]; - scriptType: string; + coin?: string; + addressNList?: number[]; + scriptType?: string; }; }; }[] = [ { chainId: Networks.BTC, - method: 'btc_getPublicKeys', + method: 'btc_getAddress', params: { addressParams: { coin: 'Bitcoin', @@ -42,7 +46,7 @@ const snapNetworksConfig: { }, { chainId: Networks.BCH, - method: 'bch_getPublicKeys', + method: 'bch_getAddress', params: { addressParams: { coin: 'BitcoinCash', @@ -54,7 +58,7 @@ const snapNetworksConfig: { }, { chainId: Networks.LTC, - method: 'ltc_getPublicKeys', + method: 'ltc_getAddress', params: { addressParams: { coin: 'Litecoin', @@ -64,18 +68,111 @@ const snapNetworksConfig: { }, }, }, + /* + * { + * chainId: Networks.DOGE, + * method: 'doge_getAddress', + * params: { + * addressParams: { + * coin: 'Dogecoin', + * // eslint-disable-next-line @typescript-eslint/no-magic-numbers + * addressNList: [0x80000000 + 44, 0x80000000 + 3, 0x80000000 + 0, 0, 0], + * scriptType: 'p2pkh', + * }, + * }, + * }, + */ + /* + * { + * chainId: Networks.BINANCE, + * method: 'binance_getAddress', + * params: { + * addressParams: { + * // eslint-disable-next-line @typescript-eslint/no-magic-numbers + * addressNList: [0x80000000 + 44, 0x80000000 + 714, 0x80000000 + 0, 0, 0], + * }, + * }, + * }, + */ + { - chainId: Networks.DOGE, - method: 'doge_getPublicKeys', + chainId: Networks.COSMOS, + method: 'cosmos_getAddress', params: { addressParams: { - coin: 'Dogecoin', // eslint-disable-next-line @typescript-eslint/no-magic-numbers - addressNList: [0x80000000 + 44, 0x80000000 + 3, 0x80000000 + 0, 0, 0], - scriptType: 'p2pkh', + addressNList: [0x80000000 + 44, 0x80000000 + 118, 0x80000000 + 0, 0, 0], + }, + }, + }, + /* + * { + * chainId: Networks.ETHEREUM, + * method: 'eth_getAddress', + * params: { + * addressParams: { + * // eslint-disable-next-line @typescript-eslint/no-magic-numbers + * addressNList: [0x80000000 + 44, 0x80000000 + 60, 0x80000000 + 0, 0, 0], + * }, + * }, + * }, + */ + { + chainId: 'osmosis-1', + method: 'osmosis_getAddress', + params: { + addressParams: { + // eslint-disable-next-line @typescript-eslint/no-magic-numbers + addressNList: [0x80000000 + 44, 0x80000000 + 118, 0x80000000 + 0, 0, 0], + }, + }, + }, + /* + * { + * chainId: Networks.SECRET, + * method: 'secret_getAddress', + * params: { + * addressParams: { + * // eslint-disable-next-line @typescript-eslint/no-magic-numbers + * addressNList: [0x80000000 + 44, 0x80000000 + 529, 0x80000000 + 0, 0, 0], + * }, + * }, + * }, + */ + /* + * { + * chainId: Networks.TERRA, + * method: 'terra_getAddress', + * params: { + * addressParams: { + * // eslint-disable-next-line @typescript-eslint/no-magic-numbers + * addressNList: [0x80000000 + 44, 0x80000000 + 330, 0x80000000 + 0, 0, 0], + * }, + * }, + * }, + */ + { + chainId: Networks.THORCHAIN, + method: 'thorchain_getAddress', + params: { + addressParams: { + // eslint-disable-next-line @typescript-eslint/no-magic-numbers + addressNList: [0x80000000 + 44, 0x80000000 + 931, 0x80000000 + 0, 0, 0], }, }, }, + /* + * { + * chainId: Networks.AVAX_CCHAIN, + * method: 'avax_getAddress', + * params: { + * addressParams: { + * // eslint-disable-next-line @typescript-eslint/no-magic-numbers + * addressNList: [0x80000000 + 44, 0x80000000 + 60, 0x80000000 + 0, 0, 0], + * }, + * }, + * }, + */ ]; export function metamask() { @@ -98,31 +195,55 @@ export const installSnap = async (instance: any) => { return walletRequestSnaps({ instance, snapId: DEFAULT_SNAP_ID, - version: '1.0.0', + version: DEFAULT_SNAP_VERSION, }); }; export const getAccounts = async ( instance: any ): Promise => { - const accountPromises = snapNetworksConfig.map(async (item) => { - const address = await walletInvokeSnap({ - instance, - params: { - snapId: DEFAULT_SNAP_ID, - request: { - method: item.method, - params: item.params, + const MAX_CONCURRENT_REQUESTS = 4; // Implemented this way to revent following error: "Exceeds maximum number of requests waiting to be resolved" + + const resolvedAccounts: ProviderConnectResult[] = []; + let index = 0; + + while (index < snapNetworksConfig.length) { + const batchConfigs = snapNetworksConfig.slice( + index, + index + MAX_CONCURRENT_REQUESTS + ); + const batchPromises = batchConfigs.map(async (item) => { + let address: string = await walletInvokeSnap({ + instance, + params: { + snapId: DEFAULT_SNAP_ID, + request: { + method: item.method, + params: item.params, + }, }, - }, + }); + + if (address.includes(':')) { + address = address.split(':')[1]; // this line is here because bitcoin cash address returns like "bitcoincash:..." + } + + return { + accounts: [address], + chainId: item.chainId, + }; }); + const availableAccountForChains = await Promise.allSettled(batchPromises); - return { - accounts: [address?.[0]?.xpub], - chainId: item.chainId, - }; - }); + availableAccountForChains.forEach((result) => { + if (result.status === 'fulfilled') { + const { accounts, chainId } = result.value; + resolvedAccounts.push({ accounts, chainId }); + } + }); + + index += MAX_CONCURRENT_REQUESTS; + } - const accounts = await Promise.all(accountPromises); - return accounts; + return resolvedAccounts; }; diff --git a/wallets/provider-shapeshift-snap/src/index.ts b/wallets/provider-shapeshift-snap/src/index.ts index 8ac0872156..729bf8ea55 100644 --- a/wallets/provider-shapeshift-snap/src/index.ts +++ b/wallets/provider-shapeshift-snap/src/index.ts @@ -1,5 +1,4 @@ import type { - CanEagerConnect, Connect, Networks, ProviderConnectResult, @@ -33,27 +32,15 @@ export const connect: Connect = async ({ instance }: { instance: any }) => { accounts = await getAccounts(instance); } + if (!accounts?.length) { + throw new Error('Please make sure ShapeShift Snap is installed.'); + } + return accounts; }; export const getSigners: (provider: any) => SignerFactory = signer; -export const canEagerConnect: CanEagerConnect = async ({ - instance, -}: { - instance: any; -}) => { - try { - const accounts = await getAccounts(instance); - if (accounts.length) { - return true; - } - return false; - } catch (error) { - return false; - } -}; - export const getWalletInfo: (allBlockChains: BlockchainMeta[]) => WalletInfo = ( allBlockChains ) => { diff --git a/wallets/provider-shapeshift-snap/src/signer.ts b/wallets/provider-shapeshift-snap/src/signer.ts index 375d8864dd..8b0273d17b 100644 --- a/wallets/provider-shapeshift-snap/src/signer.ts +++ b/wallets/provider-shapeshift-snap/src/signer.ts @@ -1,10 +1,19 @@ import type { SignerFactory } from 'rango-types'; -import { DefaultEvmSigner } from '@rango-dev/signer-evm'; import { DefaultSignerFactory, TransactionType as TxType } from 'rango-types'; +import ShapeShiftSnapBaseSigner from './signer/shapeShiftSnapBaseSigner'; +import ShapeShiftSnapCosmosSigner from './signer/shapeShiftSnapCosmosSigner'; + export default function getSigners(provider: any): SignerFactory { const signers = new DefaultSignerFactory(); - signers.registerSigner(TxType.EVM, new DefaultEvmSigner(provider)); + signers.registerSigner( + TxType.TRANSFER, + new ShapeShiftSnapBaseSigner(provider) + ); + signers.registerSigner( + TxType.COSMOS, + new ShapeShiftSnapCosmosSigner(provider) + ); return signers; } diff --git a/wallets/provider-shapeshift-snap/src/signer/shapeShiftSnapBaseSigner.ts b/wallets/provider-shapeshift-snap/src/signer/shapeShiftSnapBaseSigner.ts new file mode 100644 index 0000000000..f40b36a859 --- /dev/null +++ b/wallets/provider-shapeshift-snap/src/signer/shapeShiftSnapBaseSigner.ts @@ -0,0 +1,98 @@ +import type { GenericSigner, Transfer } from 'rango-types'; + +import { walletInvokeSnap } from '@rango-dev/wallets-shared'; +import { SignerError, SignerErrorCode } from 'rango-types'; + +import { DEFAULT_SNAP_ID } from '../helpers'; + +class ShapeShiftSnapBaseSigner implements GenericSigner { + private provider: any; + + constructor(provider: any) { + this.provider = provider; + } + + public async signMessage(): Promise { + throw SignerError.UnimplementedError('signMessage'); + } + + async signAndSendTx( + tx: Transfer, + address: string + ): Promise<{ hash: string }> { + try { + const temp1 = await fetch( + `https://api.litecoin.shapeshift.com/api/v1/account/${address}/utxos`, + { + method: 'GET', + } + ); + const temp1Json = await temp1.json(); + + const temp2 = await fetch( + `https://api.litecoin.shapeshift.com/api/v1/tx/${temp1Json?.[0]?.txid}`, + { + method: 'GET', + } + ); + const temp2Json = await temp2.json(); + + const signresult = await walletInvokeSnap({ + instance: this.provider, + params: { + snapId: DEFAULT_SNAP_ID, + request: { + method: 'ltc_signTransaction', + params: { + transaction: { + coin: 'Litecoin', + inputs: [ + { + addressNList: temp1Json?.[0]?.path, + scriptType: 'p2pkh', + amount: temp1Json?.[0]?.value, + vout: temp1Json?.[0]?.vout, + txid: temp1Json?.[0]?.txid, + hex: temp2Json?.hex, + }, + ], + outputs: [ + { + addressType: 'spend', + amount: tx.amount, + address: tx.recipientAddress, + }, + { + addressType: 'change', + amount: ( + temp1Json?.[0]?.value - parseInt(tx.amount) + ).toString(), + // eslint-disable-next-line @typescript-eslint/no-magic-numbers + addressNList: [2147483692, 2147483650, 2147483648, 1, 0], + scriptType: 'p2pkh', + isChange: true, + }, + ], + opReturnData: tx.memo, + }, + }, + }, + }, + }); + + console.log(signresult); + + return { hash: '' }; + } catch (err) { + console.log({ err }); + + if (SignerError.isSignerError(err)) { + throw err; + } else { + throw new SignerError(SignerErrorCode.SEND_TX_ERROR, undefined, err); + } + } + } +} + +export default ShapeShiftSnapBaseSigner; diff --git a/wallets/provider-shapeshift-snap/src/signer/shapeShiftSnapCosmosSigner.ts b/wallets/provider-shapeshift-snap/src/signer/shapeShiftSnapCosmosSigner.ts new file mode 100644 index 0000000000..f8a60516cd --- /dev/null +++ b/wallets/provider-shapeshift-snap/src/signer/shapeShiftSnapCosmosSigner.ts @@ -0,0 +1,83 @@ +/* eslint-disable @typescript-eslint/no-magic-numbers */ +import type { CosmosTransaction, GenericSigner } from 'rango-types'; + +import { walletInvokeSnap } from '@rango-dev/wallets-shared'; +import { SignerError, SignerErrorCode } from 'rango-types'; + +import { DEFAULT_SNAP_ID } from '../helpers'; + +const signCosmosTransaction = async (instance: any, tx: CosmosTransaction) => { + const signedTx = await walletInvokeSnap({ + instance, + params: { + snapId: DEFAULT_SNAP_ID, + request: { + method: 'cosmos_signTransaction', + params: { + transaction: { + addressNList: [ + 0x80000000 + 44, + 0x80000000 + 118, + 0x80000000 + 0, + 0, + 0, + ], + chain_id: tx.data.chainId, + account_number: tx.data.account_number, + sequence: tx.data.sequence, + tx: { + fee: tx.data.fee, + memo: tx.data.memo, + msg: tx.data.msgs, + }, + }, + }, + }, + }, + }); + + return signedTx; +}; + +const broadcastCosmosTransaction = async (instance: any, signedTx: any) => { + const result = await fetch('https://api.cosmos.shapeshift.com/api/v1/send', { + method: 'POST', + body: JSON.stringify({ + rawTx: signedTx.serialized, + }), + }); + + const resultJson = await result.json(); + return resultJson; +}; + +class ShapeShiftSnapCosmosSigner implements GenericSigner { + private provider: any; + + constructor(provider: any) { + this.provider = provider; + } + + public async signMessage(): Promise { + throw SignerError.UnimplementedError('signMessage'); + } + + async signAndSendTx(tx: CosmosTransaction): Promise<{ hash: string }> { + try { + const signedTx = await signCosmosTransaction(this.provider, tx); + const result = await broadcastCosmosTransaction(this.provider, signedTx); + + return { hash: result }; + } catch (err) { + console.log({ err }); + + if (SignerError.isSignerError(err)) { + throw err; + } else { + throw new SignerError(SignerErrorCode.SEND_TX_ERROR, undefined, err); + } + } + } +} + +export default ShapeShiftSnapCosmosSigner;