From 860b3f3b3fc278cf3c9bbe0bdaaba933cb19673c Mon Sep 17 00:00:00 2001 From: Yoon-Suji Date: Wed, 26 Apr 2023 18:32:49 +0200 Subject: [PATCH 1/9] feat: add WELLDONE wallet to wallet-ts --- .../wallet-strategy/WalletStrategy.ts | 3 + .../wallet-strategy/strategies/Welldone.ts | 188 ++++++++++++++++++ packages/wallet-ts/src/types/enums.ts | 1 + .../src/utils/wallets/cosmos/utils.ts | 6 +- packages/wallet-ts/src/utils/wallets/index.ts | 1 + .../utils/wallets/welldone/WelldoneWallet.ts | 151 ++++++++++++++ .../src/utils/wallets/welldone/index.ts | 1 + .../src/utils/wallets/welldone/welldone.d.ts | 16 ++ 8 files changed, 366 insertions(+), 1 deletion(-) create mode 100644 packages/wallet-ts/src/strategies/wallet-strategy/strategies/Welldone.ts create mode 100644 packages/wallet-ts/src/utils/wallets/welldone/WelldoneWallet.ts create mode 100644 packages/wallet-ts/src/utils/wallets/welldone/index.ts create mode 100644 packages/wallet-ts/src/utils/wallets/welldone/welldone.d.ts diff --git a/packages/wallet-ts/src/strategies/wallet-strategy/WalletStrategy.ts b/packages/wallet-ts/src/strategies/wallet-strategy/WalletStrategy.ts index 14656a638..f35e179f5 100644 --- a/packages/wallet-ts/src/strategies/wallet-strategy/WalletStrategy.ts +++ b/packages/wallet-ts/src/strategies/wallet-strategy/WalletStrategy.ts @@ -22,6 +22,7 @@ import LedgerLive from './strategies/Ledger/LedgerLive' import LedgerLegacy from './strategies/Ledger/LedgerLegacy' import Torus from './strategies/Torus' import Cosmostation from './strategies/Cosmostation' +import Welldone from './strategies/Welldone' import { Wallet, WalletDeviceType } from '../../types/enums' import { isEthWallet } from './utils' import { isCosmosWallet } from '../../utils/wallets/cosmos' @@ -97,6 +98,8 @@ const createStrategy = ({ return new Cosmostation({ ...args }) case Wallet.Leap: return new Leap({ ...args }) + case Wallet.Welldone: + return new Welldone({ ...args }) default: return undefined } diff --git a/packages/wallet-ts/src/strategies/wallet-strategy/strategies/Welldone.ts b/packages/wallet-ts/src/strategies/wallet-strategy/strategies/Welldone.ts new file mode 100644 index 000000000..f8b032de1 --- /dev/null +++ b/packages/wallet-ts/src/strategies/wallet-strategy/strategies/Welldone.ts @@ -0,0 +1,188 @@ +/* eslint-disable class-methods-use-this */ +import { + ChainId, + CosmosChainId, + AccountAddress, + EthereumChainId, +} from '@injectivelabs/ts-types' +import { + TxRaw, + TxResponse, + createTxRawFromSigResponse, + createCosmosSignDocFromSignDoc, + createSignDocFromTransaction, +} from '@injectivelabs/sdk-ts' +import type { DirectSignResponse } from '@cosmjs/proto-signing' +import { + ErrorType, + TransactionException, + UnspecifiedErrorCode, + CosmosWalletException, +} from '@injectivelabs/exceptions' +import { ConcreteWalletStrategy } from '../../types' +import BaseConcreteStrategy from './Base' +import { WalletAction, WalletDeviceType } from '../../../types/enums' +import { WelldoneWallet } from '../../../utils/wallets/welldone' + +export default class Welldone + extends BaseConcreteStrategy + implements ConcreteWalletStrategy +{ + private welldoneWallet: WelldoneWallet + + constructor(args: { chainId: ChainId }) { + super(args) + this.chainId = args.chainId || CosmosChainId.Injective + this.welldoneWallet = new WelldoneWallet(args.chainId) + } + + async getWalletDeviceType(): Promise { + return Promise.resolve(WalletDeviceType.Browser) + } + + async getAddresses(): Promise { + const welldoneWallet = this.getWelldoneWallet() + + try { + const accounts = await welldoneWallet.getAccounts() + return [accounts.address] + } catch (e: unknown) { + throw new CosmosWalletException(new Error((e as any).message), { + code: UnspecifiedErrorCode, + type: ErrorType.WalletError, + context: WalletAction.GetAccounts, + }) + } + } + + async confirm(address: AccountAddress): Promise { + return Promise.resolve( + `0x${Buffer.from( + `Confirmation for ${address} at time: ${Date.now()}`, + ).toString('hex')}`, + ) + } + + // eslint-disable-next-line class-methods-use-this + async sendEthereumTransaction( + _transaction: unknown, + _options: { address: AccountAddress; ethereumChainId: EthereumChainId }, + ): Promise { + throw new CosmosWalletException( + new Error( + 'sendEthereumTransaction is not supported. WELLDONE only supports sending cosmos transactions', + ), + { + code: UnspecifiedErrorCode, + context: WalletAction.SendEthereumTransaction, + }, + ) + } + + async sendTransaction( + transaction: DirectSignResponse | TxRaw, + _options: { address: AccountAddress; chainId: ChainId }, + ): Promise { + const { welldoneWallet } = this + const txRaw = createTxRawFromSigResponse(transaction) + + try { + return await welldoneWallet.waitTxBroadcasted( + await welldoneWallet.broadcastTx(txRaw), + ) + } catch (e: unknown) { + throw new TransactionException(new Error((e as any).message), { + code: UnspecifiedErrorCode, + context: WalletAction.SendTransaction, + }) + } + } + + /** @deprecated */ + async signTransaction( + transaction: { txRaw: TxRaw; accountNumber: number; chainId: string }, + injectiveAddress: AccountAddress, + ) { + return this.signCosmosTransaction({ + ...transaction, + address: injectiveAddress, + }) + } + + async signCosmosTransaction(transaction: { + txRaw: TxRaw + accountNumber: number + chainId: string + address: string + }): Promise { + const welldoneWallet = this.getWelldoneWallet() + const signDoc = createSignDocFromTransaction(transaction) + try { + const result = await welldoneWallet.signTransaction( + createCosmosSignDocFromSignDoc(signDoc), + ) + return result + } catch (e: unknown) { + throw new CosmosWalletException(new Error((e as any).message), { + code: UnspecifiedErrorCode, + context: WalletAction.SendTransaction, + }) + } + } + + async signEip712TypedData( + _transaction: string, + _address: AccountAddress, + ): Promise { + throw new CosmosWalletException( + new Error( + 'WELLDONE wallet does not support signing Ethereum transactions', + ), + { + code: UnspecifiedErrorCode, + context: WalletAction.SendTransaction, + }, + ) + } + + async getEthereumChainId(): Promise { + throw new CosmosWalletException( + new Error('getEthereumChainId is not supported on WELLDONE Wallet'), + { + code: UnspecifiedErrorCode, + context: WalletAction.GetChainId, + }, + ) + } + + async getEthereumTransactionReceipt(_txHash: string): Promise { + throw new CosmosWalletException( + new Error( + 'getEthereumTransactionReceipt is not supported on WELLDONE Wallet', + ), + { + code: UnspecifiedErrorCode, + context: WalletAction.GetEthereumTransactionReceipt, + }, + ) + } + + async getPubKey(): Promise { + const welldoneWallet = this.getWelldoneWallet() + const key = await welldoneWallet.getKey() + + return Buffer.from(key.replace('0x', ''), 'hex').toString('base64') + } + + private getWelldoneWallet(): WelldoneWallet { + const { welldoneWallet } = this + + if (!welldoneWallet) { + throw new CosmosWalletException( + new Error('Please install the WELLDONE wallet extension'), + ) + } + + return welldoneWallet + } +} diff --git a/packages/wallet-ts/src/types/enums.ts b/packages/wallet-ts/src/types/enums.ts index b79fba631..7234eb330 100644 --- a/packages/wallet-ts/src/types/enums.ts +++ b/packages/wallet-ts/src/types/enums.ts @@ -11,6 +11,7 @@ export enum Wallet { Leap = 'leap', Cosmostation = 'cosmostation', CosmostationEth = 'cosmostation-eth', + Welldone = 'welldone', } export enum WalletDeviceType { diff --git a/packages/wallet-ts/src/utils/wallets/cosmos/utils.ts b/packages/wallet-ts/src/utils/wallets/cosmos/utils.ts index 1dacb4fa0..60968af2b 100644 --- a/packages/wallet-ts/src/utils/wallets/cosmos/utils.ts +++ b/packages/wallet-ts/src/utils/wallets/cosmos/utils.ts @@ -2,6 +2,7 @@ import { DEFAULT_TIMESTAMP_TIMEOUT_MS } from '@injectivelabs/utils' import { Cosmos } from '@cosmostation/extension-client' import type { Keplr } from '@keplr-wallet/types' import { Wallet } from '../../../types/enums' +import { WalletProvider } from '../welldone/welldone' /** * Returns a timeout timestamp in milliseconds so its compatible @@ -26,13 +27,14 @@ export const makeTimeoutTimestampInNs = ( ) => makeTimeoutTimestamp(timeoutInMs) * 1e6 export const isCosmosWallet = (wallet: Wallet): boolean => - [Wallet.Cosmostation, Wallet.Leap, Wallet.Keplr].includes(wallet) + [Wallet.Cosmostation, Wallet.Leap, Wallet.Keplr, Wallet.Welldone].includes(wallet) export const isCosmosWalletInstalled = (wallet: Wallet) => { const $window = (typeof window !== 'undefined' ? window : {}) as Window & { leap?: Keplr keplr?: Keplr cosmostation?: Cosmos + dapp?: WalletProvider } switch (wallet) { @@ -42,6 +44,8 @@ export const isCosmosWalletInstalled = (wallet: Wallet) => { return $window.cosmostation !== undefined case Wallet.Leap: return $window.leap !== undefined + case Wallet.Welldone: + return $window.dapp !== undefined default: return false } diff --git a/packages/wallet-ts/src/utils/wallets/index.ts b/packages/wallet-ts/src/utils/wallets/index.ts index 474367efb..57c000ea6 100644 --- a/packages/wallet-ts/src/utils/wallets/index.ts +++ b/packages/wallet-ts/src/utils/wallets/index.ts @@ -2,3 +2,4 @@ export * from './keplr' export * from './leap' export * from './phantom' export * from './metamask' +export * from './welldone' diff --git a/packages/wallet-ts/src/utils/wallets/welldone/WelldoneWallet.ts b/packages/wallet-ts/src/utils/wallets/welldone/WelldoneWallet.ts new file mode 100644 index 000000000..58e20eac7 --- /dev/null +++ b/packages/wallet-ts/src/utils/wallets/welldone/WelldoneWallet.ts @@ -0,0 +1,151 @@ +/* eslint-disable class-methods-use-this */ +import { + ChainId, + CosmosChainId, + TestnetCosmosChainId, +} from '@injectivelabs/ts-types' +import { TxResponse, TxRestApi, CosmosTxV1Beta1Tx } from '@injectivelabs/sdk-ts' +import { DirectSignResponse, makeSignBytes } from '@cosmjs/proto-signing' +import { encodeSecp256k1Pubkey } from '@cosmjs/amino' +import { + ErrorType, + UnspecifiedErrorCode, + CosmosWalletException, + WalletErrorActionModule, +} from '@injectivelabs/exceptions' +import { getEndpointsFromChainId } from '../cosmos/endpoints' +import { WalletProvider } from './welldone' + +const $window = (typeof window !== 'undefined' ? window : {}) as Window & { + dapp?: WalletProvider +} + +export class WelldoneWallet { + private chainId: CosmosChainId | TestnetCosmosChainId | ChainId + + constructor(chainId: CosmosChainId | TestnetCosmosChainId | ChainId) { + this.chainId = chainId + } + + async getAccounts(): Promise<{ address: string; pubKey: string }> { + const welldone = this.getWelldone() + try { + const accounts = await welldone.request('injective', { + method: 'dapp:accounts', + }) + if (Object.keys(accounts).length === 0) { + throw new Error( + 'Please make the Injective account in the WELLDONE wallet', + ) + } + return accounts.injective + } catch (e: unknown) { + throw new CosmosWalletException(new Error((e as any).message), { + contextModule: WalletErrorActionModule.GetAccounts, + }) + } + } + + public async broadcastTx(txRaw: CosmosTxV1Beta1Tx.TxRaw): Promise { + const welldone = await this.getWelldone() + try { + const serializedTx = Buffer.from( + CosmosTxV1Beta1Tx.TxRaw.encode(txRaw).finish(), + ).toString('base64') + + const hash = await welldone.request('injective', { + method: 'dapp:sendSignedTransaction', + params: [`0x${serializedTx}`], + }) + + return hash + } catch (e) { + throw new CosmosWalletException(new Error((e as any).message), { + context: 'WELLDONE', + contextModule: 'bradcast-tx', + }) + } + } + + public async waitTxBroadcasted(txHash: string): Promise { + const endpoints = await this.getChainEndpoints() + + return new TxRestApi(endpoints.rest).fetchTxPoll(txHash) + } + + public async signTransaction( + signDoc: Omit & { + accountNumber: Long + }, + ): Promise { + const welldone = await this.getWelldone() + try { + const signBytes = makeSignBytes(signDoc) + const response = await welldone.request('injective', { + method: 'dapp:signTransaction', + params: [`0x${Buffer.from(signBytes).toString('hex')}`], + }) + return { + signed: signDoc, + signature: { + pub_key: encodeSecp256k1Pubkey( + Buffer.from(response.publicKey.replace('0x', ''), 'hex'), + ), + signature: Buffer.from( + response.signature.replace('0x', ''), + 'hex', + ).toString('base64'), + }, + } + } catch (e) { + throw new CosmosWalletException(new Error((e as any).message), { + context: 'WELLDONE', + contextModule: 'sign-tx', + }) + } + } + + public async getKey() { + const account = await this.getAccounts() + return account.pubKey + } + + public async getChainEndpoints(): Promise<{ rpc: string; rest: string }> { + const { chainId } = this + + try { + return getEndpointsFromChainId(chainId) + } catch (e: unknown) { + throw new CosmosWalletException(new Error((e as any).message), { + context: 'Keplr', + contextModule: 'get-chain-endpoints', + }) + } + } + + private getWelldone() { + if (!$window) { + throw new CosmosWalletException( + new Error('Please install WELLDONE extension'), + { + code: UnspecifiedErrorCode, + type: ErrorType.WalletNotInstalledError, + context: 'WELLDONE', + }, + ) + } + + if (!$window.dapp) { + throw new CosmosWalletException( + new Error('Please install WELLDONE extension'), + { + code: UnspecifiedErrorCode, + type: ErrorType.WalletNotInstalledError, + context: 'WELLDONE', + }, + ) + } + + return $window.dapp! + } +} diff --git a/packages/wallet-ts/src/utils/wallets/welldone/index.ts b/packages/wallet-ts/src/utils/wallets/welldone/index.ts new file mode 100644 index 000000000..00d928573 --- /dev/null +++ b/packages/wallet-ts/src/utils/wallets/welldone/index.ts @@ -0,0 +1 @@ +export * from './WelldoneWallet' diff --git a/packages/wallet-ts/src/utils/wallets/welldone/welldone.d.ts b/packages/wallet-ts/src/utils/wallets/welldone/welldone.d.ts new file mode 100644 index 000000000..1e06cc891 --- /dev/null +++ b/packages/wallet-ts/src/utils/wallets/welldone/welldone.d.ts @@ -0,0 +1,16 @@ +interface RequestParams { + jsonrpc?: '2.0' + id?: number + method: string + params?: object +} + +export interface WalletProvider { + request: (chainId: string, args: RequestParams) => Promise +} + +declare global { + interface Window { + dapp: WalletProvider + } +} From 2002ea88e09f6e66169566eea54cb9e9d1a306e5 Mon Sep 17 00:00:00 2001 From: Yoon-Suji Date: Fri, 28 Apr 2023 00:01:50 +0200 Subject: [PATCH 2/9] fix: broadcastTx, signTx in WelldoneWallet --- .../utils/wallets/welldone/WelldoneWallet.ts | 20 ++++++------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/packages/wallet-ts/src/utils/wallets/welldone/WelldoneWallet.ts b/packages/wallet-ts/src/utils/wallets/welldone/WelldoneWallet.ts index 58e20eac7..e7956732a 100644 --- a/packages/wallet-ts/src/utils/wallets/welldone/WelldoneWallet.ts +++ b/packages/wallet-ts/src/utils/wallets/welldone/WelldoneWallet.ts @@ -47,18 +47,10 @@ export class WelldoneWallet { } public async broadcastTx(txRaw: CosmosTxV1Beta1Tx.TxRaw): Promise { - const welldone = await this.getWelldone() try { - const serializedTx = Buffer.from( - CosmosTxV1Beta1Tx.TxRaw.encode(txRaw).finish(), - ).toString('base64') - - const hash = await welldone.request('injective', { - method: 'dapp:sendSignedTransaction', - params: [`0x${serializedTx}`], - }) - - return hash + const endpoints = await this.getChainEndpoints() + const { txHash } = await new TxRestApi(endpoints.rest).broadcast(txRaw) + return txHash } catch (e) { throw new CosmosWalletException(new Error((e as any).message), { context: 'WELLDONE', @@ -89,10 +81,10 @@ export class WelldoneWallet { signed: signDoc, signature: { pub_key: encodeSecp256k1Pubkey( - Buffer.from(response.publicKey.replace('0x', ''), 'hex'), + Buffer.from(response[0].publicKey.replace('0x', ''), 'hex'), ), signature: Buffer.from( - response.signature.replace('0x', ''), + response[0].signature.replace('0x', ''), 'hex', ).toString('base64'), }, @@ -117,7 +109,7 @@ export class WelldoneWallet { return getEndpointsFromChainId(chainId) } catch (e: unknown) { throw new CosmosWalletException(new Error((e as any).message), { - context: 'Keplr', + context: 'WELLDONE', contextModule: 'get-chain-endpoints', }) } From 33336d2528cb41d5ad0c01e123357abf7de6028a Mon Sep 17 00:00:00 2001 From: Yoon-Suji Date: Mon, 1 May 2023 20:57:24 +0200 Subject: [PATCH 3/9] feat: add WELLLDONE wallet to CosmosWalletStrategy --- .../strategies/Welldone.ts | 124 ++++++++++++++++++ .../utils/wallets/welldone/WelldoneWallet.ts | 71 ++++++++-- .../src/utils/wallets/welldone/welldone.d.ts | 1 + 3 files changed, 187 insertions(+), 9 deletions(-) create mode 100644 packages/wallet-ts/src/strategies/cosmos-wallet-strategy/strategies/Welldone.ts diff --git a/packages/wallet-ts/src/strategies/cosmos-wallet-strategy/strategies/Welldone.ts b/packages/wallet-ts/src/strategies/cosmos-wallet-strategy/strategies/Welldone.ts new file mode 100644 index 000000000..a4f7909d5 --- /dev/null +++ b/packages/wallet-ts/src/strategies/cosmos-wallet-strategy/strategies/Welldone.ts @@ -0,0 +1,124 @@ +/* eslint-disable class-methods-use-this */ +import { CosmosChainId } from '@injectivelabs/ts-types' +import { + TxRaw, + TxResponse, + createTxRawFromSigResponse, + createCosmosSignDocFromSignDoc, + createSignDocFromTransaction, +} from '@injectivelabs/sdk-ts' +import type { DirectSignResponse } from '@cosmjs/proto-signing' +import { + ErrorType, + TransactionException, + UnspecifiedErrorCode, + CosmosWalletException, +} from '@injectivelabs/exceptions' +import { AminoSignResponse, StdSignDoc } from '@cosmjs/launchpad' +import { ConcreteCosmosWalletStrategy } from '../../types/strategy' +import { WalletAction, WalletDeviceType } from '../../../types/enums' +import { WelldoneWallet } from '../../../../src/utils/wallets' + +export default class Welldone implements ConcreteCosmosWalletStrategy { + public chainId: CosmosChainId + + private welldoneWallet: WelldoneWallet + + constructor(args: { chainId: CosmosChainId }) { + this.chainId = args.chainId || CosmosChainId.Injective + this.welldoneWallet = new WelldoneWallet(args.chainId) + } + + async getWalletDeviceType(): Promise { + return Promise.resolve(WalletDeviceType.Browser) + } + + async isChainIdSupported(chainId?: CosmosChainId): Promise { + const welldoneWallet = chainId + ? new WelldoneWallet(chainId) + : this.getWelldoneWallet() + return welldoneWallet.checkChainIdSupport() + } + + async getAddresses(): Promise { + const welldoneWallet = this.getWelldoneWallet() + + try { + const accounts = await welldoneWallet.getAccounts() + return [accounts.address] + } catch (e: unknown) { + throw new CosmosWalletException(new Error((e as any).message), { + code: UnspecifiedErrorCode, + type: ErrorType.WalletError, + context: WalletAction.GetAccounts, + }) + } + } + + async sendTransaction( + transaction: DirectSignResponse | TxRaw, + ): Promise { + const { welldoneWallet } = this + const txRaw = createTxRawFromSigResponse(transaction) + + try { + return await welldoneWallet.waitTxBroadcasted( + await welldoneWallet.broadcastTx(txRaw), + ) + } catch (e: unknown) { + throw new TransactionException(new Error((e as any).message), { + code: UnspecifiedErrorCode, + context: WalletAction.SendTransaction, + }) + } + } + + async signTransaction(transaction: { + txRaw: TxRaw + chainId: string + accountNumber: number + address: string + }): Promise { + const welldoneWallet = this.getWelldoneWallet() + const signDoc = createSignDocFromTransaction(transaction) + try { + const result = await welldoneWallet.signTransaction( + createCosmosSignDocFromSignDoc(signDoc), + ) + return result + } catch (e: unknown) { + throw new CosmosWalletException(new Error((e as any).message), { + code: UnspecifiedErrorCode, + context: WalletAction.SendTransaction, + }) + } + } + + async signAminoTransaction(_transaction: { + address: string + stdSignDoc: StdSignDoc + }): Promise { + throw new CosmosWalletException( + new Error('signAminoTransaction not supported on WELLDONE wallet'), + ) + } + + async getPubKey(): Promise { + const welldoneWallet = this.getWelldoneWallet() + const key = await welldoneWallet.getKey() + + return Buffer.from(key.replace('0x', ''), 'hex').toString('base64') + } + + private getWelldoneWallet(): WelldoneWallet { + const { welldoneWallet } = this + + if (!welldoneWallet) { + throw new CosmosWalletException( + new Error('Please install the WELLDONE wallet extension'), + ) + } + + return welldoneWallet + } +} diff --git a/packages/wallet-ts/src/utils/wallets/welldone/WelldoneWallet.ts b/packages/wallet-ts/src/utils/wallets/welldone/WelldoneWallet.ts index e7956732a..80bb0eed2 100644 --- a/packages/wallet-ts/src/utils/wallets/welldone/WelldoneWallet.ts +++ b/packages/wallet-ts/src/utils/wallets/welldone/WelldoneWallet.ts @@ -23,22 +23,25 @@ const $window = (typeof window !== 'undefined' ? window : {}) as Window & { export class WelldoneWallet { private chainId: CosmosChainId | TestnetCosmosChainId | ChainId + private chainName: string + constructor(chainId: CosmosChainId | TestnetCosmosChainId | ChainId) { this.chainId = chainId + this.chainName = chainId.split('-')[0] } async getAccounts(): Promise<{ address: string; pubKey: string }> { - const welldone = this.getWelldone() + const welldone = await this.getWelldoneWallet() try { - const accounts = await welldone.request('injective', { + const accounts = await welldone.request(this.chainName, { method: 'dapp:accounts', }) if (Object.keys(accounts).length === 0) { throw new Error( - 'Please make the Injective account in the WELLDONE wallet', + `Please make the ${this.chainName} account in the WELLDONE wallet`, ) } - return accounts.injective + return accounts[this.chainName] } catch (e: unknown) { throw new CosmosWalletException(new Error((e as any).message), { contextModule: WalletErrorActionModule.GetAccounts, @@ -47,10 +50,17 @@ export class WelldoneWallet { } public async broadcastTx(txRaw: CosmosTxV1Beta1Tx.TxRaw): Promise { + const welldone = await this.getWelldoneWallet() try { - const endpoints = await this.getChainEndpoints() - const { txHash } = await new TxRestApi(endpoints.rest).broadcast(txRaw) - return txHash + const { txhash } = await welldone.request(this.chainName, { + method: 'dapp:sendSignedTransaction', + params: [ + `0x${Buffer.from( + CosmosTxV1Beta1Tx.TxRaw.encode(txRaw).finish(), + ).toString('hex')}`, + ], + }) + return txhash } catch (e) { throw new CosmosWalletException(new Error((e as any).message), { context: 'WELLDONE', @@ -70,10 +80,10 @@ export class WelldoneWallet { accountNumber: Long }, ): Promise { - const welldone = await this.getWelldone() + const welldone = await this.getWelldoneWallet() try { const signBytes = makeSignBytes(signDoc) - const response = await welldone.request('injective', { + const response = await welldone.request(this.chainName, { method: 'dapp:signTransaction', params: [`0x${Buffer.from(signBytes).toString('hex')}`], }) @@ -115,6 +125,49 @@ export class WelldoneWallet { } } + // WELLDONE Wallet only supports injective, cosmos, juno netoworks. + public async checkChainIdSupport() { + const { chainId } = this + if (chainId.includes('cosmoshub') || chainId.includes('juno')) { + return true + } + return false + } + + private async checkNetwork() { + const welldone = this.getWelldone() + try { + if (this.chainName !== 'injective') { + const { node_info } = await welldone.request(this.chainName, { + method: 'status', + }) + if (node_info.network === this.chainId) return true + } else { + const { injective } = await welldone.networks + const network = + injective.chain === 'injective' ? ChainId.Mainnet : ChainId.Testnet + if (network === this.chainId) { + return true + } + } + } catch (e) { + throw new CosmosWalletException(new Error((e as any).message), { + context: 'WELLDONE', + contextModule: 'check-network', + }) + } + return false + } + + public async getWelldoneWallet() { + const { chainId } = this + const welldone = this.getWelldone() + if (!(await this.checkNetwork())) { + throw new Error(`Change the WELLDONE Wallet Network to ${chainId}`) + } + return welldone + } + private getWelldone() { if (!$window) { throw new CosmosWalletException( diff --git a/packages/wallet-ts/src/utils/wallets/welldone/welldone.d.ts b/packages/wallet-ts/src/utils/wallets/welldone/welldone.d.ts index 1e06cc891..4de733f97 100644 --- a/packages/wallet-ts/src/utils/wallets/welldone/welldone.d.ts +++ b/packages/wallet-ts/src/utils/wallets/welldone/welldone.d.ts @@ -7,6 +7,7 @@ interface RequestParams { export interface WalletProvider { request: (chainId: string, args: RequestParams) => Promise + networks: any } declare global { From a8fe17cb2051c5a69b2c2e5472d68ed67ef601c3 Mon Sep 17 00:00:00 2001 From: Yoon-Suji Date: Tue, 16 May 2023 13:54:22 +0200 Subject: [PATCH 4/9] fix: modify public key type for welldone wallet --- .../utils/wallets/welldone/WelldoneWallet.ts | 49 ++++++++++--------- 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/packages/wallet-ts/src/utils/wallets/welldone/WelldoneWallet.ts b/packages/wallet-ts/src/utils/wallets/welldone/WelldoneWallet.ts index 80bb0eed2..a5da0efa2 100644 --- a/packages/wallet-ts/src/utils/wallets/welldone/WelldoneWallet.ts +++ b/packages/wallet-ts/src/utils/wallets/welldone/WelldoneWallet.ts @@ -52,15 +52,15 @@ export class WelldoneWallet { public async broadcastTx(txRaw: CosmosTxV1Beta1Tx.TxRaw): Promise { const welldone = await this.getWelldoneWallet() try { - const { txhash } = await welldone.request(this.chainName, { - method: 'dapp:sendSignedTransaction', - params: [ - `0x${Buffer.from( - CosmosTxV1Beta1Tx.TxRaw.encode(txRaw).finish(), - ).toString('hex')}`, - ], - }) - return txhash + const {hash} = await welldone.request(this.chainName, { + method: 'dapp:sendSignedTransaction', + params: [ + `0x${Buffer.from( + CosmosTxV1Beta1Tx.TxRaw.encode(txRaw).finish(), + ).toString('hex')}`, + ], + }) + return hash } catch (e) { throw new CosmosWalletException(new Error((e as any).message), { context: 'WELLDONE', @@ -75,11 +75,25 @@ export class WelldoneWallet { return new TxRestApi(endpoints.rest).fetchTxPoll(txHash) } + private changePubKeyType (authInfoBytes: Uint8Array) { + const authInfo = CosmosTxV1Beta1Tx.AuthInfo.decode(authInfoBytes) + authInfo.signerInfos.forEach((signerInfo) => { + if (signerInfo.publicKey) { + signerInfo.publicKey.typeUrl = '/cosmos.crypto.secp256k1.PubKey' + } + }) + + return CosmosTxV1Beta1Tx.AuthInfo.encode(authInfo).finish() + } + public async signTransaction( signDoc: Omit & { accountNumber: Long }, ): Promise { + const authInfoBytes = this.changePubKeyType(signDoc.authInfoBytes) + signDoc.authInfoBytes = authInfoBytes + const welldone = await this.getWelldoneWallet() try { const signBytes = makeSignBytes(signDoc) @@ -137,19 +151,10 @@ export class WelldoneWallet { private async checkNetwork() { const welldone = this.getWelldone() try { - if (this.chainName !== 'injective') { - const { node_info } = await welldone.request(this.chainName, { - method: 'status', - }) - if (node_info.network === this.chainId) return true - } else { - const { injective } = await welldone.networks - const network = - injective.chain === 'injective' ? ChainId.Mainnet : ChainId.Testnet - if (network === this.chainId) { - return true - } - } + const { node_info } = await welldone.request(this.chainName, { + method: 'status', + }) + if (node_info.network === this.chainId) return true } catch (e) { throw new CosmosWalletException(new Error((e as any).message), { context: 'WELLDONE', From e6585e3c0140f6846773e03faf6114a559badc47 Mon Sep 17 00:00:00 2001 From: Yoon-Suji Date: Thu, 18 May 2023 10:36:02 +0200 Subject: [PATCH 5/9] fix: linting --- .../strategies/Welldone.ts | 4 ++ .../wallet-strategy/strategies/Welldone.ts | 3 ++ .../utils/wallets/welldone/WelldoneWallet.ts | 44 ++++++++++++------- 3 files changed, 35 insertions(+), 16 deletions(-) diff --git a/packages/wallet-ts/src/strategies/cosmos-wallet-strategy/strategies/Welldone.ts b/packages/wallet-ts/src/strategies/cosmos-wallet-strategy/strategies/Welldone.ts index a4f7909d5..ded0237bc 100644 --- a/packages/wallet-ts/src/strategies/cosmos-wallet-strategy/strategies/Welldone.ts +++ b/packages/wallet-ts/src/strategies/cosmos-wallet-strategy/strategies/Welldone.ts @@ -37,6 +37,7 @@ export default class Welldone implements ConcreteCosmosWalletStrategy { const welldoneWallet = chainId ? new WelldoneWallet(chainId) : this.getWelldoneWallet() + return welldoneWallet.checkChainIdSupport() } @@ -45,6 +46,7 @@ export default class Welldone implements ConcreteCosmosWalletStrategy { try { const accounts = await welldoneWallet.getAccounts() + return [accounts.address] } catch (e: unknown) { throw new CosmosWalletException(new Error((e as any).message), { @@ -81,10 +83,12 @@ export default class Welldone implements ConcreteCosmosWalletStrategy { }): Promise { const welldoneWallet = this.getWelldoneWallet() const signDoc = createSignDocFromTransaction(transaction) + try { const result = await welldoneWallet.signTransaction( createCosmosSignDocFromSignDoc(signDoc), ) + return result } catch (e: unknown) { throw new CosmosWalletException(new Error((e as any).message), { diff --git a/packages/wallet-ts/src/strategies/wallet-strategy/strategies/Welldone.ts b/packages/wallet-ts/src/strategies/wallet-strategy/strategies/Welldone.ts index f8b032de1..844228fe8 100644 --- a/packages/wallet-ts/src/strategies/wallet-strategy/strategies/Welldone.ts +++ b/packages/wallet-ts/src/strategies/wallet-strategy/strategies/Welldone.ts @@ -45,6 +45,7 @@ export default class Welldone try { const accounts = await welldoneWallet.getAccounts() + return [accounts.address] } catch (e: unknown) { throw new CosmosWalletException(new Error((e as any).message), { @@ -117,10 +118,12 @@ export default class Welldone }): Promise { const welldoneWallet = this.getWelldoneWallet() const signDoc = createSignDocFromTransaction(transaction) + try { const result = await welldoneWallet.signTransaction( createCosmosSignDocFromSignDoc(signDoc), ) + return result } catch (e: unknown) { throw new CosmosWalletException(new Error((e as any).message), { diff --git a/packages/wallet-ts/src/utils/wallets/welldone/WelldoneWallet.ts b/packages/wallet-ts/src/utils/wallets/welldone/WelldoneWallet.ts index a5da0efa2..945632d15 100644 --- a/packages/wallet-ts/src/utils/wallets/welldone/WelldoneWallet.ts +++ b/packages/wallet-ts/src/utils/wallets/welldone/WelldoneWallet.ts @@ -32,15 +32,18 @@ export class WelldoneWallet { async getAccounts(): Promise<{ address: string; pubKey: string }> { const welldone = await this.getWelldoneWallet() + try { const accounts = await welldone.request(this.chainName, { method: 'dapp:accounts', }) + if (Object.keys(accounts).length === 0) { throw new Error( `Please make the ${this.chainName} account in the WELLDONE wallet`, ) } + return accounts[this.chainName] } catch (e: unknown) { throw new CosmosWalletException(new Error((e as any).message), { @@ -51,16 +54,18 @@ export class WelldoneWallet { public async broadcastTx(txRaw: CosmosTxV1Beta1Tx.TxRaw): Promise { const welldone = await this.getWelldoneWallet() + try { - const {hash} = await welldone.request(this.chainName, { - method: 'dapp:sendSignedTransaction', - params: [ - `0x${Buffer.from( - CosmosTxV1Beta1Tx.TxRaw.encode(txRaw).finish(), - ).toString('hex')}`, - ], - }) - return hash + const { hash } = await welldone.request(this.chainName, { + method: 'dapp:sendSignedTransaction', + params: [ + `0x${Buffer.from( + CosmosTxV1Beta1Tx.TxRaw.encode(txRaw).finish(), + ).toString('hex')}`, + ], + }) + + return hash } catch (e) { throw new CosmosWalletException(new Error((e as any).message), { context: 'WELLDONE', @@ -75,8 +80,9 @@ export class WelldoneWallet { return new TxRestApi(endpoints.rest).fetchTxPoll(txHash) } - private changePubKeyType (authInfoBytes: Uint8Array) { + private changePubKeyType(authInfoBytes: Uint8Array) { const authInfo = CosmosTxV1Beta1Tx.AuthInfo.decode(authInfoBytes) + authInfo.signerInfos.forEach((signerInfo) => { if (signerInfo.publicKey) { signerInfo.publicKey.typeUrl = '/cosmos.crypto.secp256k1.PubKey' @@ -95,12 +101,14 @@ export class WelldoneWallet { signDoc.authInfoBytes = authInfoBytes const welldone = await this.getWelldoneWallet() + try { const signBytes = makeSignBytes(signDoc) const response = await welldone.request(this.chainName, { method: 'dapp:signTransaction', params: [`0x${Buffer.from(signBytes).toString('hex')}`], }) + return { signed: signDoc, signature: { @@ -123,6 +131,7 @@ export class WelldoneWallet { public async getKey() { const account = await this.getAccounts() + return account.pubKey } @@ -142,34 +151,37 @@ export class WelldoneWallet { // WELLDONE Wallet only supports injective, cosmos, juno netoworks. public async checkChainIdSupport() { const { chainId } = this - if (chainId.includes('cosmoshub') || chainId.includes('juno')) { - return true - } - return false + + return ['injective', 'cosmoshub', 'juno'].some((cosmosChainId) => + chainId.includes(cosmosChainId), + ) } private async checkNetwork() { const welldone = this.getWelldone() + try { const { node_info } = await welldone.request(this.chainName, { method: 'status', }) - if (node_info.network === this.chainId) return true + + return node_info.network === this.chainId } catch (e) { throw new CosmosWalletException(new Error((e as any).message), { context: 'WELLDONE', contextModule: 'check-network', }) } - return false } public async getWelldoneWallet() { const { chainId } = this const welldone = this.getWelldone() + if (!(await this.checkNetwork())) { throw new Error(`Change the WELLDONE Wallet Network to ${chainId}`) } + return welldone } From 905321727a2bd73b65b69da124f857b03d35f856 Mon Sep 17 00:00:00 2001 From: Yoon-Suji Date: Fri, 19 May 2023 12:52:41 +0200 Subject: [PATCH 6/9] fix: signTransaction return pub_key in WELLDONE Wallet --- .../src/utils/wallets/welldone/WelldoneWallet.ts | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/packages/wallet-ts/src/utils/wallets/welldone/WelldoneWallet.ts b/packages/wallet-ts/src/utils/wallets/welldone/WelldoneWallet.ts index 945632d15..9b0f97b21 100644 --- a/packages/wallet-ts/src/utils/wallets/welldone/WelldoneWallet.ts +++ b/packages/wallet-ts/src/utils/wallets/welldone/WelldoneWallet.ts @@ -4,9 +4,13 @@ import { CosmosChainId, TestnetCosmosChainId, } from '@injectivelabs/ts-types' -import { TxResponse, TxRestApi, CosmosTxV1Beta1Tx } from '@injectivelabs/sdk-ts' +import { + TxResponse, + TxRestApi, + CosmosTxV1Beta1Tx, + getPublicKey, +} from '@injectivelabs/sdk-ts' import { DirectSignResponse, makeSignBytes } from '@cosmjs/proto-signing' -import { encodeSecp256k1Pubkey } from '@cosmjs/amino' import { ErrorType, UnspecifiedErrorCode, @@ -108,13 +112,15 @@ export class WelldoneWallet { method: 'dapp:signTransaction', params: [`0x${Buffer.from(signBytes).toString('hex')}`], }) + const pubKey = getPublicKey({ + chainId: this.chainId, + key: Buffer.from(response[0].publicKey.replace('0x', ''), 'hex').toString('base64'), + }) return { signed: signDoc, signature: { - pub_key: encodeSecp256k1Pubkey( - Buffer.from(response[0].publicKey.replace('0x', ''), 'hex'), - ), + pub_key: pubKey as any, signature: Buffer.from( response[0].signature.replace('0x', ''), 'hex', From 49fee04d53dbc3f66e238587adac01aeb44c1100 Mon Sep 17 00:00:00 2001 From: daoauth <57783762+daoauth@users.noreply.github.com> Date: Mon, 8 Jan 2024 13:37:59 +0900 Subject: [PATCH 7/9] update welldone wallet --- .../strategies/Welldone.ts | 5 +++++ .../wallet-strategy/strategies/Welldone.ts | 18 ++++++++++++++++++ .../utils/wallets/welldone/WelldoneWallet.ts | 5 +++++ 3 files changed, 28 insertions(+) diff --git a/packages/wallet-ts/src/strategies/cosmos-wallet-strategy/strategies/Welldone.ts b/packages/wallet-ts/src/strategies/cosmos-wallet-strategy/strategies/Welldone.ts index ded0237bc..508d15e6a 100644 --- a/packages/wallet-ts/src/strategies/cosmos-wallet-strategy/strategies/Welldone.ts +++ b/packages/wallet-ts/src/strategies/cosmos-wallet-strategy/strategies/Welldone.ts @@ -29,6 +29,11 @@ export default class Welldone implements ConcreteCosmosWalletStrategy { this.welldoneWallet = new WelldoneWallet(args.chainId) } + enable(): Promise { + const welldoneWallet = this.getWelldoneWallet(); + return welldoneWallet.enable(); + } + async getWalletDeviceType(): Promise { return Promise.resolve(WalletDeviceType.Browser) } diff --git a/packages/wallet-ts/src/strategies/wallet-strategy/strategies/Welldone.ts b/packages/wallet-ts/src/strategies/wallet-strategy/strategies/Welldone.ts index 844228fe8..4bc3bb83d 100644 --- a/packages/wallet-ts/src/strategies/wallet-strategy/strategies/Welldone.ts +++ b/packages/wallet-ts/src/strategies/wallet-strategy/strategies/Welldone.ts @@ -35,6 +35,24 @@ export default class Welldone this.chainId = args.chainId || CosmosChainId.Injective this.welldoneWallet = new WelldoneWallet(args.chainId) } + signAminoCosmosTransaction(_transaction: { signDoc: any; accountNumber: number; chainId: string; address: string }): Promise { + throw new CosmosWalletException( + new Error('This wallet does not support signing using amino'), + { + code: UnspecifiedErrorCode, + context: WalletAction.SendTransaction, + }, + ) + } + + async signArbitrary(_signer: string, _data: string | Uint8Array): Promise { + throw new Error('Method not implemented.') + } + + async enable(): Promise { + const welldoneWallet = this.getWelldoneWallet(); + return welldoneWallet.enable(); + } async getWalletDeviceType(): Promise { return Promise.resolve(WalletDeviceType.Browser) diff --git a/packages/wallet-ts/src/utils/wallets/welldone/WelldoneWallet.ts b/packages/wallet-ts/src/utils/wallets/welldone/WelldoneWallet.ts index 9b0f97b21..1ae6d0838 100644 --- a/packages/wallet-ts/src/utils/wallets/welldone/WelldoneWallet.ts +++ b/packages/wallet-ts/src/utils/wallets/welldone/WelldoneWallet.ts @@ -34,6 +34,11 @@ export class WelldoneWallet { this.chainName = chainId.split('-')[0] } + async enable(): Promise { + const accounts = await this.getAccounts(); + return accounts && !!accounts.address; + } + async getAccounts(): Promise<{ address: string; pubKey: string }> { const welldone = await this.getWelldoneWallet() From d3dcaa2f4bea065c1db51b531ae8f1cc2b2d711c Mon Sep 17 00:00:00 2001 From: daoauth <57783762+daoauth@users.noreply.github.com> Date: Tue, 9 Jan 2024 11:11:57 +0900 Subject: [PATCH 8/9] Update WelldoneWallet.ts chanage to /injective.crypto.v1beta1.ethsecp256k1.PubKey --- packages/wallet-ts/src/utils/wallets/welldone/WelldoneWallet.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/wallet-ts/src/utils/wallets/welldone/WelldoneWallet.ts b/packages/wallet-ts/src/utils/wallets/welldone/WelldoneWallet.ts index 1ae6d0838..81d06a9b9 100644 --- a/packages/wallet-ts/src/utils/wallets/welldone/WelldoneWallet.ts +++ b/packages/wallet-ts/src/utils/wallets/welldone/WelldoneWallet.ts @@ -94,7 +94,7 @@ export class WelldoneWallet { authInfo.signerInfos.forEach((signerInfo) => { if (signerInfo.publicKey) { - signerInfo.publicKey.typeUrl = '/cosmos.crypto.secp256k1.PubKey' + signerInfo.publicKey.typeUrl = '/injective.crypto.v1beta1.ethsecp256k1.PubKey' } }) From 34d12b446ad626c448ef1b7b94dbf005844e7252 Mon Sep 17 00:00:00 2001 From: daoauth <57783762+daoauth@users.noreply.github.com> Date: Tue, 9 Jan 2024 11:17:45 +0900 Subject: [PATCH 9/9] remove change pubKey type --- .../src/utils/wallets/welldone/WelldoneWallet.ts | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/packages/wallet-ts/src/utils/wallets/welldone/WelldoneWallet.ts b/packages/wallet-ts/src/utils/wallets/welldone/WelldoneWallet.ts index 81d06a9b9..aa5e24403 100644 --- a/packages/wallet-ts/src/utils/wallets/welldone/WelldoneWallet.ts +++ b/packages/wallet-ts/src/utils/wallets/welldone/WelldoneWallet.ts @@ -89,26 +89,11 @@ export class WelldoneWallet { return new TxRestApi(endpoints.rest).fetchTxPoll(txHash) } - private changePubKeyType(authInfoBytes: Uint8Array) { - const authInfo = CosmosTxV1Beta1Tx.AuthInfo.decode(authInfoBytes) - - authInfo.signerInfos.forEach((signerInfo) => { - if (signerInfo.publicKey) { - signerInfo.publicKey.typeUrl = '/injective.crypto.v1beta1.ethsecp256k1.PubKey' - } - }) - - return CosmosTxV1Beta1Tx.AuthInfo.encode(authInfo).finish() - } - public async signTransaction( signDoc: Omit & { accountNumber: Long }, ): Promise { - const authInfoBytes = this.changePubKeyType(signDoc.authInfoBytes) - signDoc.authInfoBytes = authInfoBytes - const welldone = await this.getWelldoneWallet() try {