Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: supporting WELLDONE Wallet in wallet-ts #193

Open
wants to merge 12 commits into
base: dev
Choose a base branch
from
Original file line number Diff line number Diff line change
@@ -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<WalletDeviceType> {
return Promise.resolve(WalletDeviceType.Browser)
}

async isChainIdSupported(chainId?: CosmosChainId): Promise<boolean> {
const welldoneWallet = chainId
? new WelldoneWallet(chainId)
: this.getWelldoneWallet()
return welldoneWallet.checkChainIdSupport()
Yoon-Suji marked this conversation as resolved.
Show resolved Hide resolved
}

async getAddresses(): Promise<string[]> {
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,
Yoon-Suji marked this conversation as resolved.
Show resolved Hide resolved
context: WalletAction.GetAccounts,
})
}
}

async sendTransaction(
transaction: DirectSignResponse | TxRaw,
): Promise<TxResponse> {
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<DirectSignResponse> {
const welldoneWallet = this.getWelldoneWallet()
const signDoc = createSignDocFromTransaction(transaction)
try {
Yoon-Suji marked this conversation as resolved.
Show resolved Hide resolved
const result = await welldoneWallet.signTransaction(
createCosmosSignDocFromSignDoc(signDoc),
)
return result
Yoon-Suji marked this conversation as resolved.
Show resolved Hide resolved
} 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<AminoSignResponse> {
throw new CosmosWalletException(
new Error('signAminoTransaction not supported on WELLDONE wallet'),
)
}

async getPubKey(): Promise<string> {
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
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down Expand Up @@ -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
}
Expand Down
Original file line number Diff line number Diff line change
@@ -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<WalletDeviceType> {
return Promise.resolve(WalletDeviceType.Browser)
}

async getAddresses(): Promise<string[]> {
const welldoneWallet = this.getWelldoneWallet()

try {
const accounts = await welldoneWallet.getAccounts()
return [accounts.address]
Yoon-Suji marked this conversation as resolved.
Show resolved Hide resolved
} 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<string> {
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<string> {
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<TxResponse> {
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<DirectSignResponse> {
const welldoneWallet = this.getWelldoneWallet()
const signDoc = createSignDocFromTransaction(transaction)
try {
Yoon-Suji marked this conversation as resolved.
Show resolved Hide resolved
const result = await welldoneWallet.signTransaction(
createCosmosSignDocFromSignDoc(signDoc),
)
return result
Yoon-Suji marked this conversation as resolved.
Show resolved Hide resolved
} catch (e: unknown) {
throw new CosmosWalletException(new Error((e as any).message), {
code: UnspecifiedErrorCode,
context: WalletAction.SendTransaction,
})
}
}

async signEip712TypedData(
_transaction: string,
_address: AccountAddress,
): Promise<string> {
throw new CosmosWalletException(
new Error(
'WELLDONE wallet does not support signing Ethereum transactions',
),
{
code: UnspecifiedErrorCode,
context: WalletAction.SendTransaction,
},
)
}

async getEthereumChainId(): Promise<string> {
throw new CosmosWalletException(
new Error('getEthereumChainId is not supported on WELLDONE Wallet'),
{
code: UnspecifiedErrorCode,
context: WalletAction.GetChainId,
},
)
}

async getEthereumTransactionReceipt(_txHash: string): Promise<string> {
throw new CosmosWalletException(
new Error(
'getEthereumTransactionReceipt is not supported on WELLDONE Wallet',
),
{
code: UnspecifiedErrorCode,
context: WalletAction.GetEthereumTransactionReceipt,
},
)
}

async getPubKey(): Promise<string> {
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
}
}
1 change: 1 addition & 0 deletions packages/wallet-ts/src/types/enums.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export enum Wallet {
Leap = 'leap',
Cosmostation = 'cosmostation',
CosmostationEth = 'cosmostation-eth',
Welldone = 'welldone',
}

export enum WalletDeviceType {
Expand Down
6 changes: 5 additions & 1 deletion packages/wallet-ts/src/utils/wallets/cosmos/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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) {
Expand All @@ -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
}
Expand Down
1 change: 1 addition & 0 deletions packages/wallet-ts/src/utils/wallets/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ export * from './keplr'
export * from './leap'
export * from './phantom'
export * from './metamask'
export * from './welldone'
Loading