From 32f079031f41b7751378ce8df74532b21cccb5ce Mon Sep 17 00:00:00 2001 From: Fuxing Loh <4266087+fuxingloh@users.noreply.github.com> Date: Fri, 23 Jul 2021 18:16:19 +0800 Subject: [PATCH] Small `app/api/wallet` refactoring (#332) * moved all network code into network.ts * updated persistence.ts * refactor provider * Fixed screen with wallet reference * added missing snapshot --- .../wallet/__snapshots__/network.test.ts.snap | 41 +++++++++++++ app/api/wallet/index.test.ts | 46 -------------- app/api/wallet/index.ts | 17 ------ app/api/wallet/mnemonic.test.ts | 57 ----------------- app/api/wallet/mnemonic.ts | 48 --------------- app/api/wallet/network.test.ts | 22 +++++++ app/api/wallet/network.ts | 12 ++++ app/api/wallet/persistence.ts | 24 ++++---- app/api/wallet/provider/index.test.ts | 44 +++++++++++++ app/api/wallet/provider/index.ts | 35 +++++++++++ .../provider/mnemonic_unprotected.test.ts | 61 +++++++++++++++++++ .../wallet/provider/mnemonic_unprotected.ts | 35 +++++++++++ app/contexts/WalletContext.tsx | 6 +- app/contexts/WalletManagementContext.tsx | 18 +++--- .../screens/Balances/screens/SendScreen.tsx | 4 +- .../sections/PlaygroundWallet.tsx | 6 +- .../screens/WalletMnemonicCreateVerify.tsx | 4 +- .../screens/WalletMnemonicRestore.tsx | 4 +- .../screens/WalletOnboarding.tsx | 6 +- 19 files changed, 282 insertions(+), 208 deletions(-) create mode 100644 app/api/wallet/__snapshots__/network.test.ts.snap delete mode 100644 app/api/wallet/index.test.ts delete mode 100644 app/api/wallet/index.ts delete mode 100644 app/api/wallet/mnemonic.test.ts delete mode 100644 app/api/wallet/mnemonic.ts create mode 100644 app/api/wallet/network.test.ts create mode 100644 app/api/wallet/provider/index.test.ts create mode 100644 app/api/wallet/provider/index.ts create mode 100644 app/api/wallet/provider/mnemonic_unprotected.test.ts create mode 100644 app/api/wallet/provider/mnemonic_unprotected.ts diff --git a/app/api/wallet/__snapshots__/network.test.ts.snap b/app/api/wallet/__snapshots__/network.test.ts.snap new file mode 100644 index 0000000000..9197197fc6 --- /dev/null +++ b/app/api/wallet/__snapshots__/network.test.ts.snap @@ -0,0 +1,41 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`should resolve bip32 option for LocalPlayground 1`] = ` +Object { + "bip32": Object { + "private": 70615956, + "public": 70617039, + }, + "wif": 239, +} +`; + +exports[`should resolve bip32 option for MainNet 1`] = ` +Object { + "bip32": Object { + "private": 76066276, + "public": 76067358, + }, + "wif": 128, +} +`; + +exports[`should resolve bip32 option for RemotePlayground 1`] = ` +Object { + "bip32": Object { + "private": 70615956, + "public": 70617039, + }, + "wif": 239, +} +`; + +exports[`should resolve bip32 option for TestNet 1`] = ` +Object { + "bip32": Object { + "private": 70615956, + "public": 70617039, + }, + "wif": 239, +} +`; diff --git a/app/api/wallet/index.test.ts b/app/api/wallet/index.test.ts deleted file mode 100644 index 780f9966da..0000000000 --- a/app/api/wallet/index.test.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { WhaleApiClient } from "@defichain/whale-api-client"; -import { WhaleWalletAccountProvider } from "@defichain/whale-api-wallet"; -import { EnvironmentNetwork } from "../../environment"; -import { createWallet } from "./index"; -import { getJellyfishNetwork } from "./network"; -import { WalletData, WalletType } from "./persistence"; - -beforeEach(async () => { - jest.clearAllMocks() -}) - -const network = EnvironmentNetwork.LocalPlayground -const client = new WhaleApiClient({ url: 'http://localhost:19553', network: 'regtest' }) -const options = getJellyfishNetwork(network) -const provider = new WhaleWalletAccountProvider(client, options) - -it('should createWallet', async () => { - const data: WalletData = { - version: "v1", - type: WalletType.MNEMONIC_UNPROTECTED, - raw: JSON.stringify([ - '235b34cd7c9f6d7e4595ffe9ae4b1cb5606df8aca2b527d20a07c8f56b2342f4', // root priv key - 'f40eaad21641ca7cb5ac00f9ce21cac9ba070bb673a237f7bce57acda54386a4' // chain code - ]) - } - - const wallet = createWallet(data, network, provider) - - expect(wallet.get(0).withTransactionBuilder().utxo).toBeDefined() - expect(wallet.get(0).withTransactionBuilder().dex).toBeDefined() - expect(wallet.get(0).withTransactionBuilder().account).toBeDefined() - expect(wallet.get(0).withTransactionBuilder().liqPool).toBeDefined() -}); - - -it('should fail as wallet type not available', async () => { - const data: WalletData = { - version: "v1", - type: undefined as any, - raw: "" - } - - expect(() => { - createWallet(data, network, provider) - }).toThrow('wallet undefined not available') -}) diff --git a/app/api/wallet/index.ts b/app/api/wallet/index.ts deleted file mode 100644 index 70c83db16c..0000000000 --- a/app/api/wallet/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { JellyfishWallet, WalletHdNode } from '@defichain/jellyfish-wallet' -import { WhaleWalletAccount, WhaleWalletAccountProvider } from '@defichain/whale-api-wallet' -import { EnvironmentNetwork } from '../../environment' -import { Mnemonic } from './mnemonic' -import { WalletData, WalletType } from './persistence' - -export type Wallet = JellyfishWallet - -export function createWallet (data: WalletData, options: EnvironmentNetwork, accountProvider: WhaleWalletAccountProvider): Wallet { - switch (data.type) { - case WalletType.MNEMONIC_UNPROTECTED: - return new JellyfishWallet(Mnemonic.createProvider(data, options), accountProvider) - - default: - throw new Error(`wallet ${data.type as string} not available`) - } -} diff --git a/app/api/wallet/mnemonic.test.ts b/app/api/wallet/mnemonic.test.ts deleted file mode 100644 index b44bab9e6a..0000000000 --- a/app/api/wallet/mnemonic.test.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { EnvironmentNetwork } from "../../environment"; -import { Mnemonic } from "./mnemonic"; -import { WalletData, WalletType } from "./persistence"; - -beforeEach(() => { - jest.clearAllMocks() -}) - -describe('getMnemonicHdNodeProvider', () => { - it('should get provider (abandon x23)', async () => { - const data: WalletData = { - version: "v1", - type: WalletType.MNEMONIC_UNPROTECTED, - raw: JSON.stringify([ - '235b34cd7c9f6d7e4595ffe9ae4b1cb5606df8aca2b527d20a07c8f56b2342f4', // root priv key - 'f40eaad21641ca7cb5ac00f9ce21cac9ba070bb673a237f7bce57acda54386a4' // chain code - ]) - } - const options = EnvironmentNetwork.LocalPlayground - - const provider = Mnemonic.createProvider(data, options) - expect(provider).toBeTruthy() - - const node = provider.derive('0') - const pubKey = await node.publicKey() - const privKey = await node.privateKey() - - expect(pubKey.toString('hex')).toStrictEqual('03f85401f5aa4e9ed831120a22b8835137404755b30c59109c18c706b2549f7951') - expect(privKey.toString('hex')).toStrictEqual('da44d2b30836e1ca7c38b2b32fb5f62e07209364248e8a3eb86ffa2aa2ff3af1') - }) -}) - -describe('addMnemonicHdNodeProvider', () => { - it('should set mnemonic (abandon x23)', async () => { - expect(Mnemonic.createWalletDataAbandon23(EnvironmentNetwork.LocalPlayground)).toStrictEqual({ - version: "v1", - type: WalletType.MNEMONIC_UNPROTECTED, - raw: JSON.stringify([ - '235b34cd7c9f6d7e4595ffe9ae4b1cb5606df8aca2b527d20a07c8f56b2342f4', - 'f40eaad21641ca7cb5ac00f9ce21cac9ba070bb673a237f7bce57acda54386a4' - ]) - }) - }) - - it('should set mnemonic (void come effort ...)', async () => { - const mnemonic = 'void come effort suffer camp survey warrior heavy shoot primary clutch crush open amazing screen patrol group space point ten exist slush involve unfold'.split(' ') - - expect(Mnemonic.createWalletData(mnemonic, EnvironmentNetwork.LocalPlayground)).toStrictEqual({ - version: "v1", - type: WalletType.MNEMONIC_UNPROTECTED, - raw: JSON.stringify([ - 'b21fcb414b4414e9bcf7ae647a79a4d29280f6b71cba204cb4dd3d6c6568d0fc', - 'bbb5f26acee2e3713d43cf4e702f2b1ff8672afa9e0d5ac846196689e1d893d2' - ]) - }) - }) -}) diff --git a/app/api/wallet/mnemonic.ts b/app/api/wallet/mnemonic.ts deleted file mode 100644 index e522795048..0000000000 --- a/app/api/wallet/mnemonic.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { Bip32Options, MnemonicHdNodeProvider } from '@defichain/jellyfish-wallet-mnemonic' -import { EnvironmentNetwork } from '../../environment' -import { getJellyfishNetwork } from './network' -import { WalletData, WalletType } from './persistence' - -function getBip32Option (envNetwork: EnvironmentNetwork): Bip32Options { - const network = getJellyfishNetwork(envNetwork) - return { - bip32: { - public: network.bip32.publicPrefix, - private: network.bip32.privatePrefix - }, - wif: network.wifPrefix - } -} - -function createProvider (data: WalletData, network: EnvironmentNetwork): MnemonicHdNodeProvider { - if (data.type !== WalletType.MNEMONIC_UNPROTECTED || data.version !== 'v1') { - throw new Error('Unexpected WalletData') - } - const [privKey, chainCode] = JSON.parse(data.raw) - return MnemonicHdNodeProvider.fromData({ - words: [], - privKey, - chainCode - }, getBip32Option(network)) -} - -export function createWalletData (mnemonic: string[], network: EnvironmentNetwork): WalletData { - const mnemonicData = MnemonicHdNodeProvider.wordsToData(mnemonic, getBip32Option(network)) - return { - version: 'v1', - type: WalletType.MNEMONIC_UNPROTECTED, - raw: JSON.stringify([mnemonicData.privKey, mnemonicData.chainCode]) - } -} - -export function createWalletDataAbandon23 (network: EnvironmentNetwork): WalletData { - return createWalletData([ - 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'art' - ], network) -} - -export const Mnemonic = { - createProvider, - createWalletData, - createWalletDataAbandon23 -} diff --git a/app/api/wallet/network.test.ts b/app/api/wallet/network.test.ts new file mode 100644 index 0000000000..69334bffe0 --- /dev/null +++ b/app/api/wallet/network.test.ts @@ -0,0 +1,22 @@ +import { EnvironmentNetwork } from "../../environment"; +import { getBip32Option } from "./network"; + +it('should resolve bip32 option for MainNet', () => { + const bip32Options = getBip32Option(EnvironmentNetwork.MainNet) + expect(bip32Options).toMatchSnapshot() +}) + +it('should resolve bip32 option for TestNet', () => { + const bip32Options = getBip32Option(EnvironmentNetwork.TestNet) + expect(bip32Options).toMatchSnapshot() +}) + +it('should resolve bip32 option for LocalPlayground', () => { + const bip32Options = getBip32Option(EnvironmentNetwork.LocalPlayground) + expect(bip32Options).toMatchSnapshot() +}) + +it('should resolve bip32 option for RemotePlayground', () => { + const bip32Options = getBip32Option(EnvironmentNetwork.RemotePlayground) + expect(bip32Options).toMatchSnapshot() +}) diff --git a/app/api/wallet/network.ts b/app/api/wallet/network.ts index ee87dd4903..5cadf4a776 100644 --- a/app/api/wallet/network.ts +++ b/app/api/wallet/network.ts @@ -1,4 +1,5 @@ import { MainNet, Network, RegTest, TestNet } from '@defichain/jellyfish-network' +import { Bip32Options } from '@defichain/jellyfish-wallet-mnemonic' import { EnvironmentNetwork } from '../../environment' export function getJellyfishNetwork (network: EnvironmentNetwork): Network { @@ -12,3 +13,14 @@ export function getJellyfishNetwork (network: EnvironmentNetwork): Network { return RegTest } } + +export function getBip32Option (envNetwork: EnvironmentNetwork): Bip32Options { + const network = getJellyfishNetwork(envNetwork) + return { + bip32: { + public: network.bip32.publicPrefix, + private: network.bip32.privatePrefix + }, + wif: network.wifPrefix + } +} diff --git a/app/api/wallet/persistence.ts b/app/api/wallet/persistence.ts index bfac342e25..c86f8eca1a 100644 --- a/app/api/wallet/persistence.ts +++ b/app/api/wallet/persistence.ts @@ -1,24 +1,19 @@ import { getItem, setItem } from '../storage' -const KEY = 'WALLET' - export enum WalletType { - MNEMONIC_UNPROTECTED = 'MNEMONIC_UNPROTECTED', - // MNEMONIC_PASSWORD = 'MNEMONIC_PASSWORD', - // MNEMONIC_BIOMETRIC = 'MNEMONIC_BIOMETRIC', - // LEDGER_BLUE = 'LEDGER_BLUE', + MNEMONIC_UNPROTECTED = 'MNEMONIC_UNPROTECTED' } -export interface WalletData { +export interface WalletPersistenceData { type: WalletType /* To migrate between app version upgrade */ version: 'v1' /* Raw Data encoded in WalletType specified format */ - raw: string + raw: T } -async function get (): Promise { - const json = await getItem(KEY) +async function get (): Promise>> { + const json = await getItem('WALLET') if (json !== null) { return JSON.parse(json) } @@ -26,11 +21,11 @@ async function get (): Promise { return [] } -async function set (wallets: WalletData[]): Promise { - await setItem(KEY, JSON.stringify(wallets)) +async function set (wallets: Array>): Promise { + await setItem('WALLET', JSON.stringify(wallets)) } -async function add (data: WalletData): Promise { +async function add (data: WalletPersistenceData): Promise { const wallets = await get() wallets.push(data) await set(wallets) @@ -42,6 +37,9 @@ async function remove (index: number): Promise { await set(wallets) } +/** + * Multi Wallet Persistence Layer + */ export const WalletPersistence = { set, get, diff --git a/app/api/wallet/provider/index.test.ts b/app/api/wallet/provider/index.test.ts new file mode 100644 index 0000000000..9f95120f61 --- /dev/null +++ b/app/api/wallet/provider/index.test.ts @@ -0,0 +1,44 @@ +import { MnemonicProviderData } from "@defichain/jellyfish-wallet-mnemonic"; +import { WhaleApiClient } from "@defichain/whale-api-client"; +import { EnvironmentNetwork } from "../../../environment"; +import { WalletPersistenceData, WalletType } from "../persistence"; +import { initWhaleWallet } from "./index"; + +beforeEach(async () => { + jest.clearAllMocks() +}) + +const network = EnvironmentNetwork.LocalPlayground +const client = new WhaleApiClient({ url: 'http://localhost:19553', network: 'regtest' }) + +it('should initWhaleWallet', async () => { + const data: WalletPersistenceData = { + version: "v1", + type: WalletType.MNEMONIC_UNPROTECTED, + raw: { + words: ['abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'art'], + privKey: '235b34cd7c9f6d7e4595ffe9ae4b1cb5606df8aca2b527d20a07c8f56b2342f4', + chainCode: 'f40eaad21641ca7cb5ac00f9ce21cac9ba070bb673a237f7bce57acda54386a4' + } + } + + const wallet = initWhaleWallet(data, network, client) + + expect(wallet.get(0).withTransactionBuilder().utxo).toBeDefined() + expect(wallet.get(0).withTransactionBuilder().dex).toBeDefined() + expect(wallet.get(0).withTransactionBuilder().account).toBeDefined() + expect(wallet.get(0).withTransactionBuilder().liqPool).toBeDefined() +}); + + +it('should fail as wallet type not available', async () => { + const data: WalletPersistenceData = { + version: "v1", + type: undefined as any, + raw: "" + } + + expect(() => { + initWhaleWallet(data, network, client) + }).toThrow('wallet undefined not available') +}) diff --git a/app/api/wallet/provider/index.ts b/app/api/wallet/provider/index.ts new file mode 100644 index 0000000000..30270e9a51 --- /dev/null +++ b/app/api/wallet/provider/index.ts @@ -0,0 +1,35 @@ +import { JellyfishWallet, WalletHdNode, WalletHdNodeProvider } from '@defichain/jellyfish-wallet' +import { WhaleApiClient } from '@defichain/whale-api-client' +import { WhaleWalletAccount, WhaleWalletAccountProvider } from '@defichain/whale-api-wallet' +import { EnvironmentNetwork } from '../../../environment' +import { getJellyfishNetwork } from '../network' +import { WalletPersistenceData, WalletType } from '../persistence' +import { MnemonicUnprotected } from './mnemonic_unprotected' + +/** + * Whale JellyfishWallet connected to Whale APIs via the Ocean Infrastructure + */ +export type WhaleWallet = JellyfishWallet + +export function initWhaleWallet (data: WalletPersistenceData, network: EnvironmentNetwork, client: WhaleApiClient): WhaleWallet { + const jellyfishNetwork = getJellyfishNetwork(network) + + const walletProvider = resolveProvider(data, network) + const accountProvider = new WhaleWalletAccountProvider(client, jellyfishNetwork) + + return new JellyfishWallet(walletProvider, accountProvider) +} + +/** + * @param {WalletPersistenceData} data to resolve wallet provider for init + * @param {EnvironmentNetwork} network + */ +function resolveProvider (data: WalletPersistenceData, network: EnvironmentNetwork): WalletHdNodeProvider { + switch (data.type) { + case WalletType.MNEMONIC_UNPROTECTED: + return MnemonicUnprotected.initProvider(data, network) + + default: + throw new Error(`wallet ${data.type as string} not available`) + } +} diff --git a/app/api/wallet/provider/mnemonic_unprotected.test.ts b/app/api/wallet/provider/mnemonic_unprotected.test.ts new file mode 100644 index 0000000000..972e4c2f95 --- /dev/null +++ b/app/api/wallet/provider/mnemonic_unprotected.test.ts @@ -0,0 +1,61 @@ +import { MnemonicProviderData } from "@defichain/jellyfish-wallet-mnemonic"; +import { EnvironmentNetwork } from "../../../environment"; +import { WalletPersistenceData, WalletType } from "../persistence"; +import { MnemonicUnprotected } from "./mnemonic_unprotected"; + +beforeEach(() => { + jest.clearAllMocks() +}) + +describe('getMnemonicHdNodeProvider', () => { + it('should get provider (abandon x23)', async () => { + const data: WalletPersistenceData = { + version: "v1", + type: WalletType.MNEMONIC_UNPROTECTED, + raw: { + words: ['abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'art'], + privKey: '235b34cd7c9f6d7e4595ffe9ae4b1cb5606df8aca2b527d20a07c8f56b2342f4', + chainCode: 'f40eaad21641ca7cb5ac00f9ce21cac9ba070bb673a237f7bce57acda54386a4' + } + } + const options = EnvironmentNetwork.LocalPlayground + + const provider = MnemonicUnprotected.initProvider(data, options) + expect(provider).toBeTruthy() + + const node = provider.derive('0') + const pubKey = await node.publicKey() + const privKey = await node.privateKey() + + expect(pubKey.toString('hex')).toStrictEqual('03f85401f5aa4e9ed831120a22b8835137404755b30c59109c18c706b2549f7951') + expect(privKey.toString('hex')).toStrictEqual('da44d2b30836e1ca7c38b2b32fb5f62e07209364248e8a3eb86ffa2aa2ff3af1') + }) +}) + +describe('addMnemonicHdNodeProvider', () => { + it('should set mnemonic (abandon x23)', async () => { + expect(MnemonicUnprotected.Abandon23Playground).toStrictEqual({ + version: "v1", + type: WalletType.MNEMONIC_UNPROTECTED, + raw: { + words: ['abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'art'], + privKey: '235b34cd7c9f6d7e4595ffe9ae4b1cb5606df8aca2b527d20a07c8f56b2342f4', + chainCode: 'f40eaad21641ca7cb5ac00f9ce21cac9ba070bb673a237f7bce57acda54386a4' + } + }) + }) + + it('should set mnemonic (void come effort ...)', async () => { + const words = 'void come effort suffer camp survey warrior heavy shoot primary clutch crush open amazing screen patrol group space point ten exist slush involve unfold'.split(' ') + + expect(MnemonicUnprotected.toData(words, EnvironmentNetwork.LocalPlayground)).toStrictEqual({ + version: "v1", + type: WalletType.MNEMONIC_UNPROTECTED, + raw: { + words: words, + privKey: 'b21fcb414b4414e9bcf7ae647a79a4d29280f6b71cba204cb4dd3d6c6568d0fc', + chainCode: 'bbb5f26acee2e3713d43cf4e702f2b1ff8672afa9e0d5ac846196689e1d893d2' + } + }) + }) +}) diff --git a/app/api/wallet/provider/mnemonic_unprotected.ts b/app/api/wallet/provider/mnemonic_unprotected.ts new file mode 100644 index 0000000000..8e159c2cad --- /dev/null +++ b/app/api/wallet/provider/mnemonic_unprotected.ts @@ -0,0 +1,35 @@ +import { MnemonicHdNodeProvider, MnemonicProviderData } from '@defichain/jellyfish-wallet-mnemonic' +import { EnvironmentNetwork } from '../../../environment' +import { getBip32Option } from '../network' +import { WalletPersistenceData, WalletType } from '../persistence' + +function initProvider (data: WalletPersistenceData, network: EnvironmentNetwork): MnemonicHdNodeProvider { + if (data.type !== WalletType.MNEMONIC_UNPROTECTED || data.version !== 'v1') { + throw new Error('Unexpected WalletPersistenceData') + } + + const options = getBip32Option(network) + return MnemonicHdNodeProvider.fromData(data.raw, options) +} + +function toData (mnemonic: string[], network: EnvironmentNetwork): WalletPersistenceData { + const options = getBip32Option(network) + const data = MnemonicHdNodeProvider.wordsToData(mnemonic, options) + + return { + version: 'v1', + type: WalletType.MNEMONIC_UNPROTECTED, + raw: data + } +} + +export const MnemonicUnprotected = { + initProvider, + toData, + /** + * Convenience Abandon23 Art on Playground Network Data + */ + Abandon23Playground: toData([ + 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'art' + ], EnvironmentNetwork.LocalPlayground) +} diff --git a/app/contexts/WalletContext.tsx b/app/contexts/WalletContext.tsx index ae75621fc7..9ab1207e4d 100644 --- a/app/contexts/WalletContext.tsx +++ b/app/contexts/WalletContext.tsx @@ -1,13 +1,13 @@ import React, { createContext, useContext, useEffect, useState } from 'react' import { useDispatch } from 'react-redux' import { Logging } from '../api/logging' -import { Wallet } from '../api/wallet' +import { WhaleWallet } from '../api/wallet/provider' import { wallet as store } from '../store/wallet' import { useWalletManagementContext } from './WalletManagementContext' -const WalletContext = createContext(undefined as any) +const WalletContext = createContext(undefined as any) -export function useWallet (): Wallet { +export function useWallet (): WhaleWallet { return useContext(WalletContext) } diff --git a/app/contexts/WalletManagementContext.tsx b/app/contexts/WalletManagementContext.tsx index 9a85506da8..d03c148c87 100644 --- a/app/contexts/WalletManagementContext.tsx +++ b/app/contexts/WalletManagementContext.tsx @@ -1,15 +1,13 @@ -import { WhaleWalletAccountProvider } from '@defichain/whale-api-wallet' import React, { createContext, useContext, useEffect, useMemo, useState } from 'react' import { Logging } from '../api/logging' -import { createWallet, Wallet } from '../api/wallet' -import { getJellyfishNetwork } from '../api/wallet/network' -import { WalletData, WalletPersistence } from '../api/wallet/persistence' +import { WalletPersistence, WalletPersistenceData } from '../api/wallet/persistence' +import { initWhaleWallet, WhaleWallet } from '../api/wallet/provider' import { useNetworkContext } from './NetworkContext' import { useWhaleApiClient } from './WhaleContext' interface WalletManagement { - wallets: Wallet[] - setWallet: (data: WalletData) => Promise + wallets: WhaleWallet[] + setWallet: (data: WalletPersistenceData) => Promise clearWallets: () => Promise } @@ -22,7 +20,7 @@ export function useWalletManagementContext (): WalletManagement { export function WalletManagementProvider (props: React.PropsWithChildren): JSX.Element | null { const { network } = useNetworkContext() const client = useWhaleApiClient() - const [dataList, setDataList] = useState([]) + const [dataList, setDataList] = useState>>([]) useEffect(() => { WalletPersistence.get().then(dataList => { @@ -31,14 +29,12 @@ export function WalletManagementProvider (props: React.PropsWithChildren): }, [network]) const wallets = useMemo(() => { - const options = getJellyfishNetwork(network) - const provider = new WhaleWalletAccountProvider(client, options) - return dataList.map(data => createWallet(data, network, provider)) + return dataList.map(data => initWhaleWallet(data, network, client)) }, [dataList]) const management: WalletManagement = { wallets: wallets, - async setWallet (data: WalletData): Promise { + async setWallet (data: WalletPersistenceData): Promise { await WalletPersistence.set([data]) setDataList(await WalletPersistence.get()) }, diff --git a/app/screens/AppNavigator/screens/Balances/screens/SendScreen.tsx b/app/screens/AppNavigator/screens/Balances/screens/SendScreen.tsx index f901f2addf..97af6fab86 100644 --- a/app/screens/AppNavigator/screens/Balances/screens/SendScreen.tsx +++ b/app/screens/AppNavigator/screens/Balances/screens/SendScreen.tsx @@ -12,7 +12,7 @@ import NumberFormat from 'react-number-format' import { useDispatch, useSelector } from 'react-redux' import { Dispatch } from 'redux' import { Logging } from '../../../../../api/logging' -import { Wallet } from '../../../../../api/wallet' +import { WhaleWallet } from '../../../../../api/wallet/provider' import { Text, TextInput } from '../../../../../components' import { getTokenIcon } from '../../../../../components/icons/tokens/_index' import { PrimaryButton } from '../../../../../components/PrimaryButton' @@ -39,7 +39,7 @@ async function send ({ token, amount, networkName -}: SendForm, wallet: Wallet, dispatch: Dispatch): Promise { +}: SendForm, wallet: WhaleWallet, dispatch: Dispatch): Promise { try { const account = wallet.get(0) const script = await account.getScript() diff --git a/app/screens/PlaygroundNavigator/sections/PlaygroundWallet.tsx b/app/screens/PlaygroundNavigator/sections/PlaygroundWallet.tsx index f7f4087566..f156ad1a1d 100644 --- a/app/screens/PlaygroundNavigator/sections/PlaygroundWallet.tsx +++ b/app/screens/PlaygroundNavigator/sections/PlaygroundWallet.tsx @@ -2,7 +2,7 @@ import { generateMnemonicWords } from '@defichain/jellyfish-wallet-mnemonic' import * as Random from 'expo-random' import React from 'react' import { useDispatch, useSelector } from 'react-redux' -import { Mnemonic } from '../../../api/wallet/mnemonic' +import { MnemonicUnprotected } from '../../../api/wallet/provider/mnemonic_unprotected' import { Text, View } from '../../../components' import { useNetworkContext } from '../../../contexts/NetworkContext' import { useWalletManagementContext } from '../../../contexts/WalletManagementContext' @@ -41,7 +41,7 @@ export function PlaygroundWallet (): JSX.Element | null { await setWallet(Mnemonic.createWalletDataAbandon23(network.network))} + onPress={async () => await setWallet(MnemonicUnprotected.Abandon23Playground)} /> diff --git a/app/screens/WalletNavigator/screens/WalletMnemonicCreateVerify.tsx b/app/screens/WalletNavigator/screens/WalletMnemonicCreateVerify.tsx index 687ecd4002..634b930e88 100644 --- a/app/screens/WalletNavigator/screens/WalletMnemonicCreateVerify.tsx +++ b/app/screens/WalletNavigator/screens/WalletMnemonicCreateVerify.tsx @@ -2,7 +2,7 @@ import { StackScreenProps } from '@react-navigation/stack' import * as React from 'react' import { useState } from 'react' import { KeyboardAvoidingView, ScrollView, TouchableOpacity } from 'react-native' -import { Mnemonic } from '../../../api/wallet/mnemonic' +import { MnemonicUnprotected } from '../../../api/wallet/provider/mnemonic_unprotected' import { Text, TextInput, View } from '../../../components' import { useNetworkContext } from '../../../contexts/NetworkContext' import { useWalletManagementContext } from '../../../contexts/WalletManagementContext' @@ -21,7 +21,7 @@ export function WalletMnemonicCreateVerify ({ route }: Props): JSX.Element { async function onVerify (): Promise { if (actualWords.join(' ') === enteredWords.join(' ')) { - await setWallet(Mnemonic.createWalletData(enteredWords, network)) + await setWallet(MnemonicUnprotected.toData(enteredWords, network)) } else { setValid(false) } diff --git a/app/screens/WalletNavigator/screens/WalletMnemonicRestore.tsx b/app/screens/WalletNavigator/screens/WalletMnemonicRestore.tsx index c213ff99b8..197f35a430 100644 --- a/app/screens/WalletNavigator/screens/WalletMnemonicRestore.tsx +++ b/app/screens/WalletNavigator/screens/WalletMnemonicRestore.tsx @@ -2,7 +2,7 @@ import { validateMnemonicSentence } from '@defichain/jellyfish-wallet-mnemonic' import * as React from 'react' import { useState } from 'react' import { KeyboardAvoidingView, ScrollView, TouchableOpacity } from 'react-native' -import { Mnemonic } from '../../../api/wallet/mnemonic' +import { MnemonicUnprotected } from '../../../api/wallet/provider/mnemonic_unprotected' import { Text, TextInput, View } from '../../../components' import { useNetworkContext } from '../../../contexts/NetworkContext' import { useWalletManagementContext } from '../../../contexts/WalletManagementContext' @@ -17,7 +17,7 @@ export function WalletMnemonicRestore (): JSX.Element { async function onRestore (): Promise { const words = phrase.split(' ') if (validateMnemonicSentence(words)) { - await setWallet(Mnemonic.createWalletData(words, network)) + await setWallet(MnemonicUnprotected.toData(words, network)) } else { setValid(false) } diff --git a/app/screens/WalletNavigator/screens/WalletOnboarding.tsx b/app/screens/WalletNavigator/screens/WalletOnboarding.tsx index 3b9c24ada7..66e23e4f02 100644 --- a/app/screens/WalletNavigator/screens/WalletOnboarding.tsx +++ b/app/screens/WalletNavigator/screens/WalletOnboarding.tsx @@ -1,22 +1,20 @@ import { useNavigation } from '@react-navigation/native' import * as React from 'react' import { ScrollView, TouchableOpacity } from 'react-native' -import { Mnemonic } from '../../../api/wallet/mnemonic' +import { MnemonicUnprotected } from '../../../api/wallet/provider/mnemonic_unprotected' import { Text, View } from '../../../components' import { VectorIcon, VectorIconName } from '../../../constants/Theme' -import { useNetworkContext } from '../../../contexts/NetworkContext' import { useWalletManagementContext } from '../../../contexts/WalletManagementContext' import { getEnvironment } from '../../../environment' import { tailwind } from '../../../tailwind' import { translate } from '../../../translations' export function WalletOnboarding (): JSX.Element { - const { network } = useNetworkContext() const { setWallet } = useWalletManagementContext() const navigator = useNavigation() const onDebugPress = getEnvironment().debug ? async () => { - await setWallet(Mnemonic.createWalletDataAbandon23(network)) + await setWallet(MnemonicUnprotected.Abandon23Playground) } : undefined return (