From b324ed7b34c2849bb2e7db2bc6a56c0a13ef1aeb Mon Sep 17 00:00:00 2001 From: Ilja Date: Tue, 15 Mar 2022 13:37:48 +0200 Subject: [PATCH 1/3] Cleanup --- wallets/react-wallet-v2/src/lib/EIP155.ts | 69 ------------------- .../src/lib/{Solana.ts => SolanaLib.ts} | 16 ++++- .../src/utils/SolanaWalletUtil.ts | 16 ++--- 3 files changed, 21 insertions(+), 80 deletions(-) delete mode 100644 wallets/react-wallet-v2/src/lib/EIP155.ts rename wallets/react-wallet-v2/src/lib/{Solana.ts => SolanaLib.ts} (85%) diff --git a/wallets/react-wallet-v2/src/lib/EIP155.ts b/wallets/react-wallet-v2/src/lib/EIP155.ts deleted file mode 100644 index c4c4fa1..0000000 --- a/wallets/react-wallet-v2/src/lib/EIP155.ts +++ /dev/null @@ -1,69 +0,0 @@ -import { Secp256k1Wallet, StdSignDoc } from '@cosmjs/amino' -import { fromHex } from '@cosmjs/encoding' -import { DirectSecp256k1Wallet, makeSignBytes } from '@cosmjs/proto-signing' -// @ts-expect-error -import { SignDoc } from '@cosmjs/proto-signing/build/codec/cosmos/tx/v1beta1/tx' -import MnemonicKeyring from 'mnemonic-keyring' - -/** - * Constants - */ -const DEFAULT_PATH = "m/44'/118'/0'/0/0" - -/** - * Types - */ -interface IInitArguments { - mnemonic?: string - path?: string - prefix?: string -} - -/** - * Utility - */ -export class EIP155 { - private keyring: MnemonicKeyring - private directSigner: DirectSecp256k1Wallet - private aminoSigner: Secp256k1Wallet - - constructor( - keyring: MnemonicKeyring, - directSigner: DirectSecp256k1Wallet, - aminoSigner: Secp256k1Wallet - ) { - this.directSigner = directSigner - this.keyring = keyring - this.aminoSigner = aminoSigner - } - - static async init({ mnemonic, path, prefix }: IInitArguments) { - const keyring = await MnemonicKeyring.init({ mnemonic }) - const privateKey = fromHex(keyring.getPrivateKey(path ?? DEFAULT_PATH)) - const chainPrefix = prefix ?? 'cosmos' - const directSigner = await DirectSecp256k1Wallet.fromKey(privateKey, chainPrefix) - const aminoSigner = await Secp256k1Wallet.fromKey(privateKey, chainPrefix) - - return new EIP155(keyring, directSigner, aminoSigner) - } - - public async getAccount(number = 0) { - const account = await this.directSigner.getAccounts() - - return account[number] - } - - public getMnemonic() { - return this.keyring.mnemonic - } - - public async signDirect(address: string, signDoc: SignDoc) { - const signDocBytes = makeSignBytes(signDoc) - // @ts-expect-error - return await this.directSigner.signDirect(address, signDocBytes) - } - - public async signAmino(address: string, signDoc: StdSignDoc) { - return await this.aminoSigner.signAmino(address, signDoc) - } -} diff --git a/wallets/react-wallet-v2/src/lib/Solana.ts b/wallets/react-wallet-v2/src/lib/SolanaLib.ts similarity index 85% rename from wallets/react-wallet-v2/src/lib/Solana.ts rename to wallets/react-wallet-v2/src/lib/SolanaLib.ts index 140136f..aca412f 100644 --- a/wallets/react-wallet-v2/src/lib/Solana.ts +++ b/wallets/react-wallet-v2/src/lib/SolanaLib.ts @@ -2,17 +2,27 @@ import { Keypair, PublicKey, Transaction, TransactionInstructionCtorFields } fro import bs58 from 'bs58' import nacl from 'tweetnacl' -export class Solana { +/** + * Types + */ +interface IInitArguments { + secretKey?: Uint8Array +} + +/** + * Library + */ +export default class SolanaLib { keypair: Keypair constructor(keypair: Keypair) { this.keypair = keypair } - static init(secretKey?: Uint8Array) { + static init({ secretKey }: IInitArguments) { const keypair = secretKey ? Keypair.fromSecretKey(secretKey) : Keypair.generate() - return new Solana(keypair) + return new SolanaLib(keypair) } public async getAccount() { diff --git a/wallets/react-wallet-v2/src/utils/SolanaWalletUtil.ts b/wallets/react-wallet-v2/src/utils/SolanaWalletUtil.ts index 1ff70f1..d1d336c 100644 --- a/wallets/react-wallet-v2/src/utils/SolanaWalletUtil.ts +++ b/wallets/react-wallet-v2/src/utils/SolanaWalletUtil.ts @@ -1,8 +1,8 @@ -import { Solana } from '@/lib/Solana' +import SolanaLib from '@/lib/SolanaLib' -export let wallet1: Solana -export let wallet2: Solana -export let solanaWallets: Record +export let wallet1: SolanaLib +export let wallet2: SolanaLib +export let solanaWallets: Record export let solanaAddresses: string[] let address1: string @@ -19,13 +19,13 @@ export async function createOrRestoreSolanaWallet() { const secretArray1: number[] = Object.values(JSON.parse(secretKey1)) const secretArray2: number[] = Object.values(JSON.parse(secretKey2)) - wallet1 = Solana.init(Uint8Array.from(secretArray1)) - wallet2 = Solana.init(Uint8Array.from(secretArray2)) + wallet1 = SolanaLib.init({ secretKey: Uint8Array.from(secretArray1) }) + wallet2 = SolanaLib.init({ secretKey: Uint8Array.from(secretArray2) }) address1 = await wallet1.getAccount() address2 = await wallet2.getAccount() } else { - wallet1 = Solana.init() - wallet2 = Solana.init() + wallet1 = SolanaLib.init({}) + wallet2 = SolanaLib.init({}) address1 = await wallet1.getAccount() address2 = await wallet2.getAccount() // Don't store secretKey in local storage in a production project! From 0c2f1350e1be889beeeca3348e307b62fdeb828f Mon Sep 17 00:00:00 2001 From: Ilja Date: Tue, 15 Mar 2022 14:21:17 +0200 Subject: [PATCH 2/3] Create EIP155Lib for consistency with Cosmos and Solana --- wallets/react-wallet-v2/src/lib/CosmosLib.ts | 4 +- wallets/react-wallet-v2/src/lib/EIP155Lib.ts | 49 +++++++++++++++++++ wallets/react-wallet-v2/src/lib/SolanaLib.ts | 2 +- .../src/utils/CosmosWalletUtil.ts | 12 ++--- .../src/utils/EIP155WalletUtil.ts | 34 ++++++++----- .../src/utils/SolanaWalletUtil.ts | 9 ++-- 6 files changed, 81 insertions(+), 29 deletions(-) create mode 100644 wallets/react-wallet-v2/src/lib/EIP155Lib.ts diff --git a/wallets/react-wallet-v2/src/lib/CosmosLib.ts b/wallets/react-wallet-v2/src/lib/CosmosLib.ts index 90ec44f..0128ab9 100644 --- a/wallets/react-wallet-v2/src/lib/CosmosLib.ts +++ b/wallets/react-wallet-v2/src/lib/CosmosLib.ts @@ -47,10 +47,10 @@ export default class CosmosLib { return this.keyring.mnemonic } - public async getAccount() { + public async getAddress() { const account = await this.directSigner.getAccounts() - return account[0] + return account[0].address } public async signDirect(address: string, signDoc: SignDoc) { diff --git a/wallets/react-wallet-v2/src/lib/EIP155Lib.ts b/wallets/react-wallet-v2/src/lib/EIP155Lib.ts new file mode 100644 index 0000000..652a85d --- /dev/null +++ b/wallets/react-wallet-v2/src/lib/EIP155Lib.ts @@ -0,0 +1,49 @@ +import { providers, Wallet } from 'ethers' + +/** + * Types + */ +interface IInitArgs { + mnemonic?: string +} + +/** + * Library + */ +export default class EIP155Lib { + wallet: Wallet + + constructor(wallet: Wallet) { + this.wallet = wallet + } + + static init({ mnemonic }: IInitArgs) { + const wallet = mnemonic ? Wallet.fromMnemonic(mnemonic) : Wallet.createRandom() + + return new EIP155Lib(wallet) + } + + getMnemonic() { + return this.wallet.mnemonic.phrase + } + + getAddress() { + return this.wallet.address + } + + signMessage(message: string) { + return this.wallet.signMessage(message) + } + + _signTypedData(domain: any, types: any, data: any) { + return this.wallet._signTypedData(domain, types, data) + } + + connect(provider: providers.JsonRpcProvider) { + return this.wallet.connect(provider) + } + + signTransaction(transaction: providers.TransactionRequest) { + return this.wallet.signTransaction(transaction) + } +} diff --git a/wallets/react-wallet-v2/src/lib/SolanaLib.ts b/wallets/react-wallet-v2/src/lib/SolanaLib.ts index aca412f..9abc514 100644 --- a/wallets/react-wallet-v2/src/lib/SolanaLib.ts +++ b/wallets/react-wallet-v2/src/lib/SolanaLib.ts @@ -25,7 +25,7 @@ export default class SolanaLib { return new SolanaLib(keypair) } - public async getAccount() { + public async getAddress() { return await this.keypair.publicKey.toBase58() } diff --git a/wallets/react-wallet-v2/src/utils/CosmosWalletUtil.ts b/wallets/react-wallet-v2/src/utils/CosmosWalletUtil.ts index fd63298..55ed38f 100644 --- a/wallets/react-wallet-v2/src/utils/CosmosWalletUtil.ts +++ b/wallets/react-wallet-v2/src/utils/CosmosWalletUtil.ts @@ -18,22 +18,18 @@ export async function createOrRestoreCosmosWallet() { if (mnemonic1 && mnemonic2) { wallet1 = await CosmosLib.init({ mnemonic: mnemonic1 }) wallet2 = await CosmosLib.init({ mnemonic: mnemonic2 }) - const account1 = await wallet1.getAccount() - const account2 = await wallet2.getAccount() - address1 = account1.address - address2 = account2.address } else { wallet1 = await CosmosLib.init({}) wallet2 = await CosmosLib.init({}) - const account1 = await wallet1.getAccount() - const account2 = await wallet2.getAccount() - address1 = account1.address - address2 = account2.address + // Don't store mnemonic in local storage in a production project! localStorage.setItem('COSMOS_MNEMONIC_1', wallet1.getMnemonic()) localStorage.setItem('COSMOS_MNEMONIC_2', wallet2.getMnemonic()) } + address1 = await wallet1.getAddress() + address2 = await wallet2.getAddress() + cosmosWallets = { [address1]: wallet1, [address2]: wallet2 diff --git a/wallets/react-wallet-v2/src/utils/EIP155WalletUtil.ts b/wallets/react-wallet-v2/src/utils/EIP155WalletUtil.ts index fa212f8..a09ca5e 100644 --- a/wallets/react-wallet-v2/src/utils/EIP155WalletUtil.ts +++ b/wallets/react-wallet-v2/src/utils/EIP155WalletUtil.ts @@ -1,30 +1,38 @@ -import { Wallet } from 'ethers' +import EIP155Lib from '@/lib/EIP155Lib' -export let eip155Wallets: Record +export let wallet1: EIP155Lib +export let wallet2: EIP155Lib +export let eip155Wallets: Record export let eip155Addresses: string[] -let wallet1: Wallet -let wallet2: Wallet +let address1: string +let address2: string /** * Utilities */ export function createOrRestoreEIP155Wallet() { - const mnemonic = localStorage.getItem('WALLET_MNEMONIC') + const mnemonic1 = localStorage.getItem('EIP155_MNEMONIC_1') + const mnemonic2 = localStorage.getItem('EIP155_MNEMONIC_2') - if (mnemonic) { - wallet1 = Wallet.fromMnemonic(mnemonic, "m/44'/60'/0'/0/0") - wallet2 = Wallet.fromMnemonic(mnemonic, "m/44'/60'/0'/0/1") + if (mnemonic1 && mnemonic2) { + wallet1 = EIP155Lib.init({ mnemonic: mnemonic1 }) + wallet2 = EIP155Lib.init({ mnemonic: mnemonic2 }) } else { - wallet1 = Wallet.createRandom() - wallet2 = Wallet.fromMnemonic(wallet1.mnemonic.phrase, "m/44'/60'/0'/0/1") + wallet1 = EIP155Lib.init({}) + wallet2 = EIP155Lib.init({}) + // Don't store mnemonic in local storage in a production project! - localStorage.setItem('WALLET_MNEMONIC', wallet1.mnemonic.phrase) + localStorage.setItem('EIP155_MNEMONIC_1', wallet1.getMnemonic()) + localStorage.setItem('EIP155_MNEMONIC_2', wallet2.getMnemonic()) } + address1 = wallet1.getAddress() + address2 = wallet2.getAddress() + eip155Wallets = { - [wallet1.address]: wallet1, - [wallet2.address]: wallet2 + [address1]: wallet1, + [address2]: wallet2 } eip155Addresses = Object.keys(eip155Wallets) diff --git a/wallets/react-wallet-v2/src/utils/SolanaWalletUtil.ts b/wallets/react-wallet-v2/src/utils/SolanaWalletUtil.ts index d1d336c..60b36c1 100644 --- a/wallets/react-wallet-v2/src/utils/SolanaWalletUtil.ts +++ b/wallets/react-wallet-v2/src/utils/SolanaWalletUtil.ts @@ -18,16 +18,12 @@ export async function createOrRestoreSolanaWallet() { if (secretKey1 && secretKey2) { const secretArray1: number[] = Object.values(JSON.parse(secretKey1)) const secretArray2: number[] = Object.values(JSON.parse(secretKey2)) - wallet1 = SolanaLib.init({ secretKey: Uint8Array.from(secretArray1) }) wallet2 = SolanaLib.init({ secretKey: Uint8Array.from(secretArray2) }) - address1 = await wallet1.getAccount() - address2 = await wallet2.getAccount() } else { wallet1 = SolanaLib.init({}) wallet2 = SolanaLib.init({}) - address1 = await wallet1.getAccount() - address2 = await wallet2.getAccount() + // Don't store secretKey in local storage in a production project! localStorage.setItem( 'SOLANA_SECRET_KEY_1', @@ -39,6 +35,9 @@ export async function createOrRestoreSolanaWallet() { ) } + address1 = await wallet1.getAddress() + address2 = await wallet2.getAddress() + solanaWallets = { [address1]: wallet1, [address2]: wallet2 From 52f8c5d82c960ff3e7b8df782d6931cb5e89a69d Mon Sep 17 00:00:00 2001 From: Ilja Date: Tue, 15 Mar 2022 14:31:10 +0200 Subject: [PATCH 3/3] Fis solana signTransaction --- wallets/react-wallet-v2/src/lib/SolanaLib.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/wallets/react-wallet-v2/src/lib/SolanaLib.ts b/wallets/react-wallet-v2/src/lib/SolanaLib.ts index 9abc514..ce999aa 100644 --- a/wallets/react-wallet-v2/src/lib/SolanaLib.ts +++ b/wallets/react-wallet-v2/src/lib/SolanaLib.ts @@ -58,8 +58,12 @@ export default class SolanaLib { await tx.sign(this.keypair) - const { signature } = tx.signatures[tx.signatures.length - 1] + if (!tx.signature) { + throw new Error('Missing signature!') + } - return { signature } + const bs58Signature = bs58.encode(tx.signature) + + return { signature: bs58Signature } } }