Skip to content

feat: turnkey wallet #552

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

Open
wants to merge 6 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@
},
"resolutions": {
"@solana/web3.js": "1.98.0",
"rpc-websockets": "9.0.4"
"rpc-websockets": "9.0.4",
"next": "file:./etc/noop"
}
}
1 change: 1 addition & 0 deletions packages/exceptions/src/exceptions/types/codes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -817,4 +817,5 @@ export type ErrorContextCode =
| ChainStakingErrorCodes
| ChainWasmErrorCodes
| ErrorCode
| number
| typeof UnspecifiedErrorCode
10 changes: 10 additions & 0 deletions packages/sdk-ts/src/utils/address.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {
getEthereumAddress,
getInjectiveAddress,
getDefaultSubaccountId,
getChecksumAddress,
} from '../../src/utils/index.js'

describe('address helper functions', () => {
Expand Down Expand Up @@ -31,4 +32,13 @@ describe('address helper functions', () => {
'0xaf79152ac5df276d9a8e1e2e22822f9713474902000000000000000000000000',
)
})

it('getChecksumAddress returns correct value', () => {
const ethereumAddress =
'0xaf79152ac5df276d9a8e1e2e22822f9713474902'.toLowerCase()

expect(getChecksumAddress(ethereumAddress)).toMatch(
'0xAF79152AC5dF276D9A8e1E2E22822f9713474902',
)
})
})
4 changes: 3 additions & 1 deletion packages/utils/src/classes/HttpRestClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ const getErrorMessage = (error: any, endpoint: string): string => {
}

return error.response.data
? error.response.data.message || error.response.data
? error.response.data.message ||
error.response.data.statusMessage ||
error.response.data
: error.response.statusText
}

Expand Down
24 changes: 19 additions & 5 deletions packages/wallets/wallet-base/src/base.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import { ChainId, CosmosChainId, EthereumChainId } from '@injectivelabs/ts-types'
import {
ChainId,
CosmosChainId,
EthereumChainId,
} from '@injectivelabs/ts-types'
import {
WalletMetadata,
WalletEventListener,
ConcreteWalletStrategyArgs,
ConcreteCosmosWalletStrategyArgs,
Expand All @@ -13,10 +18,19 @@ export default abstract class BaseConcreteStrategy {

protected listeners: Partial<Record<WalletEventListener, any>> = {}

protected constructor(args: ConcreteWalletStrategyArgs | ConcreteEthereumWalletStrategyArgs | ConcreteCosmosWalletStrategyArgs) {
this.ethereumChainId = 'ethereumOptions' in args && args.ethereumOptions
? args.ethereumOptions.ethereumChainId
: undefined
public metadata?: WalletMetadata

public constructor(
args:
| ConcreteWalletStrategyArgs
| ConcreteEthereumWalletStrategyArgs
| ConcreteCosmosWalletStrategyArgs,
) {
this.ethereumChainId =
'ethereumOptions' in args && args.ethereumOptions
? args.ethereumOptions.ethereumChainId
: undefined
this.chainId = args.chainId
this.metadata = args.metadata
}
}
2 changes: 2 additions & 0 deletions packages/wallets/wallet-base/src/types/enums.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ export enum Wallet {
Phantom = 'phantom',
Metamask = 'metamask',
OkxWallet = 'okx-wallet',
TurnkeyOtp = 'turnkey-otp',
TurnkeyOauth = 'turnkey-oauth',
TrustWallet = 'trust-wallet',
PrivateKey = 'private-key',
TrezorBip32 = 'trezor-bip32',
Expand Down
77 changes: 59 additions & 18 deletions packages/wallets/wallet-base/src/types/strategy.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import {
ChainId,
CosmosChainId,
AccountAddress,
EthereumChainId,
} from '@injectivelabs/ts-types'
Expand Down Expand Up @@ -30,10 +29,13 @@ export type MagicMetadata = {
rpcEndpoint?: string
}

export type WalletConnectMetadata = Record<
string,
string | Record<string, string> | Record<string, string[]>
>
export type PrivateKeyMetadata = {
privateKey: string
}

export type WalletConnectMetadata = {
projectId?: string
}

export interface WalletStrategyEthereumOptions {
ethereumChainId: EthereumChainId
Expand All @@ -51,20 +53,57 @@ export interface SendTransactionOptions {
}
}

export interface ConcreteWalletStrategyOptions {
privateKey?: string
metadata?: Record<string, string | Record<string, string>>
export enum TurnkeyProvider {
Email = 'email',
Google = 'google',
Apple = 'apple',
}

export type TurnkeySession = {
sessionType: any
userId: string
organizationId: string
expiry: number
token: string
}

export interface TurnkeyMetadata {
defaultOrganizationId: string
apiBaseUrl: string
apiServerEndpoint: string
iframeUrl?: string
email?: string
session?: TurnkeySession
otpId?: string
otpCode?: string
oidcToken?: string
iframeElementId?: string
iframeContainerId: string
credentialBundle?: string
organizationId?: string
provider?: TurnkeyProvider
otpInitPath?: string
otpVerifyPath?: string
oauthLoginPath?: string
googleClientId?: string
googleRedirectUri?: string
}

export interface WalletMetadata {
magic?: MagicMetadata
turnkey?: Partial<TurnkeyMetadata>
walletConnect?: WalletConnectMetadata
privateKey?: PrivateKeyMetadata
}

export interface ConcreteWalletStrategyArgs {
chainId: ChainId
options?: ConcreteWalletStrategyOptions
metadata?: WalletMetadata
}

export interface ConcreteCosmosWalletStrategyArgs {
chainId: CosmosChainId | ChainId
export interface ConcreteCosmosWalletStrategyArgs
extends ConcreteWalletStrategyArgs {
wallet?: Wallet
options?: ConcreteWalletStrategyOptions
}

export interface ConcreteEthereumWalletStrategyArgs
Expand All @@ -73,6 +112,9 @@ export interface ConcreteEthereumWalletStrategyArgs
}

export interface ConcreteCosmosWalletStrategy {
metadata?: WalletMetadata

setMetadata?(metadata?: WalletMetadata): void
/**
* The accounts from the wallet (addresses)
*/
Expand Down Expand Up @@ -125,7 +167,7 @@ export type ConcreteStrategiesArg = {

export interface WalletStrategyArguments {
chainId: ChainId
options?: ConcreteWalletStrategyOptions
metadata?: WalletMetadata
ethereumOptions?: WalletStrategyEthereumOptions
disabledWallets?: Wallet[]
wallet?: Wallet
Expand All @@ -135,9 +177,7 @@ export interface WalletStrategyArguments {
export interface ConcreteWalletStrategy
extends Omit<
ConcreteCosmosWalletStrategy,
| 'sendTransaction'
| 'isChainIdSupported'
| 'signAminoTransaction'
'sendTransaction' | 'isChainIdSupported' | 'signAminoTransaction'
> {
/**
* Sends Cosmos transaction. Returns a transaction hash
Expand Down Expand Up @@ -224,10 +264,11 @@ export interface WalletStrategy {
strategies: ConcreteStrategiesArg
wallet: Wallet
args: WalletStrategyArguments
metadata?: WalletMetadata

getWallet(): Wallet
setWallet(wallet: Wallet): void
setOptions(options?: ConcreteWalletStrategyOptions): void
setMetadata(metadata?: WalletMetadata): void
getStrategy(): ConcreteWalletStrategy
getAddresses(args?: unknown): Promise<AccountAddress[]>
getWalletDeviceType(): Promise<WalletDeviceType>
Expand Down Expand Up @@ -269,4 +310,4 @@ export interface WalletStrategy {
getCosmosWallet?(chainId: ChainId): CosmosWalletAbstraction
}

export { StdSignDoc}
export { StdSignDoc }
24 changes: 14 additions & 10 deletions packages/wallets/wallet-base/src/utils/wallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ export const isEvmWallet = (wallet: Wallet): boolean =>
Wallet.Magic,
Wallet.BitGet,
Wallet.Ledger,
Wallet.TrezorBip32,
Wallet.TrezorBip44,
Wallet.Phantom,
Wallet.Metamask,
Wallet.OkxWallet,
Wallet.PrivateKey,
Wallet.TrezorBip32,
Wallet.TurnkeyOtp,
Wallet.TurnkeyOauth,
Wallet.TrezorBip44,
Wallet.TrustWallet,
Wallet.LedgerLegacy,
Wallet.WalletConnect,
Expand All @@ -19,14 +21,16 @@ export const isEvmWallet = (wallet: Wallet): boolean =>

export const isCosmosWallet = (wallet: Wallet): boolean => !isEvmWallet(wallet)

export const isEvmBrowserWallet = (wallet: Wallet) => [
Wallet.BitGet,
Wallet.Phantom,
Wallet.Metamask,
Wallet.OkxWallet,
Wallet.TrustWallet,
].includes(wallet)

export const isEvmBrowserWallet = (wallet: Wallet) =>
[
Wallet.BitGet,
Wallet.Phantom,
Wallet.Metamask,
Wallet.OkxWallet,
Wallet.TrustWallet,
Wallet.TurnkeyOtp,
Wallet.TurnkeyOauth,
].includes(wallet)

export const isCosmosBrowserWallet = (wallet: Wallet): boolean =>
[
Expand Down
14 changes: 11 additions & 3 deletions packages/wallets/wallet-core/src/strategy/BaseWalletStrategy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ import {
ConcreteStrategiesArg,
SendTransactionOptions,
ConcreteWalletStrategy,
type WalletMetadata,
onAccountChangeCallback,
onChainIdChangeCallback,
WalletStrategyArguments,
CosmosWalletAbstraction,
ConcreteWalletStrategyOptions,
WalletStrategy as WalletStrategyInterface,
} from '@injectivelabs/wallet-base'
import { StdSignDoc } from '@keplr-wallet/types'
Expand Down Expand Up @@ -58,12 +58,15 @@ export default class BaseWalletStrategy implements WalletStrategyInterface {

public args: WalletStrategyArguments

public metadata?: WalletMetadata

public wallets?: Wallet[]

constructor(args: WalletStrategyArguments) {
this.args = args
this.strategies = args.strategies
this.wallet = getInitialWallet(args)
this.metadata = args.metadata
}

public getWallet(): Wallet {
Expand All @@ -74,8 +77,13 @@ export default class BaseWalletStrategy implements WalletStrategyInterface {
this.wallet = wallet
}

public setOptions(_options?: ConcreteWalletStrategyOptions) {
//
/**
* When we use setMetadata, we are usually updating the metadata of the
* existing strategy.
*/
public setMetadata(metadata?: WalletMetadata) {
this.metadata = metadata
this.getStrategy().setMetadata?.(metadata)
}

public getStrategy(): ConcreteWalletStrategy {
Expand Down
5 changes: 3 additions & 2 deletions packages/wallets/wallet-cosmos/src/strategy/strategy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export class CosmosWalletStrategy
implements ConcreteWalletStrategy
{
public wallet: Wallet

private cosmosWallet: CosmosWallet

constructor(
Expand All @@ -49,7 +50,7 @@ export class CosmosWalletStrategy
endpoints?: { rest: string; rpc: string }
} & { wallet: Wallet },
) {
super(args)
super({ ...args, chainId: args.chainId as ChainId })

if (!cosmosWallets.includes(args.wallet)) {
throw new CosmosWalletException(
Expand All @@ -60,7 +61,7 @@ export class CosmosWalletStrategy
}

this.wallet = args.wallet
this.chainId = args.chainId || CosmosChainId.Injective
this.chainId = args.chainId as ChainId
this.cosmosWallet = new CosmosWallet({
wallet: args.wallet,
chainId: args.chainId,
Expand Down
Loading