From 912067ea494cb217b5b6fc56b76cf24de6989866 Mon Sep 17 00:00:00 2001 From: Igor Artamonov Date: Wed, 29 May 2024 22:09:51 +0100 Subject: [PATCH 1/5] solution: Storybook for web demo with general features --- packages/react-app/.storybook/main.js | 3 +- .../react-app/src/app/layout/Header/Title.tsx | 8 +- .../src/transactions/TxDetails/TxStatus.tsx | 1 + .../TxHistory/List/Transaction.tsx | 18 ++- .../ExampleWeb/Blockchains.stories.tsx | 51 +++++++ .../stories/ExampleWeb/CancelTx.stories.tsx | 100 +++++++++++++ .../stories/ExampleWeb/Ledger.stories.tsx | 15 ++ .../stories/ExampleWeb/Main.stories.tsx | 139 +++++++++++++++--- .../stories/ExampleWeb/SpeedUpTx.stories.tsx | 100 +++++++++++++ .../stories/ExampleWeb/StableCoin.stories.tsx | 80 ++++++++++ .../stories/ExampleWeb/TxHistory.stories.tsx | 113 ++++++++++++++ packages/react-app/stories/electron_index.js | 2 +- packages/react-app/stories/wallets.ts | 14 +- packages/store/src/hdpath-preview/sagas.ts | 2 +- .../components/common/Form/FormAccordion.tsx | 1 + .../src/components/common/Form/FormLabel.tsx | 1 + 16 files changed, 607 insertions(+), 41 deletions(-) create mode 100644 packages/react-app/stories/ExampleWeb/Blockchains.stories.tsx create mode 100644 packages/react-app/stories/ExampleWeb/CancelTx.stories.tsx create mode 100644 packages/react-app/stories/ExampleWeb/Ledger.stories.tsx create mode 100644 packages/react-app/stories/ExampleWeb/SpeedUpTx.stories.tsx create mode 100644 packages/react-app/stories/ExampleWeb/StableCoin.stories.tsx create mode 100644 packages/react-app/stories/ExampleWeb/TxHistory.stories.tsx diff --git a/packages/react-app/.storybook/main.js b/packages/react-app/.storybook/main.js index 3ac8eb343..90949dbbe 100644 --- a/packages/react-app/.storybook/main.js +++ b/packages/react-app/.storybook/main.js @@ -4,9 +4,8 @@ const config = { stories: [ '../stories/**/*.stories.tsx' ], - docs: { - autodocs: true + autodocs: false } }; diff --git a/packages/react-app/src/app/layout/Header/Title.tsx b/packages/react-app/src/app/layout/Header/Title.tsx index c8add38b8..e2829ae8f 100644 --- a/packages/react-app/src/app/layout/Header/Title.tsx +++ b/packages/react-app/src/app/layout/Header/Title.tsx @@ -1,5 +1,5 @@ import { IState, screen } from '@emeraldwallet/store'; -import { Theme, createStyles } from '@material-ui/core'; +import {Theme, createStyles, Typography} from '@material-ui/core'; import { makeStyles } from '@material-ui/core/styles'; import * as React from 'react'; import { connect } from 'react-redux'; @@ -17,9 +17,11 @@ const useStyles = makeStyles((theme) => brandPart: { color: theme.palette.primary.main, marginRight: '4px', + float: 'left', }, productPart: { color: theme.palette.secondary.main, + float: 'left', }, }), ); @@ -34,8 +36,8 @@ const Component: React.FC = ({ gotoWalletsScreen }) => { return (
- Emerald - Wallet + Emerald + Wallet
); diff --git a/packages/react-app/src/transactions/TxDetails/TxStatus.tsx b/packages/react-app/src/transactions/TxDetails/TxStatus.tsx index 3b162948a..5c5dd58d9 100644 --- a/packages/react-app/src/transactions/TxDetails/TxStatus.tsx +++ b/packages/react-app/src/transactions/TxDetails/TxStatus.tsx @@ -18,6 +18,7 @@ const useStyles = makeStyles((theme) => block: { alignItems: 'center', display: 'flex', + fontFamily: theme.typography.fontFamily, }, error: { color: theme.palette.error.main, diff --git a/packages/react-app/src/transactions/TxHistory/List/Transaction.tsx b/packages/react-app/src/transactions/TxHistory/List/Transaction.tsx index ffdda6380..6330d6682 100644 --- a/packages/react-app/src/transactions/TxHistory/List/Transaction.tsx +++ b/packages/react-app/src/transactions/TxHistory/List/Transaction.tsx @@ -28,7 +28,7 @@ import { TextField, Tooltip, createStyles, - makeStyles, + makeStyles, Typography, } from '@material-ui/core'; import CheckIcon from '@material-ui/icons/Check'; import CloseIcon from '@material-ui/icons/Close'; @@ -103,6 +103,7 @@ const useStyles = makeStyles((theme) => changeItemCoin: { lineHeight: '24px', textAlign: 'right', + color: theme.palette.text.primary, }, container: { boxSizing: 'border-box', @@ -182,6 +183,7 @@ const useStyles = makeStyles((theme) => }, transactionLabelText: { marginRight: 10, + color: theme.palette.text.primary, }, }), ); @@ -334,7 +336,7 @@ const Transaction: React.FC = ({ /> ) : ( <> -
Tx {label}
+ Tx {label} @@ -342,12 +344,12 @@ const Transaction: React.FC = ({ )}
-
+ {sinceTime} /{' '} {confirmations >= CONFIRMED[blockchainCode] ? 'Confirmed' : `${confirmations > 0 ? confirmations : 'No'} confirmation`} -
+ @@ -378,7 +380,7 @@ const Transaction: React.FC = ({ return (
0 ? styles.changeItem : undefined} key={`${change.address}-${index}`}> -
+ {change.direction === Direction.EARN ? '+' : '-'}  {approxZero ? ( @@ -388,7 +390,7 @@ const Transaction: React.FC = ({ amountValue )}{' '} {amountUnit} -
+
{change.walletInstance.id === walletId ? (
@@ -410,9 +412,9 @@ const Transaction: React.FC = ({ {change.walletInstance.name}
)} -
+ {formatFiatAmount(getFiatValue(change.amountValue))} -
+
); diff --git a/packages/react-app/stories/ExampleWeb/Blockchains.stories.tsx b/packages/react-app/stories/ExampleWeb/Blockchains.stories.tsx new file mode 100644 index 000000000..8232043b6 --- /dev/null +++ b/packages/react-app/stories/ExampleWeb/Blockchains.stories.tsx @@ -0,0 +1,51 @@ +import {BlockchainCode} from '@emeraldwallet/core'; +import type {Meta, StoryObj} from '@storybook/react'; +import SelectHDPath from '../../src/create-account/SelectHDPath'; +import {createSeeds, createWallets, initLauncher, ledgerSeedId} from "../wallets"; +import {providerForStore} from "../storeProvider"; +import {createNew} from './data'; +import {accounts} from "@emeraldwallet/store"; + +const { api, backend} = createNew() + +let seedId = 'e23378da-d4b2-4843-ae4d-f42888a11b58'; + +api.vault.addSeedAddress( + seedId, + "m/44'/60'/0'/0/0", + '0xc4cf138d349ead73f7a93306096a626c40f56653', +); +api.vault.addSeedAddress( + seedId, + "m/84'/0'/0'/0/0", + 'bc1qqvc28z0kgc7fmdfu440sd7knpgzytgnurszh6t', +); + +let configure = [ + accounts.actions.setSeedsAction([ + { + id: seedId, + type: 'mnemonic', + createdAt: new Date(), + available: true, + }, + ]), +] + + +export default { + title: 'Example Web / Multiple Blockchains', + component: SelectHDPath, + decorators: [providerForStore(api, backend, [...initLauncher, ...configure])], +} as Meta; + +type Story = StoryObj; + +export const Default: Story = { + name: 'Multiple Blockchains', + args: { + seed: { type: 'id', value: seedId }, + blockchains: [BlockchainCode.BTC, BlockchainCode.ETH], + onChange: (accountId, indexes) => console.log('Account selected', accountId, indexes), + } +}; diff --git a/packages/react-app/stories/ExampleWeb/CancelTx.stories.tsx b/packages/react-app/stories/ExampleWeb/CancelTx.stories.tsx new file mode 100644 index 000000000..3d627f905 --- /dev/null +++ b/packages/react-app/stories/ExampleWeb/CancelTx.stories.tsx @@ -0,0 +1,100 @@ +import {providerForStore} from "../storeProvider"; +import {Meta} from "@storybook/react"; +import * as React from 'react'; +import {accounts, StoredTransaction, tokens, TxAction, txStash} from "@emeraldwallet/store"; +import {CreateTransaction} from "../../src/transaction"; +import {BackendMock, MemoryApiMock} from "../__mocks__"; +import {WalletEntry} from "@emeraldpay/emerald-vault-core"; +import {BlockchainCode, TokenRegistry, workflow} from "@emeraldwallet/core"; +import {State, Status} from "@emeraldwallet/core/lib/persistentState"; + +const api = new MemoryApiMock(); +const backend = new BackendMock(); + +const entries: WalletEntry[] = [ + { + id: '2a19e023-f119-4dab-b2cb-4b3e73fa32c9-1', + address: { + type: 'single', + value: '0x0', + }, + key: { + type: 'hd-path', + hdPath: "m/44'/60'/0'/0/0", + seedId: 'c782ff2b-ba6e-43e2-9e2d-92d05cc37b03', + }, + blockchain: 100, + createdAt: new Date(), + }, +]; + +let actions = [ + accounts.actions.setWalletsAction([ + { + entries, + id: '2a19e023-f119-4dab-b2cb-4b3e73fa32c9', + createdAt: new Date(), + }, + ]), + { + type: 'LAUNCHER/TOKENS', + payload: [ + { + name: 'Wrapped Ether', + blockchain: 100, + address: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', + symbol: 'WETH', + decimals: 18, + type: 'ERC20', + }, + ], + }, + + accounts.actions.setBalanceAction({ + address: '0x0', + balance: '1000000000000000000/WEI', + entryId: '2a19e023-f119-4dab-b2cb-4b3e73fa32c9-1', + }), + tokens.actions.setTokenBalance(BlockchainCode.ETH, '0x0', '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', { + decimals: 18, + symbol: 'WETH', + unitsValue: '1000000000000000000', + }), + + txStash.actions.setTransaction({ + blockchain: BlockchainCode.ETH, + amount: '1000000000000000000/WEI', + asset: 'ETH', + target: workflow.TxTarget.MANUAL, + type: "transfer", + meta: { + type: workflow.TxMetaType.ETHER_CANCEL, + } + }), +]; + +// @ts-ignore +let prevTx: StoredTransaction = { + blockchain: 100, + changes: [], + convertChanges: undefined, + meta: { + txId: "0xc88ffa6d41ac14f583b86aa27674ddcc442c12e1d5bb6bb7aa2c7c77824e50d3", + blockchain: BlockchainCode.ETH, + timestamp: new Date(), + }, + sinceTimestamp: new Date(), + state: State.SUBMITTED, + status: Status.UNKNOWN, + txId: "0xc88ffa6d41ac14f583b86aa27674ddcc442c12e1d5bb6bb7aa2c7c77824e50d3", +} + +export default { + title: 'Example Web / Cancel Tx', + decorators: [providerForStore(api, backend, actions),], +} as Meta; + +export const Default = { + name: 'Cancel Tx', + render: () => +}; diff --git a/packages/react-app/stories/ExampleWeb/Ledger.stories.tsx b/packages/react-app/stories/ExampleWeb/Ledger.stories.tsx new file mode 100644 index 000000000..c3f30aec7 --- /dev/null +++ b/packages/react-app/stories/ExampleWeb/Ledger.stories.tsx @@ -0,0 +1,15 @@ +import { action } from '@storybook/addon-actions'; +import {Meta} from '@storybook/react'; +import * as React from 'react'; +import WaitLedger from '../../src/ledger/WaitLedger'; +import withProvider from '../storeProvider'; + +export default { + title: 'Example Web / Ledger', + decorators: [withProvider], +} as Meta; + +export const Default = { + name: 'Ledger', + render: () => +}; diff --git a/packages/react-app/stories/ExampleWeb/Main.stories.tsx b/packages/react-app/stories/ExampleWeb/Main.stories.tsx index fb7f15e5c..63deb9dbd 100644 --- a/packages/react-app/stories/ExampleWeb/Main.stories.tsx +++ b/packages/react-app/stories/ExampleWeb/Main.stories.tsx @@ -1,29 +1,120 @@ -import {BlockchainCode} from '@emeraldwallet/core'; -import type {Meta, StoryObj} from '@storybook/react'; -import {createSeeds, xpubSeedId} from "../wallets"; -import {providerForStore} from "../storeProvider"; -import {createNew} from './data'; -import HDPathCounter from "../../src/create-account/HDPathCounter"; -import {action} from "@storybook/addon-actions"; +import { BlockchainCode } from '@emeraldwallet/core'; +import { accounts, tokens, application } from '@emeraldwallet/store'; +import * as React from 'react'; +import DetailsPage from '../../src/wallets/WalletDetails'; +import Addresses from '../../src/wallets/WalletDetails/addresses/Addresses'; +import WalletDetails from '../../src/wallets/WalletDetails/WalletDetails'; +import { MemoryApiMock } from '../__mocks__/apiMock'; +import { BackendMock } from '../__mocks__/backendMock'; +import { providerForStore } from '../storeProvider'; +import withTheme from '../themeProvider'; +import {initLauncher, setRates, xpubSeedId} from '../wallets'; +import {Meta} from "@storybook/react"; +import {Wallet} from "@emeraldpay/emerald-vault-core"; +import Header from "../../lib/app/layout/Header/Header"; -const { api, backend} = createNew(); +const api = new MemoryApiMock(); +const backend = new BackendMock(); -const meta: Meta = { - title: 'Example Web', - component: HDPathCounter, - decorators: [ - //@ts-ignore - providerForStore(api, backend, [...createSeeds]) - ] +const wallet: Wallet = { + id: '60ed215e-e487-4245-8027-cd6efe3f9046', + name: 'My Savings', + reserved: [ + { seedId: 'b00e3378-40e7-4eca-b287-a5ead2f747d4', accountId: 2 } + ], + entries: [ + { + key: { type: 'hd-path', seedId: 'b00e3378-40e7-4eca-b287-a5ead2f747d4', hdPath: "m/44'" }, + address: { type: 'single', value: '0x9d8e3fed246384e726b5962577503b916fb246d7' }, + blockchain: 100, + id: '60ed215e-e487-4245-8027-cd6efe3f9046-1', + createdAt: new Date(), + }, + { + // seed: lake cupboard yellow project spoil era educate behind move slide fluid early purpose stone panel + key: { type: 'hd-path', seedId: xpubSeedId, hdPath: "m/84'/0'/3'/0/0" }, + address: { + type: 'xpub', + value: + 'zpub6trp3XEQXBogyby8NUy5xg5qykZAMnC7e4apsn1kNXhtGs3TKVpKS8P4DXMKuy56yKkLwgAYnWsMd9PzGnTdWAHoiwvRLwfAZ58ajkbVudW', + }, + addresses: [], + blockchain: 1, + id: '60ed215e-e487-4245-8027-cd6efe3f9046-2', + createdAt: new Date(), + xpub: [], + }, + ], + createdAt: new Date(), }; -export default meta; -type Story = StoryObj; +const configure = [ + accounts.actions.setBalanceAction({ + address: '0x9d8e3fed246384e726b5962577503b916fb246d7', + balance: '15224100000000000000/WEI', + entryId: '60ed215e-e487-4245-8027-cd6efe3f9046-1', + }), + accounts.actions.setBalanceAction({ + address: 'bc1qqvc28z0kgc7fmdfu440sd7knpgzytgnurszh6t', + balance: '196120051/SAT', + entryId: '60ed215e-e487-4245-8027-cd6efe3f9046-2', + }), + application.actions.setTokens([ + { + address: "0x6B175474E89094C44Da98b954EedeAC495271d0F", + blockchain: 100, + decimals: 18, + name: 'DAI', + stablecoin: true, + symbol: 'DAI', + type: 'ERC20', + }, + { + address: "0xdac17f958d2ee523a2206206994597c13d831ec7", + blockchain: 100, + decimals: 6, + name: 'USDT', + stablecoin: true, + symbol: 'USDT', + type: 'ERC20', + } + ], false), + tokens.actions.setTokenBalance( + BlockchainCode.ETH, + '0x9d8e3fed246384e726b5962577503b916fb246d7', + '0x6B175474E89094C44Da98b954EedeAC495271d0F', + { + decimals: 18, + symbol: 'DAI', + unitsValue: '450000000000000000000', + }, + ), + tokens.actions.setTokenBalance( + BlockchainCode.ETH, + '0x9d8e3fed246384e726b5962577503b916fb246d7', + '0xdAC17F958D2ee523a2206206994597C13D831ec7', + { + decimals: 6, + symbol: 'USDT', + unitsValue: '32001050000', + }, + ), + accounts.actions.setWalletsAction([wallet]), +]; -export const Base: Story = { - name: 'HDPath Counter / Base', - args: { - base: "m/44'/60'/0'/0/0", - onChange: action('changed') - } -}; + +export default { + title: 'Example Web / Wallet', + decorators: [providerForStore(api, backend, [...initLauncher, ...setRates, ...configure])], + component: WalletDetails, +} as Meta; + +export const Default = { + name: 'Wallet', + render: () =>
+
+
+ +
+
, +} diff --git a/packages/react-app/stories/ExampleWeb/SpeedUpTx.stories.tsx b/packages/react-app/stories/ExampleWeb/SpeedUpTx.stories.tsx new file mode 100644 index 000000000..aa5fa23df --- /dev/null +++ b/packages/react-app/stories/ExampleWeb/SpeedUpTx.stories.tsx @@ -0,0 +1,100 @@ +import {providerForStore} from "../storeProvider"; +import {Meta} from "@storybook/react"; +import * as React from 'react'; +import {accounts, StoredTransaction, tokens, TxAction, txStash} from "@emeraldwallet/store"; +import {CreateTransaction} from "../../src/transaction"; +import {BackendMock, MemoryApiMock} from "../__mocks__"; +import {WalletEntry} from "@emeraldpay/emerald-vault-core"; +import {BlockchainCode, TokenRegistry, workflow} from "@emeraldwallet/core"; +import {State, Status} from "@emeraldwallet/core/lib/persistentState"; + +const api = new MemoryApiMock(); +const backend = new BackendMock(); + +const entries: WalletEntry[] = [ + { + id: '2a19e023-f119-4dab-b2cb-4b3e73fa32c9-1', + address: { + type: 'single', + value: '0x0', + }, + key: { + type: 'hd-path', + hdPath: "m/44'/60'/0'/0/0", + seedId: 'c782ff2b-ba6e-43e2-9e2d-92d05cc37b03', + }, + blockchain: 100, + createdAt: new Date(), + }, +]; + +let actions = [ + accounts.actions.setWalletsAction([ + { + entries, + id: '2a19e023-f119-4dab-b2cb-4b3e73fa32c9', + createdAt: new Date(), + }, + ]), + { + type: 'LAUNCHER/TOKENS', + payload: [ + { + name: 'Wrapped Ether', + blockchain: 100, + address: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', + symbol: 'WETH', + decimals: 18, + type: 'ERC20', + }, + ], + }, + + accounts.actions.setBalanceAction({ + address: '0x0', + balance: '1000000000000000000/WEI', + entryId: '2a19e023-f119-4dab-b2cb-4b3e73fa32c9-1', + }), + tokens.actions.setTokenBalance(BlockchainCode.ETH, '0x0', '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', { + decimals: 18, + symbol: 'WETH', + unitsValue: '1000000000000000000', + }), + + txStash.actions.setTransaction({ + blockchain: BlockchainCode.ETH, + amount: '1000000000000000000/WEI', + asset: 'ETH', + target: workflow.TxTarget.MANUAL, + type: "transfer", + meta: { + type: workflow.TxMetaType.ETHER_SPEEDUP, + } + }), +]; + +// @ts-ignore +let prevTx: StoredTransaction = { + blockchain: 100, + changes: [], + convertChanges: undefined, + meta: { + txId: "0xaa27674ddc77824e50d3c442c12e1d5bb6bb7c88ffa6d41ac14f583b86aa2c7c", + blockchain: BlockchainCode.ETH, + timestamp: new Date(), + }, + sinceTimestamp: new Date(), + state: State.SUBMITTED, + status: Status.UNKNOWN, + txId: "0xaa27674ddc77824e50d3c442c12e1d5bb6bb7c88ffa6d41ac14f583b86aa2c7c", +} + +export default { + title: 'Example Web / Speed Up Tx', + decorators: [providerForStore(api, backend, actions),], +} as Meta; + +export const Default = { + name: 'Speed Up Tx', + render: () => +}; diff --git a/packages/react-app/stories/ExampleWeb/StableCoin.stories.tsx b/packages/react-app/stories/ExampleWeb/StableCoin.stories.tsx new file mode 100644 index 000000000..ed3ac6bbf --- /dev/null +++ b/packages/react-app/stories/ExampleWeb/StableCoin.stories.tsx @@ -0,0 +1,80 @@ +import {BlockchainCode} from '@emeraldwallet/core'; +import type {Meta, StoryObj} from '@storybook/react'; +import {createSeeds, initLauncher, setRates, xpubSeedId} from "../wallets"; +import {providerForStore} from "../storeProvider"; +import WalletBalance from "../../src/wallets/WalletDetails/WalletBalance"; +import {BackendMock, MemoryApiMock} from "../__mocks__"; +import {Wallet} from "@emeraldpay/emerald-vault-core"; +import {accounts, application, tokens} from "@emeraldwallet/store"; +import * as React from 'react'; + +const api = new MemoryApiMock(); +const backend = new BackendMock(); + +const wallet: Wallet = { + id: '60ed215e-e487-4245-8027-cd6efe3f9046', + name: 'My Savings', + reserved: [ + { seedId: 'b00e3378-40e7-4eca-b287-a5ead2f747d4', accountId: 2 } + ], + entries: [ + { + key: { type: 'hd-path', seedId: 'b00e3378-40e7-4eca-b287-a5ead2f747d4', hdPath: "m/44'" }, + address: { type: 'single', value: '0x9d8e3fed246384e726b5962577503b916fb246d7' }, + blockchain: 100, + id: '60ed215e-e487-4245-8027-cd6efe3f9046-1', + createdAt: new Date(), + }, + ], + createdAt: new Date(), +}; + +const configure = [ + accounts.actions.setBalanceAction({ + address: '0x9d8e3fed246384e726b5962577503b916fb246d7', + balance: '15224100000000000000/WEI', + entryId: '60ed215e-e487-4245-8027-cd6efe3f9046-1', + }), + tokens.actions.setTokenBalance( + BlockchainCode.ETH, + '0x9d8e3fed246384e726b5962577503b916fb246d7', + '0x6B175474E89094C44Da98b954EedeAC495271d0F', + { + decimals: 18, + symbol: 'DAI', + unitsValue: '450000000000000000000', + }, + ), + tokens.actions.setTokenBalance( + BlockchainCode.ETH, + '0x9d8e3fed246384e726b5962577503b916fb246d7', + '0xdAC17F958D2ee523a2206206994597C13D831ec7', + { + decimals: 6, + symbol: 'USDT', + unitsValue: '32001050000', + }, + ), + tokens.actions.setTokenBalance( + BlockchainCode.ETH, + '0x9d8e3fed246384e726b5962577503b916fb246d7', + '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', + { + decimals: 6, + symbol: 'USDC', + unitsValue: '56011050000', + }, + ), + accounts.actions.setWalletsAction([wallet]), +]; + +export default { + title: 'Example Web / Stable Coin Flexibility', + decorators: [providerForStore(api, backend, [...initLauncher, ...setRates, ...configure])], +} as Meta; + + +export const Default = { + name: 'Stable Coin Flexibility', + render: () => +}; diff --git a/packages/react-app/stories/ExampleWeb/TxHistory.stories.tsx b/packages/react-app/stories/ExampleWeb/TxHistory.stories.tsx new file mode 100644 index 000000000..327add29b --- /dev/null +++ b/packages/react-app/stories/ExampleWeb/TxHistory.stories.tsx @@ -0,0 +1,113 @@ +import { BlockchainCode, PersistentState, blockchainCodeToId } from '@emeraldwallet/core'; +import { txhistory } from '@emeraldwallet/store'; +import {Meta} from '@storybook/react'; +import * as React from 'react'; +import TxHistory from '../../src/transactions/TxHistory'; +import { MemoryApiMock } from '../__mocks__/apiMock'; +import { BackendMock } from '../__mocks__/backendMock'; +import { providerForStore } from '../storeProvider'; +import { createWallets, setRates, wallet3 } from '../wallets'; + +const { ChangeType, Direction, State, Status } = PersistentState; + +const txEthereum1: PersistentState.Transaction = { + blockchain: blockchainCodeToId(BlockchainCode.ETH), + changes: [ + { + address: '0x2', + amount: '797181931000000000', + asset: 'ETH', + direction: Direction.EARN, + type: ChangeType.TRANSFER, + wallet: 'f1fa1c12-5ac0-48f3-a76d-5bfb75be37b4-1', + }, + ], + txId: 'Withdrawn from Coinbase', + state: State.PREPARED, + sinceTimestamp: new Date(Date.now() - 123234), + status: Status.UNKNOWN, +}; + +const txEthereum2: PersistentState.Transaction = { + block: { + blockId: '0x1', + height: 99990, + timestamp: new Date('2023-12-01T11:00:00'), + }, + blockchain: blockchainCodeToId(BlockchainCode.ETH), + changes: [ + { + address: '0x2', + amount: '15610000000000000', + asset: 'ETH', + direction: Direction.SPEND, + type: ChangeType.TRANSFER, + wallet: 'f1fa1c12-5ac0-48f3-a76d-5bfb75be37b4-1', + }, + ], + txId: 'c9351f38...b974e20b', + state: State.PREPARED, + sinceTimestamp: new Date('2023-12-01T11:00:00'), + status: Status.UNKNOWN, +}; + +const txBitcoin1: PersistentState.Transaction = { + blockchain: blockchainCodeToId(BlockchainCode.BTC), + changes: [ + { + address: 'abc', + amount: '16100000', + asset: 'BTC', + direction: Direction.SPEND, + type: ChangeType.TRANSFER, + wallet: 'f1fa1c12-5ac0-48f3-a76d-5bfb75be37b4-1', + }, + ], + txId: 'e3b0c442...ca495991', + state: State.PREPARED, + sinceTimestamp: new Date('2024-01-01T11:00:00'), + status: Status.UNKNOWN, +}; + +const txBitcoin2: PersistentState.Transaction = { + blockchain: blockchainCodeToId(BlockchainCode.BTC), + changes: [ + { + address: 'abc', + amount: '1700000', + asset: 'BTC', + direction: Direction.EARN, + type: ChangeType.TRANSFER, + wallet: 'f1fa1c12-5ac0-48f3-a76d-5bfb75be37b4-1', + }, + ], + sinceTimestamp: new Date('2022-01-01T10:00:00'), + state: State.PREPARED, + status: Status.UNKNOWN, + txId: 'from johnny', +}; + +const api = new MemoryApiMock(); +const backend = new BackendMock(); + +api.txHistory.insertTransactions([txEthereum1, txBitcoin1, txEthereum2, txBitcoin2]); + +export default { + title: 'Example Web / Tx History', + decorators: [ + providerForStore(api, backend, [ + ...setRates, + ...createWallets, + txhistory.actions.loadTransactions(wallet3.id, true), + ]), + ], +} as Meta; + +export const Transactions = { + name: 'Tx History', + render: () => ( +
+ +
+ ) +}; diff --git a/packages/react-app/stories/electron_index.js b/packages/react-app/stories/electron_index.js index bebd9bc22..35796e131 100644 --- a/packages/react-app/stories/electron_index.js +++ b/packages/react-app/stories/electron_index.js @@ -6,7 +6,7 @@ app.commandLine.appendSwitch('remote-debugging-port', '5858') // // To run: -// yarn workspace @emeraldwallet/react-app run storybook +// yarn workspace @emeraldwallet/react-app run storybook:build // yarn workspace @emeraldwallet/react-app run storybook:electron // diff --git a/packages/react-app/stories/wallets.ts b/packages/react-app/stories/wallets.ts index 11df9a362..c9c0a7428 100644 --- a/packages/react-app/stories/wallets.ts +++ b/packages/react-app/stories/wallets.ts @@ -141,6 +141,15 @@ export const initLauncher = [ type: 'ERC20', stablecoin: true, }, + { + name: 'USD Coin', + blockchain: 100, + address: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', + symbol: 'USDC', + decimals: 6, + type: 'ERC20', + stablecoin: true, + }, ], }, ]; @@ -214,8 +223,9 @@ export const setRates = [ settings.actions.setRates({ ETH: '3810.6981', ETC: '31.31', - DAI: '1.001', - USDT: '0.9985', BTC: '68216.29', + "100:0x6b175474e89094c44da98b954eedeac495271d0f": "1.001", //DAI + "100:0xdac17f958d2ee523a2206206994597c13d831ec7": "0.9985", //USDT + "100:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48": "0.9991", //USDC }), ]; diff --git a/packages/store/src/hdpath-preview/sagas.ts b/packages/store/src/hdpath-preview/sagas.ts index bbd1a1a7e..2c9496211 100644 --- a/packages/store/src/hdpath-preview/sagas.ts +++ b/packages/store/src/hdpath-preview/sagas.ts @@ -21,7 +21,7 @@ function* loadAddresses( let addresses: { [hdPath: string]: string } = {}; try { - addresses = yield call(vault.listSeedAddresses, seed, blockchainCodeToId(blockchain), hdPaths); + addresses = yield call([vault, vault.listSeedAddresses], seed, blockchainCodeToId(blockchain), hdPaths); } catch (exception) { console.warn('Failed to get addresses', exception); } diff --git a/packages/ui/src/components/common/Form/FormAccordion.tsx b/packages/ui/src/components/common/Form/FormAccordion.tsx index 9fdcf5574..4f8a077fa 100644 --- a/packages/ui/src/components/common/Form/FormAccordion.tsx +++ b/packages/ui/src/components/common/Form/FormAccordion.tsx @@ -17,6 +17,7 @@ const useStyles = makeStyles((theme) => }, title: { color: theme.palette.text.secondary, + fontFamily: theme.typography.fontFamily, fontSize: 16, fontWeight: 400, padding: 0, diff --git a/packages/ui/src/components/common/Form/FormLabel.tsx b/packages/ui/src/components/common/Form/FormLabel.tsx index 986e0da79..57a702e33 100644 --- a/packages/ui/src/components/common/Form/FormLabel.tsx +++ b/packages/ui/src/components/common/Form/FormLabel.tsx @@ -13,6 +13,7 @@ const styles = (theme: Theme): StyleRules => paddingRight: 30, textAlign: 'right', width: 160, + fontFamily: theme.typography.fontFamily }, top: { alignSelf: 'flex-start', From 700ccc8ae33e397c2fcc7cd408327b53ca473e03 Mon Sep 17 00:00:00 2001 From: Igor Artamonov Date: Thu, 30 May 2024 21:30:53 +0100 Subject: [PATCH 2/5] problem: doesn't see allowance if address is not in lower case --- packages/store/src/allowances/selectors.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/store/src/allowances/selectors.ts b/packages/store/src/allowances/selectors.ts index 6fd7d0c22..d9ed117f8 100644 --- a/packages/store/src/allowances/selectors.ts +++ b/packages/store/src/allowances/selectors.ts @@ -22,7 +22,7 @@ export function getEntriesGroupedAllowances(state: IState, entries: WalletEntry[ if (isEthereumEntry(entry) && entry.address != null) { const blockchainCode = blockchainIdToCode(entry.blockchain); - const { allowedFor = {}, approvedBy = {} } = state[moduleName][blockchainCode]?.[entry.address.value] ?? {}; + const { allowedFor = {}, approvedBy = {} } = state[moduleName][blockchainCode]?.[entry.address.value.toLowerCase()] ?? {}; const allowances = new Map(Object.entries(allowedFor)); From e4e7ea0df570ae945011462dca13d8ccc8be9970 Mon Sep 17 00:00:00 2001 From: Igor Artamonov Date: Thu, 30 May 2024 21:31:55 +0100 Subject: [PATCH 3/5] problem: on allowance screen it's unclear what are the address relations --- .../src/wallets/WalletDetails/WalletAllowance.tsx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/packages/react-app/src/wallets/WalletDetails/WalletAllowance.tsx b/packages/react-app/src/wallets/WalletDetails/WalletAllowance.tsx index 5b183fd96..271772e03 100644 --- a/packages/react-app/src/wallets/WalletDetails/WalletAllowance.tsx +++ b/packages/react-app/src/wallets/WalletDetails/WalletAllowance.tsx @@ -56,6 +56,10 @@ const useStyles = makeStyles((theme) => allowanceAddressIcon: { marginRight: 5, }, + allowanceAddressDescription: { + textAlign: 'right', + display: 'block', + }, allowanceActions: { display: 'flex', justifyContent: 'end', @@ -164,6 +168,9 @@ const WalletAllowance: React.FC = ({ )}
+ + {type === AllowanceType.ALLOWED_FOR ? 'Allowed To Address' : 'Allowed By Address'} +
{type === AllowanceType.ALLOWED_FOR ? ( From 28398700e9f29205a8e76c03361e0204fb64fbd8 Mon Sep 17 00:00:00 2001 From: Igor Artamonov Date: Thu, 30 May 2024 21:32:41 +0100 Subject: [PATCH 4/5] problem: when changing the message type the message field moves up and down --- packages/react-app/src/message/SignMessage.tsx | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/react-app/src/message/SignMessage.tsx b/packages/react-app/src/message/SignMessage.tsx index d0be42c34..a104058d2 100644 --- a/packages/react-app/src/message/SignMessage.tsx +++ b/packages/react-app/src/message/SignMessage.tsx @@ -58,6 +58,9 @@ const useStyles = makeStyles( marginBottom: 10, width: '100%', }, + typeAutoDetected: { + marginLeft: 20, + } }), ); @@ -333,18 +336,15 @@ const SignMessage: React.FC = ({ Unstructured / EIP-191 Structured / EIP-712 - - {messageType === MessageType.AUTO && ( - - -
+ {messageType === MessageType.AUTO && ( -
-
- )} + )} + + Message Date: Thu, 30 May 2024 21:33:37 +0100 Subject: [PATCH 5/5] solution: stories for web demo with ethereum features --- .../ExampleWeb/ERC20Allowance.stories.tsx | 114 ++++++++++++++++++ .../ExampleWeb/ETHSignMessage.stories.tsx | 19 +++ .../stories/ExampleWeb/SwapWETH.stories.tsx | 85 +++++++++++++ .../react-app/stories/__mocks__/vaultMock.ts | 2 - packages/react-app/stories/storeProvider.tsx | 1 - packages/react-app/stories/wallets.ts | 74 +++++++----- packages/store/src/allowances/actions.ts | 10 +- packages/store/src/allowances/reducer.ts | 34 +++--- packages/store/src/allowances/types.ts | 20 ++- 9 files changed, 308 insertions(+), 51 deletions(-) create mode 100644 packages/react-app/stories/ExampleWeb/ERC20Allowance.stories.tsx create mode 100644 packages/react-app/stories/ExampleWeb/ETHSignMessage.stories.tsx create mode 100644 packages/react-app/stories/ExampleWeb/SwapWETH.stories.tsx diff --git a/packages/react-app/stories/ExampleWeb/ERC20Allowance.stories.tsx b/packages/react-app/stories/ExampleWeb/ERC20Allowance.stories.tsx new file mode 100644 index 000000000..db6ee3de3 --- /dev/null +++ b/packages/react-app/stories/ExampleWeb/ERC20Allowance.stories.tsx @@ -0,0 +1,114 @@ +import {providerForStore} from "../storeProvider"; +import {Meta} from "@storybook/react"; +import * as React from 'react'; +import {accounts, allowances, tokens} from "@emeraldwallet/store"; +import {BackendMock, MemoryApiMock} from "../__mocks__"; +import {WalletEntry} from "@emeraldpay/emerald-vault-core"; +import {BlockchainCode} from "@emeraldwallet/core"; +import WalletAllowance from "../../src/wallets/WalletDetails/WalletAllowance"; +import {tokenDAI, tokenWETH} from "../wallets"; + +const api = new MemoryApiMock(); +const backend = new BackendMock(); + +const entries: WalletEntry[] = [ + { + id: '2a19e023-f119-4dab-b2cb-4b3e73fa32c9-1', + address: { + type: 'single', + value: '0x1d1C7DB10aa1a6067Ba81F0Dd6FD4F26FC594f13', + }, + key: { + type: 'hd-path', + hdPath: "m/44'/60'/0'/0/0", + seedId: 'c782ff2b-ba6e-43e2-9e2d-92d05cc37b03', + }, + blockchain: 100, + createdAt: new Date(), + }, +]; + +let actions = [ + accounts.actions.setWalletsAction([ + { + entries, + id: '2a19e023-f119-4dab-b2cb-4b3e73fa32c9', + createdAt: new Date(), + }, + ]), + { + type: 'LAUNCHER/TOKENS', + payload: [ + { + name: 'Wrapped Ether', + blockchain: 100, + address: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', + symbol: 'WETH', + decimals: 18, + type: 'ERC20', + }, + ], + }, + + accounts.actions.setBalanceAction({ + address: '0x0', + balance: '1000000000000000000/WEI', + entryId: '2a19e023-f119-4dab-b2cb-4b3e73fa32c9-1', + }), + tokens.actions.setTokenBalance(BlockchainCode.ETH, '0x0', '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', { + decimals: 18, + symbol: 'WETH', + unitsValue: '1000000000000000000', + }), + + allowances.actions.setAllowance({ + address: '0x1d1C7DB10aa1a6067Ba81F0Dd6FD4F26FC594f13', + allowance: "1000000000000000000", + available: "700000000000000000", + blockchain: BlockchainCode.ETH, + contractAddress: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', + ownerAddress: "0x1d1C7DB10aa1a6067Ba81F0Dd6FD4F26FC594f13", + spenderAddress: "0x7992586aCaEcA5b19B973c1cd12B695131c0B736", + timestamp: Date.now() - 12345678, + }, [ + tokenWETH, tokenDAI + ]), + + allowances.actions.setAllowance({ + address: '0x1d1C7DB10aa1a6067Ba81F0Dd6FD4F26FC594f13', + allowance: "20000000000000000000000", + available: "17500000000000000000", + blockchain: BlockchainCode.ETH, + contractAddress: '0x6B175474E89094C44Da98b954EedeAC495271d0F', + ownerAddress: "0x1d1C7DB10aa1a6067Ba81F0Dd6FD4F26FC594f13", + spenderAddress: "0x7992586aCaEcA5b19B973c1cd12B695131c0B736", + timestamp: Date.now() - 12345678, + }, [ + tokenWETH, tokenDAI + ]), + + allowances.actions.setAllowance({ + address: '0x1d1C7DB10aa1a6067Ba81F0Dd6FD4F26FC594f13', + allowance: "99000000000000000000000000000000000000000000", + available: "9161660000000000000", + blockchain: BlockchainCode.ETH, + contractAddress: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', + ownerAddress: "0xCb1c1a86bcae979B971c192Cc5D2B6551311B73e", + spenderAddress: "0x1d1C7DB10aa1a6067Ba81F0Dd6FD4F26FC594f13", + timestamp: Date.now() - 12345678, + }, [ + tokenWETH, tokenDAI + ]), + +]; + + +export default { + title: 'Example Web / ERC20 Allowance', + decorators: [providerForStore(api, backend, actions),], +} as Meta; + +export const Default = { + name: 'ERC20 Allowance', + render: () => +}; diff --git a/packages/react-app/stories/ExampleWeb/ETHSignMessage.stories.tsx b/packages/react-app/stories/ExampleWeb/ETHSignMessage.stories.tsx new file mode 100644 index 000000000..80b90368b --- /dev/null +++ b/packages/react-app/stories/ExampleWeb/ETHSignMessage.stories.tsx @@ -0,0 +1,19 @@ +import {providerForStore} from "../storeProvider"; +import {Meta} from "@storybook/react"; +import * as React from "react"; +import {BackendMock, MemoryApiMock} from "../__mocks__"; +import SignMessage from "../../src/message/SignMessage"; +import {createWallets} from "../wallets"; + +const api = new MemoryApiMock(); +const backend = new BackendMock(); + +export default { + title: 'Example Web / ETH Sign Message', + decorators: [providerForStore(api, backend, [...createWallets]), ], +} as Meta; + +export const Default = { + name: 'ETH Sign Message', + render: () => +}; diff --git a/packages/react-app/stories/ExampleWeb/SwapWETH.stories.tsx b/packages/react-app/stories/ExampleWeb/SwapWETH.stories.tsx new file mode 100644 index 000000000..82cb4ab66 --- /dev/null +++ b/packages/react-app/stories/ExampleWeb/SwapWETH.stories.tsx @@ -0,0 +1,85 @@ +import {providerForStore} from "../storeProvider"; +import {Meta} from "@storybook/react"; +import * as React from 'react'; +import {accounts, StoredTransaction, tokens, TxAction, txStash} from "@emeraldwallet/store"; +import {CreateTransaction} from "../../src/transaction"; +import {BackendMock, MemoryApiMock} from "../__mocks__"; +import {WalletEntry} from "@emeraldpay/emerald-vault-core"; +import {BlockchainCode, TokenRegistry, workflow} from "@emeraldwallet/core"; +import {State, Status} from "@emeraldwallet/core/lib/persistentState"; + +const api = new MemoryApiMock(); +const backend = new BackendMock(); + +const entries: WalletEntry[] = [ + { + id: '2a19e023-f119-4dab-b2cb-4b3e73fa32c9-1', + address: { + type: 'single', + value: '0x1d1C7DB10aa1a6067Ba81F0Dd6FD4F26FC594f13', + }, + key: { + type: 'hd-path', + hdPath: "m/44'/60'/0'/0/0", + seedId: 'c782ff2b-ba6e-43e2-9e2d-92d05cc37b03', + }, + blockchain: 100, + createdAt: new Date(), + }, +]; + +let actions = [ + accounts.actions.setWalletsAction([ + { + entries, + id: '2a19e023-f119-4dab-b2cb-4b3e73fa32c9', + createdAt: new Date(), + }, + ]), + { + type: 'LAUNCHER/TOKENS', + payload: [ + { + name: 'Wrapped Ether', + blockchain: 100, + address: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', + symbol: 'WETH', + decimals: 18, + type: 'ERC20', + }, + ], + }, + + accounts.actions.setBalanceAction({ + address: '0x0', + balance: '1000000000000000000/WEI', + entryId: '2a19e023-f119-4dab-b2cb-4b3e73fa32c9-1', + }), + tokens.actions.setTokenBalance(BlockchainCode.ETH, '0x0', '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', { + decimals: 18, + symbol: 'WETH', + unitsValue: '1000000000000000000', + }), + + txStash.actions.setTransaction({ + blockchain: BlockchainCode.ETH, + amount: '1000000000000000000/WEI', + asset: 'ETH', + target: workflow.TxTarget.MANUAL, + type: "transfer", + meta: { + type: workflow.TxMetaType.ERC20_CONVERT, + } + }), +]; + + +export default { + title: 'Example Web / ETH to WETH Conversion', + decorators: [providerForStore(api, backend, actions),], +} as Meta; + +export const Default = { + name: 'ETH to WETH Conversion', + render: () => +}; diff --git a/packages/react-app/stories/__mocks__/vaultMock.ts b/packages/react-app/stories/__mocks__/vaultMock.ts index 7f65f7740..788b92728 100644 --- a/packages/react-app/stories/__mocks__/vaultMock.ts +++ b/packages/react-app/stories/__mocks__/vaultMock.ts @@ -73,7 +73,6 @@ export class VaultMock implements IEmeraldVault { readonly vault: MemoryVault; constructor(vault: MemoryVault) { - console.log("create vault mock", vault); this.vault = vault; } @@ -162,7 +161,6 @@ export class VaultMock implements IEmeraldVault { blockchain: number, hdpaths: string[], ): Promise { - console.log("call listSeedAddresses", this); if (typeof seedId == 'object') { if (seedId.type == 'id') { const seed: IdSeedReference = seedId; diff --git a/packages/react-app/stories/storeProvider.tsx b/packages/react-app/stories/storeProvider.tsx index ac49aa8ed..e5b774feb 100644 --- a/packages/react-app/stories/storeProvider.tsx +++ b/packages/react-app/stories/storeProvider.tsx @@ -19,7 +19,6 @@ import { VaultMock } from './__mocks__'; import {DecoratorFunction, Renderer, Args} from "@storybook/types"; function createApi(api: MemoryApiMock): WalletApi { - console.log("create api"); return new ApiMock( new AddressBookMock(api.addressBook), new AllowancesMock(api.allowances), diff --git a/packages/react-app/stories/wallets.ts b/packages/react-app/stories/wallets.ts index c9c0a7428..b52ff5428 100644 --- a/packages/react-app/stories/wallets.ts +++ b/packages/react-app/stories/wallets.ts @@ -1,5 +1,5 @@ import { Wallet } from '@emeraldpay/emerald-vault-core'; -import { BlockchainCode } from '@emeraldwallet/core'; +import {BlockchainCode, TokenData} from '@emeraldwallet/core'; import { accounts, settings, tokens } from '@emeraldwallet/store'; export const ledgerSeedId = '7befa8b6-670d-467a-8ddd-a9615087ba14'; @@ -115,6 +115,47 @@ export const wallet5: Wallet = { createdAt: new Date(), }; +export const tokenDAI: TokenData = { + name: 'Dai Stablecoin', + blockchain: 100, + address: '0x6B175474E89094C44Da98b954EedeAC495271d0F', + symbol: 'DAI', + decimals: 18, + type: 'ERC20', + stablecoin: true, +} + +export const tokenUSDT: TokenData = { + name: 'Tether USD', + blockchain: 100, + address: '0xdAC17F958D2ee523a2206206994597C13D831ec7', + symbol: 'USDT', + decimals: 6, + type: 'ERC20', + stablecoin: true, +} + +export const tokenUSDC: TokenData = { + name: 'USD Coin', + blockchain: 100, + address: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', + symbol: 'USDC', + decimals: 6, + type: 'ERC20', + stablecoin: true, +} + +export const tokenWETH: TokenData = { + name: 'Wrapped Ether', + blockchain: 100, + address: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', + symbol: 'WETH', + decimals: 18, + type: 'ERC20', + stablecoin: false, + pinned: true, +} + export const initLauncher = [ { type: 'LAUNCHER/OPTIONS', @@ -123,33 +164,10 @@ export const initLauncher = [ { type: 'LAUNCHER/TOKENS', payload: [ - { - name: 'Dai Stablecoin', - blockchain: 100, - address: '0x6B175474E89094C44Da98b954EedeAC495271d0F', - symbol: 'DAI', - decimals: 18, - type: 'ERC20', - stablecoin: true, - }, - { - name: 'Tether USD', - blockchain: 100, - address: '0xdAC17F958D2ee523a2206206994597C13D831ec7', - symbol: 'USDT', - decimals: 6, - type: 'ERC20', - stablecoin: true, - }, - { - name: 'USD Coin', - blockchain: 100, - address: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', - symbol: 'USDC', - decimals: 6, - type: 'ERC20', - stablecoin: true, - }, + tokenDAI, + tokenUSDT, + tokenUSDC, + tokenWETH, ], }, ]; diff --git a/packages/store/src/allowances/actions.ts b/packages/store/src/allowances/actions.ts index 5bbb8f280..ce08c04f8 100644 --- a/packages/store/src/allowances/actions.ts +++ b/packages/store/src/allowances/actions.ts @@ -1,5 +1,6 @@ import { Dispatched } from '../types'; -import { ActionTypes, AllowanceRaw, InitAllowanceAction } from './types'; +import {ActionTypes, AllowanceCommon, AllowanceRaw, InitAllowanceAction, SetAllowanceAction} from './types'; +import {TokenData} from "@emeraldwallet/core"; export function initAddressAllowance(allowance: AllowanceRaw): Dispatched { return (dispatch, getState, extra) => { @@ -18,3 +19,10 @@ export function initAddressAllowance(allowance: AllowanceRaw): Dispatched