Skip to content

Commit

Permalink
chore: abstract cosmos wallets
Browse files Browse the repository at this point in the history
  • Loading branch information
ThomasRalee committed Oct 18, 2024
1 parent 0896017 commit 673b3bf
Show file tree
Hide file tree
Showing 19 changed files with 309 additions and 271 deletions.
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
# 🌟 Injective Protocol - Keplr Wallet Strategy
# 🌟 Injective Protocol - Cosmos Wallet Strategy

<!-- TODO -->

[![downloads](https://img.shields.io/npm/dm/@injectivelabs/wallet-ts.svg)](https://www.npmjs.com/package/@injectivelabs/wallet-ts)
[![npm-version](https://img.shields.io/npm/v/@injectivelabs/wallet-ts.svg)](https://www.npmjs.com/package/@injectivelabs/wallet-ts)
[![license](https://img.shields.io/npm/l/express.svg)]()

_Package to use Keplr Wallets on Injective via the wallet strategy._
_Package to use Cosmos Wallets on Injective via the wallet strategy._

---

## 📚 Installation

```bash
yarn add @injectivelabs/wallet-keplr
yarn add @injectivelabs/wallet-cosmos
```

---
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@injectivelabs/wallet-keplr",
"description": "Keplr wallet strategy for use with @injectivelabs/wallet-core.",
"name": "@injectivelabs/wallet-cosmos",
"description": "Cosmos wallet strategies for use with @injectivelabs/wallet-core.",
"version": "0.0.1",
"sideEffects": false,
"author": {
Expand All @@ -15,7 +15,7 @@
"dist"
],
"_moduleAliases": {
"~wallet-keplr": "dist"
"~wallet-cosmos": "dist"
},
"scripts": {
"postinstall": "link-module-alias",
Expand All @@ -34,34 +34,26 @@
"start": "node dist/index.js"
},
"dependencies": {
"@ethereumjs/common": "^3.1.1",
"@ethereumjs/tx": "^4.1.1",
"@injectivelabs/exceptions": "^1.14.14",
"@injectivelabs/networks": "^1.14.15-beta.0",
"@injectivelabs/sdk-ts": "^1.14.15-beta.9",
"@injectivelabs/ts-types": "^1.14.14",
"@injectivelabs/utils": "^1.14.14",
"@injectivelabs/wallet-base": "^0.0.1",
"alchemy-sdk": "^2.6.3",
"eip1193-provider": "^1.0.1",
"eth-sig-util": "^3.0.1",
"ethereumjs-util": "^7.1.0",
"ethers": "^6.5.1",
"hdkey": "^2.0.1",
"link-module-alias": "^1.2.0",
"long": "^5.2.1",
"@cosmjs/launchpad": "0.27.1",
"@cosmjs/amino": "^0.32.3",
"@cosmjs/stargate": "^0.32.3",
"@cosmjs/proto-signing": "^0.32.3",
"@keplr-wallet/cosmos": "^0.12.71",
"@keplr-wallet/types": "^0.12.71",
"shx": "^0.3.3"
},
"devDependencies": {
"@types/eth-sig-util": "^2.1.1",
"@types/ethereumjs-util": "^6.1.0",
"@types/hdkey": "^2.0.1"
},
"gitHead": "35bd09035587be3fd170cc48b5c13f231e699a79",
"typedoc": {
"entryPoint": "./src/index.ts",
"readmeFile": "./README.md",
"displayName": "wallet-metamask API Documentation"
"displayName": "wallet-cosmos API Documentation"
},
"resolutions": {
"**/libsodium": "npm:@bangjelkoski/noop",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,9 @@ import type { Window as KeplrWindow } from '@keplr-wallet/types'

declare global {
// eslint-disable-next-line @typescript-eslint/no-empty-interface
interface Window extends KeplrWindow {}
interface Window extends KeplrWindow {
leap: KeplrWindow['keplr']
keplr: KeplrWindow['keplr']
ninji: KeplrWindow['ninji']
}
}
1 change: 1 addition & 0 deletions packages/wallets/wallet-cosmos/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { CosmosWalletStrategy } from './strategy/strategy'
Original file line number Diff line number Diff line change
@@ -1,79 +1,105 @@
/* eslint-disable class-methods-use-this */
import {
ChainId,
CosmosChainId,
AccountAddress,
EthereumChainId,
} from '@injectivelabs/ts-types'
import {
TxRaw,
TxResponse,
waitTxBroadcasted,
createTxRawFromSigResponse,
createSignDocFromTransaction,
} from '@injectivelabs/sdk-ts'
import type { DirectSignResponse } from '@cosmjs/proto-signing'
import {
ChainId,
CosmosChainId,
AccountAddress,
EthereumChainId,
} from '@injectivelabs/ts-types'
import {
ErrorType,
TransactionException,
UnspecifiedErrorCode,
CosmosWalletException,
TransactionException,
} from '@injectivelabs/exceptions'
import { KeplrWallet } from '../utils/wallet'
import {
Wallet,
WalletAction,
WalletDeviceType,
WalletEventListener,
BaseConcreteStrategy,
ConcreteWalletStrategy,
SendTransactionOptions,
CosmosWalletAbstraction,
createCosmosSignDocFromSignDoc,
} from '@injectivelabs/wallet-base'
import type { DirectSignResponse } from '@cosmjs/proto-signing'
import { CosmosWallet } from './../wallet'

export class Keplr
export class CosmosWalletStrategy
extends BaseConcreteStrategy
implements ConcreteWalletStrategy
{
private keplrWallet: KeplrWallet

constructor(args: { chainId: ChainId }) {
public wallet: Wallet
private cosmosWallet: CosmosWallet

constructor(
args: {
chainId: ChainId
endpoints?: { rest: string; rpc: string }
} & { wallet: Wallet },
) {
super(args)

this.wallet = args.wallet
this.chainId = args.chainId || CosmosChainId.Injective
this.keplrWallet = new KeplrWallet(args.chainId)
this.cosmosWallet = new CosmosWallet(args.chainId, args.wallet)
}

async getWalletDeviceType(): Promise<WalletDeviceType> {
const keplrWallet = this.getKeplrWallet()
const key = await keplrWallet.getKey()
const cosmosWallet = this.getCurrentCosmosWallet()
const key = await cosmosWallet.getKey()

return key.isNanoLedger
? Promise.resolve(WalletDeviceType.Hardware)
: Promise.resolve(WalletDeviceType.Browser)
}

async enable(): Promise<boolean> {
const keplrWallet = this.getKeplrWallet()
const cosmosWallet = this.getCurrentCosmosWallet()

return await keplrWallet.checkChainIdSupport()
return await cosmosWallet.checkChainIdSupport()
}

public async disconnect() {
const { wallet } = this

if (this.listeners[WalletEventListener.AccountChange]) {
window.removeEventListener(
'keplr_keystorechange',
this.listeners[WalletEventListener.AccountChange],
)
if (wallet === Wallet.Ninji) {
window.ninji.off(
'accountsChanged',
this.listeners[WalletEventListener.AccountChange],
)
}

if (wallet === Wallet.Keplr) {
window.removeEventListener(
'keplr_keystorechange',
this.listeners[WalletEventListener.AccountChange],
)
}

if (wallet === Wallet.Leap) {
window.removeEventListener(
'leap_keystorechange',
this.listeners[WalletEventListener.AccountChange],
)
}
}

this.listeners = {}
}

async getAddresses(): Promise<string[]> {
const keplrWallet = this.getKeplrWallet()
const cosmosWallet = this.getCurrentCosmosWallet()

try {
const accounts = await keplrWallet.getAccounts()
const accounts = await cosmosWallet.getAccounts()

return accounts.map((account) => account.address)
} catch (e: unknown) {
Expand All @@ -97,9 +123,11 @@ export class Keplr
_transaction: unknown,
_options: { address: AccountAddress; ethereumChainId: EthereumChainId },
): Promise<string> {
const { wallet } = this

throw new CosmosWalletException(
new Error(
'sendEthereumTransaction is not supported. Keplr only supports sending cosmos transactions',
`sendEthereumTransaction is not supported. ${wallet} only supports sending cosmos transactions`,
),
{
code: UnspecifiedErrorCode,
Expand All @@ -112,7 +140,7 @@ export class Keplr
transaction: DirectSignResponse | TxRaw,
options: SendTransactionOptions,
): Promise<TxResponse> {
const { keplrWallet } = this
const cosmosWallet = this.getCurrentCosmosWallet()
const txRaw = createTxRawFromSigResponse(transaction)

if (!options.endpoints) {
Expand All @@ -124,7 +152,7 @@ export class Keplr
}

try {
const txHash = await keplrWallet.broadcastTx(txRaw)
const txHash = await cosmosWallet.broadcastTx(txRaw)

return await waitTxBroadcasted(txHash, options)
} catch (e: unknown) {
Expand Down Expand Up @@ -169,10 +197,10 @@ export class Keplr
txRaw: TxRaw
accountNumber: number
chainId: string
address: string
address: AccountAddress
}) {
const keplrWallet = this.getKeplrWallet()
const signer = await keplrWallet.getOfflineSigner()
const cosmosWallet = this.getCurrentCosmosWallet()
const signer = await cosmosWallet.getOfflineSigner()
const signDoc = createSignDocFromTransaction(transaction)

try {
Expand All @@ -189,7 +217,7 @@ export class Keplr
}

async signEip712TypedData(
_transaction: string,
_eip712TypedData: string,
_address: AccountAddress,
): Promise<string> {
throw new CosmosWalletException(
Expand All @@ -205,13 +233,12 @@ export class Keplr
signer: string,
data: string | Uint8Array,
): Promise<string> {
const keplrWallet = this.getKeplrWallet()
const keplr = await keplrWallet.getKeplrWallet()
const cosmosWallet = this.getCurrentCosmosWallet()

try {
const signature = await keplr.signArbitrary(this.chainId, signer, data)
const signature = await cosmosWallet.signArbitrary({ data, signer })

return signature.signature
return signature
} catch (e: unknown) {
throw new CosmosWalletException(new Error((e as any).message), {
code: UnspecifiedErrorCode,
Expand All @@ -221,8 +248,10 @@ export class Keplr
}

async getEthereumChainId(): Promise<string> {
const { wallet } = this

throw new CosmosWalletException(
new Error('getEthereumChainId is not supported on Keplr'),
new Error(`getEthereumChainId is not supported on ${wallet}`),
{
code: UnspecifiedErrorCode,
context: WalletAction.GetChainId,
Expand All @@ -231,8 +260,10 @@ export class Keplr
}

async getEthereumTransactionReceipt(_txHash: string): Promise<string> {
const { wallet } = this

throw new CosmosWalletException(
new Error('getEthereumTransactionReceipt is not supported on Keplr'),
new Error(`getEthereumTransactionReceipt is not supported on ${wallet}`),
{
code: UnspecifiedErrorCode,
context: WalletAction.GetEthereumTransactionReceipt,
Expand All @@ -241,15 +272,17 @@ export class Keplr
}

async getPubKey(): Promise<string> {
const keplrWallet = this.getKeplrWallet()
const key = await keplrWallet.getKey()
const cosmosWallet = this.getCurrentCosmosWallet()
const key = await cosmosWallet.getKey()

return Buffer.from(key.pubKey).toString('base64')
}

async onAccountChange(
callback: (account: AccountAddress) => void,
): Promise<void> {
const { wallet } = this

const listener = async () => {
const [account] = await this.getAddresses()

Expand All @@ -260,19 +293,31 @@ export class Keplr
[WalletEventListener.AccountChange]: listener,
}

window.addEventListener('keplr_keystorechange', listener)
if (wallet === Wallet.Ninji) {
window.ninji.on('accountsChanged', listener)
}

if (wallet === Wallet.Keplr) {
window.addEventListener('keplr_keystorechange', listener)
}

if (wallet === Wallet.Leap) {
window.addEventListener('leap_keystorechange', listener)
}
}

public getCosmosWallet(chainId: ChainId): CosmosWalletAbstraction {
return new KeplrWallet(chainId)
public getCosmosWallet(chainId: ChainId): CosmosWallet {
const { wallet, cosmosWallet } = this

return !cosmosWallet ? new CosmosWallet(chainId, wallet) : cosmosWallet
}

private getKeplrWallet(): KeplrWallet {
const { keplrWallet } = this
private getCurrentCosmosWallet(): CosmosWallet {
const { wallet, cosmosWallet } = this

if (!keplrWallet) {
if (!cosmosWallet) {
throw new CosmosWalletException(
new Error('Please install the Keplr wallet extension'),
new Error(`Please install the ${wallet} wallet extension`),
{
code: UnspecifiedErrorCode,
type: ErrorType.WalletNotInstalledError,
Expand All @@ -281,6 +326,6 @@ export class Keplr
)
}

return keplrWallet
return cosmosWallet as CosmosWallet
}
}
Loading

0 comments on commit 673b3bf

Please sign in to comment.