diff --git a/packages/react-app/.babelrc.json b/packages/react-app/.babelrc.json new file mode 100644 index 000000000..d2ef6ed60 --- /dev/null +++ b/packages/react-app/.babelrc.json @@ -0,0 +1,19 @@ +{ + "sourceType": "module", + "presets": [ + [ + "@babel/preset-env", + { + "targets": { + "chrome": 120, + "electron": 22 + } + } + ], + "@babel/preset-typescript", + "@babel/preset-react" + ], + "plugins": [ + "@babel/plugin-transform-optional-chaining" + ] +} diff --git a/packages/react-app/.storybook/main.js b/packages/react-app/.storybook/main.js index 679bb4e87..3ac8eb343 100644 --- a/packages/react-app/.storybook/main.js +++ b/packages/react-app/.storybook/main.js @@ -1,5 +1,13 @@ -module.exports = { - core: { - builder: 'webpack5', - }, +// see { StorybookConfig } from '@storybook/react-webpack5'; +const config = { + framework: '@storybook/react-webpack5', + stories: [ + '../stories/**/*.stories.tsx' + ], + + docs: { + autodocs: true + } }; + +export default config; diff --git a/packages/react-app/.storybook/preview-head.html b/packages/react-app/.storybook/preview-head.html new file mode 100644 index 000000000..7d9e2fa50 --- /dev/null +++ b/packages/react-app/.storybook/preview-head.html @@ -0,0 +1,10 @@ + diff --git a/packages/react-app/.storybook/preview.tsx b/packages/react-app/.storybook/preview.tsx index b350b65f2..4bb29ba2e 100644 --- a/packages/react-app/.storybook/preview.tsx +++ b/packages/react-app/.storybook/preview.tsx @@ -1,13 +1,16 @@ import {Theme} from '@emeraldwallet/ui'; import {ThemeProvider} from '@material-ui/core/styles'; -import { addDecorator, configure } from '@storybook/react'; import * as React from 'react'; +import { Preview } from '@storybook/react'; -const req = require.context('../stories/', true, /\.tsx$/); +const preview: Preview = { + decorators: [ + (Story) => ( + + + + ), + ], +}; -function loadStories () { - addDecorator((story) => ({story()})); - req.keys().forEach((filename) => req(filename)); -} - -configure(loadStories, module); +export default preview; diff --git a/packages/react-app/.storybook/tsconfig.json b/packages/react-app/.storybook/tsconfig.json index e7a5b13be..0dcfb1b8a 100644 --- a/packages/react-app/.storybook/tsconfig.json +++ b/packages/react-app/.storybook/tsconfig.json @@ -21,6 +21,5 @@ "include": [ "../src/**/*.ts", "../src/**/*.tsx", - "../stories/**/*.tsx" ] } diff --git a/packages/react-app/package.json b/packages/react-app/package.json index f257a28b3..7b431340f 100644 --- a/packages/react-app/package.json +++ b/packages/react-app/package.json @@ -11,7 +11,7 @@ "clean": "rimraf lib/ tsconfig.tsbuildinfo", "compile": "tsc -b", "resources": "copyfiles -u 1 src/**/*.png lib/", - "storybook": "start-storybook -p 9001 -c .storybook --ci", + "storybook:build": "storybook dev -p 9001 -c .storybook --ci", "storybook:electron": "electron stories/electron_index.js", "test": "jest", "test:coverage": "jest --coverage" @@ -52,11 +52,15 @@ "sortablejs": "^1.15.0" }, "devDependencies": { - "@babel/core": "^7.22.9", - "@storybook/addon-actions": "6.5.16", - "@storybook/builder-webpack5": "6.5.16", - "@storybook/manager-webpack5": "6.5.16", - "@storybook/react": "6.5.16", + "@babel/core": "^7.24.6", + "@babel/plugin-transform-optional-chaining": "^7.24.6", + "@babel/preset-env": "^7.24.6", + "@babel/preset-react": "^7.24.6", + "@babel/preset-typescript": "^7.24.6", + "@storybook/addon-actions": "8.1.3", + "@storybook/cli": "^8.1.3", + "@storybook/react": "^8.1.3", + "@storybook/react-webpack5": "^8.1.3", "@testing-library/jest-dom": "^5.17.0", "@testing-library/react": "12.1.5", "@types/enzyme": "^3.10.13", @@ -69,6 +73,7 @@ "@types/react-redux": "^7.1.25", "@types/react-virtualized": "^9.21.22", "@types/sortablejs": "^1.15.1", + "@types/webpack-env": "^1.18.5", "copyfiles": "^2.4.1", "dotenv-webpack": "^8.0.1", "electron": "22.3.27", @@ -82,11 +87,12 @@ "jest-transform-stub": "^2.0.0", "require-from-string": "^2.0.2", "rimraf": "^5.0.1", + "storybook": "8.1.3", "ts-jest": "^29.1.1", "ts-loader": "^9.4.4", "ts-node": "^10.9.1", "typescript": "^5.1.6", - "webpack": "5.74.0" + "webpack": "5.91.0" }, "jest": { "preset": "ts-jest", diff --git a/packages/react-app/stories/ContactForm/index.tsx b/packages/react-app/stories/ContactForm/ContactForm.stories.tsx similarity index 67% rename from packages/react-app/stories/ContactForm/index.tsx rename to packages/react-app/stories/ContactForm/ContactForm.stories.tsx index a0679c1ff..63e4749a6 100644 --- a/packages/react-app/stories/ContactForm/index.tsx +++ b/packages/react-app/stories/ContactForm/ContactForm.stories.tsx @@ -1,19 +1,29 @@ import { Blockchains } from '@emeraldwallet/core'; +import type { Meta, StoryObj } from '@storybook/react'; import { action } from '@storybook/addon-actions'; -import { storiesOf } from '@storybook/react'; import * as React from 'react'; import ContactForm from '../../src/address-book/ContactForm'; -storiesOf('ContactForm', module) - .add('new contact', () => ( +const meta: Meta = { + title: 'ContactForm', + component: ContactForm, +}; +export default meta; + +type Story = StoryObj; + +export const AddContact: Story = { + render: () => - )) - .add('edit', () => ( +}; + +export const EditContact: Story = { + render: () => - )); +} + + diff --git a/packages/react-app/stories/CreateAccount/HDPathCounter.stories.tsx b/packages/react-app/stories/CreateAccount/HDPathCounter.stories.tsx new file mode 100644 index 000000000..88f8dc02f --- /dev/null +++ b/packages/react-app/stories/CreateAccount/HDPathCounter.stories.tsx @@ -0,0 +1,37 @@ +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"; + +const { api, backend} = createNew(); + +const meta: Meta = { + title: 'Create Account', + component: HDPathCounter, + decorators: [ + //@ts-ignore + providerForStore(api, backend, [...createSeeds]) + ] +}; +export default meta; + +type Story = StoryObj; + +export const Base: Story = { + name: 'HDPath Counter / Base', + args: { + base: "m/44'/60'/0'/0/0", + onChange: action('changed') + } +}; + +export const WithDisabled: Story = { + name: 'HDPath Counter / With Disabled', + args: { + base: "m/44'/60'/0'/0/0", + disabled: [0, 3, 4], + onChange: action('changed') + } +}; diff --git a/packages/react-app/stories/CreateAccount/SelectCoins.stories.tsx b/packages/react-app/stories/CreateAccount/SelectCoins.stories.tsx new file mode 100644 index 000000000..ad5877eab --- /dev/null +++ b/packages/react-app/stories/CreateAccount/SelectCoins.stories.tsx @@ -0,0 +1,51 @@ +import {BlockchainCode, Blockchains} from '@emeraldwallet/core'; +import type {Meta, StoryObj} from '@storybook/react'; +import {createSeeds, xpubSeedId} from "../wallets"; +import {providerForStore} from "../storeProvider"; +import {createNew} from './data'; +import SelectCoins from '../../src/create-account/SelectBlockchains'; +import {action} from "@storybook/addon-actions"; + +const { api, backend} = createNew(); + +const meta: Meta = { + title: 'Create Account', + component: SelectCoins, + decorators: [ + //@ts-ignore + providerForStore(api, backend, [...createSeeds]) + ] +}; +export default meta; + +type Story = StoryObj; + +export const Empty: Story = { + name: 'Select Blockchain / Empty', + args: { + multiple: true, + blockchains: [Blockchains[BlockchainCode.ETH], Blockchains[BlockchainCode.ETC]], + enabled: [], + onChange: action('selected') + } +}; + +export const OneSet: Story = { + name: 'Select Blockchain / One Set', + args: { + multiple: true, + blockchains: [Blockchains[BlockchainCode.ETH], Blockchains[BlockchainCode.ETC]], + enabled: [BlockchainCode.ETH], + onChange: action('selected') + } +}; + +export const Single: Story = { + name: 'Select Blockchain / Single', + args: { + multiple: false, + blockchains: [Blockchains[BlockchainCode.ETH], Blockchains[BlockchainCode.ETC]], + enabled: [], + onChange: action('selected') + } +}; diff --git a/packages/react-app/stories/CreateAccount/SelectHDPath.stories.tsx b/packages/react-app/stories/CreateAccount/SelectHDPath.stories.tsx new file mode 100644 index 000000000..1b374dc61 --- /dev/null +++ b/packages/react-app/stories/CreateAccount/SelectHDPath.stories.tsx @@ -0,0 +1,47 @@ +import {BlockchainCode} from '@emeraldwallet/core'; +import type {Meta, StoryObj} from '@storybook/react'; +import SelectHDPath from '../../src/create-account/SelectHDPath'; +import {createSeeds, xpubSeedId} from "../wallets"; +import {providerForStore} from "../storeProvider"; +import {createNew} from './data'; + +const { api, backend} = createNew(); + +const meta: Meta = { + title: 'Create Account', + component: SelectHDPath, + decorators: [ + //@ts-ignore + providerForStore(api, backend, [...createSeeds]) + ] +}; +export default meta; + +type Story = StoryObj; + +export const SelectAccount: Story = { + name: 'Select Account / Base', + args: { + seed: { type: 'id', value: 'e23378da-d4b2-4843-ae4d-f42888a11b58' }, + blockchains: [BlockchainCode.BTC, BlockchainCode.ETH], + onChange: (accountId, indexes) => console.log('Account selected', accountId, indexes), + } +}; + +export const SelectAccountETH: Story = { + name: 'Select Account / Only ETH', + args: { + seed: { type: 'id', value: 'e23378da-d4b2-4843-ae4d-f42888a11b58' }, + blockchains: [BlockchainCode.ETH], + onChange: (accountId, indexes) => console.log('Account selected', accountId, indexes), + } +}; + +export const SelectAccountXpub: Story = { + name: 'Select Account / Xpub', + args: { + seed: { type: 'id', value: xpubSeedId }, + blockchains: [BlockchainCode.BTC, BlockchainCode.ETH], + onChange: (accountId, indexes) => console.log('Account selected', accountId, indexes), + } +}; diff --git a/packages/react-app/stories/CreateAccount/data.ts b/packages/react-app/stories/CreateAccount/data.ts new file mode 100644 index 000000000..2cffb6cad --- /dev/null +++ b/packages/react-app/stories/CreateAccount/data.ts @@ -0,0 +1,65 @@ +import {BackendMock, MemoryApiMock} from "../__mocks__"; +import {BlockchainCode} from "@emeraldwallet/core"; +import {xpubSeedId, wallet3SeedAddresses} from "../wallets"; + +export interface Data { + api: MemoryApiMock; + backend: BackendMock; +} + +export function createNew(): Data { + + console.log("prepare api data"); + + const api = new MemoryApiMock(); + const backend = new BackendMock(); + + api.vault.addSeedAddress( + 'e23378da-d4b2-4843-ae4d-f42888a11b58', + "m/44'/60'/0'/0/0", + '0xc4cf138d349ead73f7a93306096a626c40f56653', + ); + api.vault.addSeedAddress( + 'e23378da-d4b2-4843-ae4d-f42888a11b58', + "m/44'/61'/0'/0/0", + '0x75a32a48a215675f822fca1f9d99dadf7c6ec104', + ); + api.vault.addSeedAddress( + 'e23378da-d4b2-4843-ae4d-f42888a11b58', + "m/44'/60'/1'/0/0", + '0x49dbb473f4fbdc20a4367763351df63553c86824', + ); + api.vault.addSeedAddress( + 'e23378da-d4b2-4843-ae4d-f42888a11b58', + "m/44'/61'/1'/0/0", + '0x2b59a19f1f4de027d039ac3f24e9b73ddf03386f', + ); + api.vault.addSeedAddresses(xpubSeedId, wallet3SeedAddresses()); + + backend.useBlockchains([BlockchainCode.ETH, BlockchainCode.ETC]); + backend.blockchains[BlockchainCode.ETC]?.setBalance( + '0x75a32a48a215675f822fca1f9d99dadf7c6ec104', + 'ETC', + '30400000000000000000', + ); + backend.blockchains[BlockchainCode.ETH]?.setBalance( + '0xc4cf138d349ead73f7a93306096a626c40f56653', + 'ETH', + '150078009050000000', + ); + backend.blockchains[BlockchainCode.ETH]?.setBalance( + '0xc4cf138d349ead73f7a93306096a626c40f56653', + 'DAI', + '250018500000000000000', + ); + backend.blockchains[BlockchainCode.ETH]?.setBalance( + '0xc4cf138d349ead73f7a93306096a626c40f56653', + 'USDT', + '41010000000', + ); + + return { + api, + backend + } +} diff --git a/packages/react-app/stories/CreateAccount/index.tsx b/packages/react-app/stories/CreateAccount/index.tsx deleted file mode 100644 index ded5826ca..000000000 --- a/packages/react-app/stories/CreateAccount/index.tsx +++ /dev/null @@ -1,111 +0,0 @@ -import { BlockchainCode, Blockchains } from '@emeraldwallet/core'; -import { action } from '@storybook/addon-actions'; -import { storiesOf } from '@storybook/react'; -import * as React from 'react'; -import HDPathCounter from '../../src/create-account/HDPathCounter'; -import SelectCoins from '../../src/create-account/SelectBlockchains'; -import SelectHDPath from '../../src/create-account/SelectHDPath'; -import { MemoryApiMock } from '../__mocks__/apiMock'; -import { BackendMock } from '../__mocks__/backendMock'; -import { providerForStore } from '../storeProvider'; -import withTheme from '../themeProvider'; -import { createSeeds, ledgerSeedId } from '../wallets'; - -const api = new MemoryApiMock(); -const backend = new BackendMock(); - -api.vault.addSeedAddress( - 'e23378da-d4b2-4843-ae4d-f42888a11b58', - "m/44'/60'/0'/0/0", - '0xc4cf138d349ead73f7a93306096a626c40f56653', -); -api.vault.addSeedAddress( - 'e23378da-d4b2-4843-ae4d-f42888a11b58', - "m/44'/61'/0'/0/0", - '0x75a32a48a215675f822fca1f9d99dadf7c6ec104', -); -api.vault.addSeedAddress( - 'e23378da-d4b2-4843-ae4d-f42888a11b58', - "m/44'/60'/1'/0/0", - '0x49dbb473f4fbdc20a4367763351df63553c86824', -); -api.vault.addSeedAddress( - 'e23378da-d4b2-4843-ae4d-f42888a11b58', - "m/44'/61'/1'/0/0", - '0x2b59a19f1f4de027d039ac3f24e9b73ddf03386f', -); - -backend.useBlockchains([BlockchainCode.ETH, BlockchainCode.ETC]); -backend.blockchains[BlockchainCode.ETC]?.setBalance( - '0x75a32a48a215675f822fca1f9d99dadf7c6ec104', - 'ETC', - '30400000000000000000/WEI', -); -backend.blockchains[BlockchainCode.ETH]?.setBalance( - '0xc4cf138d349ead73f7a93306096a626c40f56653', - 'ETH', - '150078009050000000/WEI', -); -backend.blockchains[BlockchainCode.ETH]?.setBalance( - '0xc4cf138d349ead73f7a93306096a626c40f56653', - 'DAI', - '250018500000000000000/DAI', -); -backend.blockchains[BlockchainCode.ETH]?.setBalance( - '0xc4cf138d349ead73f7a93306096a626c40f56653', - 'USDT', - '41010000000/USDT', -); - -storiesOf('CreateAccount', module) - .addDecorator(withTheme) - .addDecorator(providerForStore(api, backend, [...createSeeds])) - .add('select account', () => ( - console.log('Account selected', accountId, indexes)} - /> - )) - .add('select account, only ETH', () => ( - console.log('Account selected', accountId, indexes)} - /> - )) - .add('select with slow read of xpub', () => ( - console.log('Account selected', accountId, indexes)} - /> - )) - .add('just HDPath counter', () => ) - .add('just HDPath counter with disabled 0,3,4', () => ( - - )) - .add('select blockchain when empty', () => ( - - )) - .add('select blockchain when one is set', () => ( - - )) - .add('select single blockchain', () => ( - - )); diff --git a/packages/react-app/stories/CreateTransaction/CreateTransaction.stories.tsx b/packages/react-app/stories/CreateTransaction/CreateTransaction.stories.tsx new file mode 100644 index 000000000..e3eaae291 --- /dev/null +++ b/packages/react-app/stories/CreateTransaction/CreateTransaction.stories.tsx @@ -0,0 +1,153 @@ +import { WalletEntry } from '@emeraldpay/emerald-vault-core'; +import { BlockchainCode } from '@emeraldwallet/core'; +import { TxAction, accounts, tokens } from '@emeraldwallet/store'; +import * as React from 'react'; +import { CreateTransaction } from '../../src/transaction'; +import { MemoryApiMock } from '../__mocks__/apiMock'; +import { BackendMock } from '../__mocks__/backendMock'; +import { providerForStore } from '../storeProvider'; +import {Meta} from "@storybook/react"; + +const api = new MemoryApiMock(); +const backend = new BackendMock(); + +const entries: WalletEntry[] = [ + { + id: '2a19e023-f119-4dab-b2cb-4b3e73fa32c9-0', + address: { + type: 'xpub', + value: 'vpub_common', + }, + key: { + type: 'hd-path', + hdPath: "m/84'/1'/0'/0/0", + seedId: 'c782ff2b-ba6e-43e2-9e2d-92d05cc37b03', + }, + xpub: [ + { + role: 'receive', + xpub: 'vpub_receive', + }, + { + role: 'change', + xpub: 'vpub_change', + }, + ], + blockchain: 1, + createdAt: new Date(), + addresses: [], + }, + { + 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(), + }, + { + id: '2a19e023-f119-4dab-b2cb-4b3e73fa32c9-2', + address: { + type: 'single', + value: '0x1', + }, + key: { + type: 'hd-path', + hdPath: "m/44'/61'/0'/0/0'", + seedId: 'c782ff2b-ba6e-43e2-9e2d-92d05cc37b03', + }, + blockchain: 101, + createdAt: new Date(), + }, +]; + +api.vault.addEntry('2a19e023-f119-4dab-b2cb-4b3e73fa32c9-0', { + address: 'addr', + hdPath: "m/84'/1'/0'/1/0", + role: 'change', +}); + +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', + }, + { + name: 'Wrapped Ether', + blockchain: 101, + address: '0x1953cab0E5bFa6D4a9BaD6E05fD46C1CC6527a5a', + symbol: 'WETC', + decimals: 18, + type: 'ERC20', + }, + ], + }, + accounts.actions.setBalanceAction({ + address: 'tb1', + balance: '100000000/SAT', + entryId: '2a19e023-f119-4dab-b2cb-4b3e73fa32c9-0', + utxo: [ + { + address: 'tb1', + txid: 'tx_0', + value: '100000000/SAT', + vout: 0, + }, + ], + }), + accounts.actions.setBalanceAction({ + address: '0x0', + balance: '1000000000000000000/WEI', + entryId: '2a19e023-f119-4dab-b2cb-4b3e73fa32c9-1', + }), + accounts.actions.setBalanceAction({ + address: '0x1', + balance: '1000000000000000000/WEI', + entryId: '2a19e023-f119-4dab-b2cb-4b3e73fa32c9-2', + }), + tokens.actions.setTokenBalance(BlockchainCode.ETH, '0x0', '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', { + decimals: 18, + symbol: 'WETH', + unitsValue: '1000000000000000000', + }), + tokens.actions.setTokenBalance(BlockchainCode.ETC, '0x1', '0x1953cab0E5bFa6D4a9BaD6E05fD46C1CC6527a5a', { + decimals: 18, + symbol: 'WETC', + unitsValue: '1000000000000000000', + }), +]; + +export default { + title: 'Create Transaction', + decorators: [ + providerForStore(api, backend, actions), + ], +} as Meta; + +export const Transfer = () => ; +export const Approve = () => ( + +); +export const Convert = () => ( + +); diff --git a/packages/react-app/stories/CreateTransaction/index.tsx b/packages/react-app/stories/CreateTransaction/index.tsx deleted file mode 100644 index 69488a295..000000000 --- a/packages/react-app/stories/CreateTransaction/index.tsx +++ /dev/null @@ -1,150 +0,0 @@ -import { WalletEntry } from '@emeraldpay/emerald-vault-core'; -import { BlockchainCode } from '@emeraldwallet/core'; -import { TxAction, accounts, tokens } from '@emeraldwallet/store'; -import { storiesOf } from '@storybook/react'; -import * as React from 'react'; -import { CreateTransaction } from '../../src/transaction'; -import { MemoryApiMock } from '../__mocks__/apiMock'; -import { BackendMock } from '../__mocks__/backendMock'; -import { providerForStore } from '../storeProvider'; -import withTheme from '../themeProvider'; - -const api = new MemoryApiMock(); -const backend = new BackendMock(); - -const entries: WalletEntry[] = [ - { - id: '2a19e023-f119-4dab-b2cb-4b3e73fa32c9-0', - address: { - type: 'xpub', - value: 'vpub_common', - }, - key: { - type: 'hd-path', - hdPath: "m/84'/1'/0'/0/0", - seedId: 'c782ff2b-ba6e-43e2-9e2d-92d05cc37b03', - }, - xpub: [ - { - role: 'receive', - xpub: 'vpub_receive', - }, - { - role: 'change', - xpub: 'vpub_change', - }, - ], - blockchain: 1, - createdAt: new Date(), - addresses: [], - }, - { - 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(), - }, - { - id: '2a19e023-f119-4dab-b2cb-4b3e73fa32c9-2', - address: { - type: 'single', - value: '0x1', - }, - key: { - type: 'hd-path', - hdPath: "m/44'/61'/0'/0/0'", - seedId: 'c782ff2b-ba6e-43e2-9e2d-92d05cc37b03', - }, - blockchain: 101, - createdAt: new Date(), - }, -]; - -api.vault.addEntry('2a19e023-f119-4dab-b2cb-4b3e73fa32c9-0', { - address: 'addr', - hdPath: "m/84'/1'/0'/1/0", - role: 'change', -}); - -storiesOf('CreateTransaction', module) - .addDecorator( - providerForStore(api, backend, [ - 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', - }, - { - name: 'Wrapped Ether', - blockchain: 101, - address: '0x1953cab0E5bFa6D4a9BaD6E05fD46C1CC6527a5a', - symbol: 'WETC', - decimals: 18, - type: 'ERC20', - }, - ], - }, - accounts.actions.setBalanceAction({ - address: 'tb1', - balance: '100000000/SAT', - entryId: '2a19e023-f119-4dab-b2cb-4b3e73fa32c9-0', - utxo: [ - { - address: 'tb1', - txid: 'tx_0', - value: '100000000/SAT', - vout: 0, - }, - ], - }), - accounts.actions.setBalanceAction({ - address: '0x0', - balance: '1000000000000000000/WEI', - entryId: '2a19e023-f119-4dab-b2cb-4b3e73fa32c9-1', - }), - accounts.actions.setBalanceAction({ - address: '0x1', - balance: '1000000000000000000/WEI', - entryId: '2a19e023-f119-4dab-b2cb-4b3e73fa32c9-2', - }), - tokens.actions.setTokenBalance(BlockchainCode.ETH, '0x0', '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', { - decimals: 18, - symbol: 'WETH', - unitsValue: '1000000000000000000', - }), - tokens.actions.setTokenBalance(BlockchainCode.ETC, '0x1', '0x1953cab0E5bFa6D4a9BaD6E05fD46C1CC6527a5a', { - decimals: 18, - symbol: 'WETC', - unitsValue: '1000000000000000000', - }), - ]), - ) - .addDecorator(withTheme) - .add('transfer', () => ) - .add('approve', () => ( - - )) - .add('convert', () => ( - - )); diff --git a/packages/react-app/stories/CreateWallet/index.tsx b/packages/react-app/stories/CreateWallet/CreateWallet.stories.tsx similarity index 82% rename from packages/react-app/stories/CreateWallet/index.tsx rename to packages/react-app/stories/CreateWallet/CreateWallet.stories.tsx index d08c56bbe..a8e044439 100644 --- a/packages/react-app/stories/CreateWallet/index.tsx +++ b/packages/react-app/stories/CreateWallet/CreateWallet.stories.tsx @@ -1,7 +1,7 @@ import { SeedDefinition, SeedDescription } from '@emeraldpay/emerald-vault-core'; import { BlockchainCode, Blockchains, IBlockchain } from '@emeraldwallet/core'; import { action } from '@storybook/addon-actions'; -import { storiesOf } from '@storybook/react'; +import {Meta} from '@storybook/react'; import * as React from 'react'; import UnlockSeed from '../../src/create-account/UnlockSeed'; import CreateWalletWizard from '../../src/create-wallet/CreateWalletWizard'; @@ -9,7 +9,6 @@ import { Result } from '../../src/create-wallet/flow/types'; import { MemoryApiMock } from '../__mocks__/apiMock'; import { BackendMock } from '../__mocks__/backendMock'; import { providerForStore } from '../storeProvider'; -import withTheme from '../themeProvider'; const handlers = { onCancel: action('Cancel'), @@ -124,22 +123,20 @@ const blockchains: IBlockchain[] = [ Blockchains[BlockchainCode.BTC], ]; -storiesOf('CreateWallet', module) - .addDecorator(providerForStore(api, backend)) - .addDecorator(withTheme) - .add('empty', () => ) - .add('single seed', () => { - const seed: SeedDescription = { - id: 'e23378da-d4b2-4843-ae4d-f42888a11b58', - type: 'raw', - available: true, - createdAt: new Date(), - }; +export default { + title: 'CreateWallet', + decorators: [providerForStore(api, backend)], +} as Meta; - return ; - }); +export const Empty = () => ; +export const SingleSeed = () => { + const seed: SeedDescription = { + id: 'e23378da-d4b2-4843-ae4d-f42888a11b58', + type: 'raw', + available: true, + createdAt: new Date(), + }; -storiesOf('CreateWallet', module) - .addDecorator(providerForStore(api, backend)) - .addDecorator(withTheme) - .add('unlock seed', () => ); + return ; +}; +export const UnlockingSeed = () => ; diff --git a/packages/react-app/stories/ExampleWeb/Main.stories.tsx b/packages/react-app/stories/ExampleWeb/Main.stories.tsx new file mode 100644 index 000000000..fb7f15e5c --- /dev/null +++ b/packages/react-app/stories/ExampleWeb/Main.stories.tsx @@ -0,0 +1,29 @@ +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"; + +const { api, backend} = createNew(); + +const meta: Meta = { + title: 'Example Web', + component: HDPathCounter, + decorators: [ + //@ts-ignore + providerForStore(api, backend, [...createSeeds]) + ] +}; +export default meta; + +type Story = StoryObj; + +export const Base: Story = { + name: 'HDPath Counter / Base', + args: { + base: "m/44'/60'/0'/0/0", + onChange: action('changed') + } +}; diff --git a/packages/react-app/stories/ExampleWeb/data.ts b/packages/react-app/stories/ExampleWeb/data.ts new file mode 100644 index 000000000..01337574c --- /dev/null +++ b/packages/react-app/stories/ExampleWeb/data.ts @@ -0,0 +1,21 @@ +import {BackendMock, MemoryApiMock} from "../__mocks__"; +import {BlockchainCode} from "@emeraldwallet/core"; +import {xpubSeedId, wallet3SeedAddresses} from "../wallets"; + +export interface Data { + api: MemoryApiMock; + backend: BackendMock; +} + +export function createNew(): Data { + + console.log("prepare api data"); + + const api = new MemoryApiMock(); + const backend = new BackendMock(); + + return { + api, + backend + } +} diff --git a/packages/react-app/stories/InitialSetup/InitialSetup.stories.tsx b/packages/react-app/stories/InitialSetup/InitialSetup.stories.tsx new file mode 100644 index 000000000..be4d1c8b5 --- /dev/null +++ b/packages/react-app/stories/InitialSetup/InitialSetup.stories.tsx @@ -0,0 +1,10 @@ +import * as React from 'react'; +import { Meta } from '@storybook/react'; +import InitialSetup from '../../src/app/onboarding/InitialSetup/InitialSetupView'; + +export default { + title: 'Initial Setup', +} as Meta; + +export const Default = () => ; +export const OpenWallet = () => ; diff --git a/packages/react-app/stories/InitialSetup/index.tsx b/packages/react-app/stories/InitialSetup/index.tsx deleted file mode 100644 index 8545e8c40..000000000 --- a/packages/react-app/stories/InitialSetup/index.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import { storiesOf } from '@storybook/react'; -import * as React from 'react'; -import InitialSetup from '../../src/app/onboarding/InitialSetup/InitialSetupView'; - -storiesOf('InitialSetup', module) - .add('default', () => ()) - .add('open wallet', () => ()); diff --git a/packages/react-app/stories/Landing/Landing.stories.tsx b/packages/react-app/stories/Landing/Landing.stories.tsx new file mode 100644 index 000000000..841bb4113 --- /dev/null +++ b/packages/react-app/stories/Landing/Landing.stories.tsx @@ -0,0 +1,9 @@ +import * as React from 'react'; +import { Meta } from '@storybook/react'; +import Landing from '../../src/app/onboarding/Landing/LandingView'; + +export default { + title: 'Landing', +} as Meta; + +export const Default = () => ; diff --git a/packages/react-app/stories/Landing/index.tsx b/packages/react-app/stories/Landing/index.tsx deleted file mode 100644 index 810f66bfb..000000000 --- a/packages/react-app/stories/Landing/index.tsx +++ /dev/null @@ -1,6 +0,0 @@ -import { storiesOf } from '@storybook/react'; -import * as React from 'react'; -import Landing from '../../src/app/onboarding/Landing/LandingView'; - -storiesOf('Landing', module) - .add('default', () => ()); diff --git a/packages/react-app/stories/LedgerAdditionalAddress/index.tsx b/packages/react-app/stories/LedgerAdditionalAddress/LedgerAdditionalAddress.stories.tsx similarity index 53% rename from packages/react-app/stories/LedgerAdditionalAddress/index.tsx rename to packages/react-app/stories/LedgerAdditionalAddress/LedgerAdditionalAddress.stories.tsx index 92340a493..6d12e22c8 100644 --- a/packages/react-app/stories/LedgerAdditionalAddress/index.tsx +++ b/packages/react-app/stories/LedgerAdditionalAddress/LedgerAdditionalAddress.stories.tsx @@ -1,11 +1,10 @@ +import { Meta } from '@storybook/react'; import { accounts } from '@emeraldwallet/store'; -import { storiesOf } from '@storybook/react'; import * as React from 'react'; import AddHDAddress from '../../src/create-account/AddHDAddress'; import { MemoryApiMock } from '../__mocks__/apiMock'; import { BackendMock } from '../__mocks__/backendMock'; import { providerForStore } from '../storeProvider'; -import withTheme from '../themeProvider'; import { createSeeds, wallet4, wallet5 } from '../wallets'; const api = new MemoryApiMock(); @@ -13,8 +12,10 @@ const backend = new BackendMock(); api.vault.setSeedPassword('b00e3378-40e7-4eca-b287-a5ead2f747d4', 'password'); -storiesOf('LedgerAdditionalAddress', module) - .addDecorator(providerForStore(api, backend, [...createSeeds, accounts.actions.setWalletsAction([wallet4, wallet5])])) - .addDecorator(withTheme) - .add('default', () => ) - .add('ledger', () => ); +export default { + title: 'Ledger Additional Address', + decorators: [providerForStore(api, backend, [...createSeeds, accounts.actions.setWalletsAction([wallet4, wallet5])])], +} as Meta; + +export const Default = () => ; +export const Ledger = () => ; diff --git a/packages/react-app/stories/LedgerWait/LedgerWait.stories.tsx b/packages/react-app/stories/LedgerWait/LedgerWait.stories.tsx new file mode 100644 index 000000000..beb8ab59a --- /dev/null +++ b/packages/react-app/stories/LedgerWait/LedgerWait.stories.tsx @@ -0,0 +1,12 @@ +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: 'Ledger Wait', + decorators: [withProvider], +} as Meta; + +export const Default = () => ; diff --git a/packages/react-app/stories/LedgerWait/index.tsx b/packages/react-app/stories/LedgerWait/index.tsx deleted file mode 100644 index bf45218ce..000000000 --- a/packages/react-app/stories/LedgerWait/index.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import { action } from '@storybook/addon-actions'; -import { storiesOf } from '@storybook/react'; -import * as React from 'react'; -import WaitLedger from '../../src/ledger/WaitLedger'; -import withProvider from '../storeProvider'; -import withTheme from '../themeProvider'; - -storiesOf('WaitLedger', module) - .addDecorator(withProvider) - .addDecorator(withTheme) - .add('default', () => ); diff --git a/packages/react-app/stories/Receive/Receive.stories.tsx b/packages/react-app/stories/Receive/Receive.stories.tsx new file mode 100644 index 000000000..efd94f82f --- /dev/null +++ b/packages/react-app/stories/Receive/Receive.stories.tsx @@ -0,0 +1,19 @@ +import { Meta } from '@storybook/react'; +import * as React from 'react'; +import ReceiveScreen from '../../src/receive/ReceiveScreen'; +import { MemoryApiMock } from '../__mocks__/apiMock'; +import { BackendMock } from '../__mocks__/backendMock'; +import { providerForStore } from '../storeProvider'; +import { createWallets, setBalances, setRates } from '../wallets'; + +const api = new MemoryApiMock(); +const backend = new BackendMock(); + +export default { + title: 'Receive', + decorators: [providerForStore(api, backend, [...setRates, ...createWallets, ...setBalances])], +} as Meta; + +export const Wallet1 = () => ; +export const Wallet2 = () => ; +export const Wallet3 = () => ; diff --git a/packages/react-app/stories/Receive/index.tsx b/packages/react-app/stories/Receive/index.tsx deleted file mode 100644 index 4e3fa988b..000000000 --- a/packages/react-app/stories/Receive/index.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import { storiesOf } from '@storybook/react'; -import * as React from 'react'; -import ReceiveScreen from '../../src/receive/ReceiveScreen'; -import { MemoryApiMock } from '../__mocks__/apiMock'; -import { BackendMock } from '../__mocks__/backendMock'; -import { providerForStore } from '../storeProvider'; -import withTheme from '../themeProvider'; -import { createWallets, setBalances, setRates } from '../wallets'; - -const api = new MemoryApiMock(); -const backend = new BackendMock(); - -storiesOf('Receive', module) - .addDecorator(providerForStore(api, backend, [...setRates, ...createWallets, ...setBalances])) - .addDecorator(withTheme) - .add('wallet 1', () => ) - .add('wallet 2', () => ) - .add('wallet 3', () => ); diff --git a/packages/react-app/stories/Settings/index.tsx b/packages/react-app/stories/Settings/Settings.stories.tsx similarity index 79% rename from packages/react-app/stories/Settings/index.tsx rename to packages/react-app/stories/Settings/Settings.stories.tsx index 7301f432b..4c756e55d 100644 --- a/packages/react-app/stories/Settings/index.tsx +++ b/packages/react-app/stories/Settings/Settings.stories.tsx @@ -1,16 +1,20 @@ -import { storiesOf } from '@storybook/react'; +import {Meta} from '@storybook/react'; import i18n from 'i18next'; import * as React from 'react'; import { ExportResult } from '../../src/settings/Settings/types'; import Settings from '../../src/settings/SettingsForm'; -storiesOf('Settings', module).add('default', () => ( +export default { + title: 'Settings', +} as Meta; + +export const Default = () => str} exportVaultFile={() => Promise.resolve(ExportResult.COMPLETE)} @@ -20,5 +24,4 @@ storiesOf('Settings', module).add('default', () => ( onSubmit={() => Promise.resolve()} showNotification={() => null} updateSeed={() => Promise.resolve(true)} - /> -)); + />; diff --git a/packages/react-app/stories/Total/index.tsx b/packages/react-app/stories/Total/Total.stories.tsx similarity index 77% rename from packages/react-app/stories/Total/index.tsx rename to packages/react-app/stories/Total/Total.stories.tsx index 7557ce183..562bb9ca8 100644 --- a/packages/react-app/stories/Total/index.tsx +++ b/packages/react-app/stories/Total/Total.stories.tsx @@ -1,10 +1,14 @@ import { Wei } from '@emeraldpay/bigamount-crypto'; import { CurrencyAmount } from '@emeraldwallet/core'; -import { storiesOf } from '@storybook/react'; +import {Meta} from '@storybook/react'; import * as React from 'react'; import TotalButton from '../../src/app/layout/Header/TotalButton'; -storiesOf('TotalButton', module).add('default', () => ( +export default { + title: 'Total', +} as Meta; + +export const Default = () => ( ]} loading={false} totalBalance={new CurrencyAmount(0, 'USD')} - /> -)); + />; diff --git a/packages/react-app/stories/TxDetails/index.tsx b/packages/react-app/stories/TxDetails/TxDetails.stories.tsx similarity index 81% rename from packages/react-app/stories/TxDetails/index.tsx rename to packages/react-app/stories/TxDetails/TxDetails.stories.tsx index 9e1aeed84..392000dd9 100644 --- a/packages/react-app/stories/TxDetails/index.tsx +++ b/packages/react-app/stories/TxDetails/TxDetails.stories.tsx @@ -1,6 +1,6 @@ import { BlockchainCode, PersistentState, TokenRegistry, blockchainCodeToId } from '@emeraldwallet/core'; import { StoredTransaction } from '@emeraldwallet/store'; -import { storiesOf } from '@storybook/react'; +import { Meta } from '@storybook/react'; import * as React from 'react'; import TxDetails from '../../src/transactions/TxDetails'; import { MemoryApiMock } from '../__mocks__/apiMock'; @@ -78,9 +78,11 @@ const txBitcoin2 = new StoredTransaction( null, ); -storiesOf('TxDetails', module) - .addDecorator(providerForStore(api, backend)) - .addDecorator(withTheme) - .add('ethereum', () => ) - .add('bitcoin 1', () => ) - .add('bitcoin 2', () => ); +export default { + title: 'Tx Details', + decorators: [providerForStore(api, backend)], +} as Meta; + +export const Ethereum = () => ; +export const Bitcoin1 = () => ; +export const Bitcoin2 = () => ; diff --git a/packages/react-app/stories/TxHistory/index.tsx b/packages/react-app/stories/TxHistory/TxHistory.stories.tsx similarity index 92% rename from packages/react-app/stories/TxHistory/index.tsx rename to packages/react-app/stories/TxHistory/TxHistory.stories.tsx index 2f6e5dbba..c52f549fc 100644 --- a/packages/react-app/stories/TxHistory/index.tsx +++ b/packages/react-app/stories/TxHistory/TxHistory.stories.tsx @@ -1,12 +1,11 @@ import { BlockchainCode, PersistentState, blockchainCodeToId } from '@emeraldwallet/core'; import { txhistory } from '@emeraldwallet/store'; -import { storiesOf } from '@storybook/react'; +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 withTheme from '../themeProvider'; import { createWallets, setRates, wallet3 } from '../wallets'; const { ChangeType, Direction, State, Status } = PersistentState; @@ -125,17 +124,19 @@ const backend = new BackendMock(); api.txHistory.insertTransactions([txEthereum1, txBitcoin1, txEthereum2, txBitcoin2]); -storiesOf('TxHistory', module) - .addDecorator(withTheme) - .addDecorator( +export default { + title: 'Tx History', + decorators: [ providerForStore(api, backend, [ ...setRates, ...createWallets, txhistory.actions.loadTransactions(wallet3.id, true), ]), - ) - .add('transactions', () => ( -
- -
- )); + ], +} as Meta; + +export const Transactions = () => ( +
+ +
+); diff --git a/packages/react-app/stories/WalletDetails/WalletDetails.stories.tsx b/packages/react-app/stories/WalletDetails/WalletDetails.stories.tsx new file mode 100644 index 000000000..ca8032a8c --- /dev/null +++ b/packages/react-app/stories/WalletDetails/WalletDetails.stories.tsx @@ -0,0 +1,75 @@ +import { BlockchainCode } from '@emeraldwallet/core'; +import { accounts, tokens } 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 { createWallets, initLauncher, setRates } from '../wallets'; +import {Meta} from "@storybook/react"; + +const api = new MemoryApiMock(); +const backend = new BackendMock(); + +const setBalances = [ + accounts.actions.setBalanceAction({ + address: '0x9d8e3fed246384e726b5962577503b916fb246d7', + balance: '918522410056000000000000/WEI', + entryId: '1022fd13-3431-4f3b-bce8-109fdab15873-1', + }), + accounts.actions.setBalanceAction({ + address: '0x577503b916fb246d79d8e3fed246384e726b5962', + balance: '498123400000000000000000/WEI', + entryId: '1022fd13-3431-4f3b-bce8-109fdab15873-2', + }), + accounts.actions.setBalanceAction({ + address: '0x9d8e3fed246384e726b5962577503b916fb246d7', + balance: '81852400000000000000/WEI', + entryId: 'f1fa1c12-5ac0-48f3-a76d-5bfb75be37b4-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, + '0xdac17f958d2ee523a2206206994597c13d831ec7', + '0x9d8e3fed246384e726b5962577503b916fb246d7', + { + decimals: 6, + symbol: 'USDT', + unitsValue: '500000000000', + }, + ), +]; + +export default { + title: 'Wallet Details', + decorators: [providerForStore(api, backend, [...initLauncher, ...setRates, ...createWallets, ...setBalances]), withTheme], +} as Meta; + +export const SingleWallet = () => ; +export const WithFewBalances = () => ; +export const WithBitcoin = () => ; +export const AddressesList = () => ; +export const AddressesListWithBTC = () => ; +export const WholePage = () => ; diff --git a/packages/react-app/stories/WalletDetails/index.tsx b/packages/react-app/stories/WalletDetails/index.tsx deleted file mode 100644 index 53d975872..000000000 --- a/packages/react-app/stories/WalletDetails/index.tsx +++ /dev/null @@ -1,78 +0,0 @@ -import { BlockchainCode } from '@emeraldwallet/core'; -import { accounts, tokens } from '@emeraldwallet/store'; -import { storiesOf } from '@storybook/react'; -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 { createWallets, initLauncher, setRates } from '../wallets'; - -const api = new MemoryApiMock(); -const backend = new BackendMock(); - -const setBalances = [ - accounts.actions.setBalanceAction({ - address: '0x9d8e3fed246384e726b5962577503b916fb246d7', - balance: '918522410056000000000000/WEI', - entryId: '1022fd13-3431-4f3b-bce8-109fdab15873-1', - }), - accounts.actions.setBalanceAction({ - address: '0x577503b916fb246d79d8e3fed246384e726b5962', - balance: '498123400000000000000000/WEI', - entryId: '1022fd13-3431-4f3b-bce8-109fdab15873-2', - }), - tokens.actions.setTokenBalance( - BlockchainCode.ETH, - '0x9d8e3fed246384e726b5962577503b916fb246d7', - '0x6B175474E89094C44Da98b954EedeAC495271d0F', - { - decimals: 18, - symbol: 'DAI', - unitsValue: '450000000000000000000', - }, - ), - tokens.actions.setTokenBalance( - BlockchainCode.ETH, - '0xdac17f958d2ee523a2206206994597c13d831ec7', - '0x9d8e3fed246384e726b5962577503b916fb246d7', - { - decimals: 6, - symbol: 'USDT', - unitsValue: '500000000000', - }, - ), -]; - -storiesOf('WalletDetails', module) - .addDecorator(providerForStore(api, backend, [...initLauncher, ...setRates, ...createWallets])) - .addDecorator(withTheme) - .add('single wallet', () => ); - -storiesOf('WalletDetails', module) - .addDecorator(providerForStore(api, backend, [...initLauncher, ...setRates, ...createWallets, ...setBalances])) - .addDecorator(withTheme) - .add('with few balances', () => ); - -storiesOf('WalletDetails', module) - .addDecorator(providerForStore(api, backend, [...initLauncher, ...setRates, ...createWallets, ...setBalances])) - .addDecorator(withTheme) - .add('with bitcoin', () => ); - -storiesOf('WalletDetails', module) - .addDecorator(providerForStore(api, backend, [...initLauncher, ...setRates, ...createWallets, ...setBalances])) - .addDecorator(withTheme) - .add('addresses list', () => ); - -storiesOf('WalletDetails', module) - .addDecorator(providerForStore(api, backend, [...initLauncher, ...setRates, ...createWallets, ...setBalances])) - .addDecorator(withTheme) - .add('addresses list with btc', () => ); - -storiesOf('WalletDetails', module) - .addDecorator(providerForStore(api, backend, [...initLauncher, ...setRates, ...createWallets, ...setBalances])) - .addDecorator(withTheme) - .add('whole page', () => ); diff --git a/packages/react-app/stories/WalletsList/index.tsx b/packages/react-app/stories/WalletsList/WalletList.stories.tsx similarity index 75% rename from packages/react-app/stories/WalletsList/index.tsx rename to packages/react-app/stories/WalletsList/WalletList.stories.tsx index 4088a8c41..8ececf519 100644 --- a/packages/react-app/stories/WalletsList/index.tsx +++ b/packages/react-app/stories/WalletsList/WalletList.stories.tsx @@ -1,12 +1,11 @@ import { BlockchainCode } from '@emeraldwallet/core'; import { accounts, tokens } from '@emeraldwallet/store'; -import { storiesOf } from '@storybook/react'; +import { Meta } from '@storybook/react'; import * as React from 'react'; import WalletList from '../../src/wallets/WalletList'; import { MemoryApiMock } from '../__mocks__/apiMock'; import { BackendMock } from '../__mocks__/backendMock'; import { providerForStore } from '../storeProvider'; -import withTheme from '../themeProvider'; import { createWallets, setRates } from '../wallets'; const api = new MemoryApiMock(); @@ -15,7 +14,7 @@ const backend = new BackendMock(); const setBalances = [ accounts.actions.setBalanceAction({ address: '0x9d8e3fed246384e726b5962577503b916fb246d7', - balance: '918522410056000000000000/WEI', + balance: '918522410000000000000/WEI', entryId: '1022fd13-3431-4f3b-bce8-109fdab15873-1', }), accounts.actions.setBalanceAction({ @@ -25,7 +24,7 @@ const setBalances = [ }), accounts.actions.setBalanceAction({ address: '0x577503b916fb246d79d8e3fed246384e726b5962', - balance: '498123400000000000000000/WEI', + balance: '4981234000000000000000/WEI', entryId: '1022fd13-3431-4f3b-bce8-109fdab15873-2', }), tokens.actions.setTokenBalance( @@ -60,12 +59,14 @@ const setBalances = [ ), ]; -storiesOf('Wallets List', module) - .addDecorator(providerForStore(api, backend, [...setRates, ...createWallets])) - .addDecorator(withTheme) - .add('two wallet - empty', () => ); +export default { + title: 'Wallets List', + decorators: [providerForStore(api, backend, [...setRates, ...createWallets])], +} as Meta; -storiesOf('Wallets List', module) - .addDecorator(providerForStore(api, backend, [...setRates, ...createWallets, ...setBalances])) - .addDecorator(withTheme) - .add('two wallet - with balance', () => ); +export const TwoWalletEmpty = () => ; + +export const TwoWalletWithBalance = { + decorators: [providerForStore(api, backend, [...setRates, ...createWallets, ...setBalances])], + render: () => +}; diff --git a/packages/react-app/stories/__mocks__/vaultMock.ts b/packages/react-app/stories/__mocks__/vaultMock.ts index e03022091..7f65f7740 100644 --- a/packages/react-app/stories/__mocks__/vaultMock.ts +++ b/packages/react-app/stories/__mocks__/vaultMock.ts @@ -51,6 +51,16 @@ export class MemoryVault { this.seedAddresses[seedId][hdpath] = address; } + addSeedAddresses(seedId: Uuid, addresses: Array<[string, string]>): void { + if (this.seeds.indexOf(seedId) < 0) { + this.seedAddresses[seedId] = {}; + this.seeds.push(seedId); + } + + addresses.forEach(([hdpath, address]) => { + this.seedAddresses[seedId][hdpath] = address; + }) + } setSeedPassword(seedId: Uuid, password: string): void { this.passwords[seedId] = password; @@ -63,6 +73,7 @@ export class VaultMock implements IEmeraldVault { readonly vault: MemoryVault; constructor(vault: MemoryVault) { + console.log("create vault mock", vault); this.vault = vault; } @@ -151,6 +162,7 @@ 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/electron_index.js b/packages/react-app/stories/electron_index.js index ded6f15a8..bebd9bc22 100644 --- a/packages/react-app/stories/electron_index.js +++ b/packages/react-app/stories/electron_index.js @@ -7,12 +7,14 @@ app.commandLine.appendSwitch('remote-debugging-port', '5858') // // To run: // yarn workspace @emeraldwallet/react-app run storybook -// electron packages/react-app/stories/electron_index.js +// yarn workspace @emeraldwallet/react-app run storybook:electron // app.on('ready', function () { - mainWindow = new BrowserWindow({ + console.log("Starting Electron app"); + + let mainWindow = new BrowserWindow({ width: 1410, height: 830, allowRunningInsecureContent: true, @@ -26,11 +28,13 @@ app.on('ready', function () { webSecurity: false, contextIsolation: false, }, - }) + }); mainWindow.loadURL('http://localhost:9001') + .then(() => { console.log("Opened Storybook") }) + .catch((err) => { console.error("Error opening Storybook", err) }) installExtension(REACT_DEVELOPER_TOOLS) .then((name) => console.log(`Added Extension: ${name}`)) - .catch((err) => console.log('An error occurred: ', err)); -}) \ No newline at end of file + .catch((err) => console.log('Failed to add Extension: ', err)); +}) diff --git a/packages/react-app/stories/storeProvider.tsx b/packages/react-app/stories/storeProvider.tsx index 07fb521f7..ac49aa8ed 100644 --- a/packages/react-app/stories/storeProvider.tsx +++ b/packages/react-app/stories/storeProvider.tsx @@ -1,12 +1,11 @@ import { WalletApi } from '@emeraldwallet/core'; import { Dispatched, createStore } from '@emeraldwallet/store'; -import { DecoratorFunction } from '@storybook/addons/dist/ts3.9/types'; import * as React from 'react'; import { ReactElement } from 'react'; import { Provider } from 'react-redux'; import { AnyAction } from 'redux'; -import { ApiMock, MemoryApiMock } from './__mocks__/apiMock'; -import { BackendMock } from './__mocks__/backendMock'; +import { ApiMock, MemoryApiMock } from './__mocks__'; +import { BackendMock } from './__mocks__'; import { AddressBookMock, AllowancesMock, @@ -15,10 +14,12 @@ import { TxHistoryMock, TxMetaMock, XPubPosMock, -} from './__mocks__/persistentStateMock'; -import { VaultMock } from './__mocks__/vaultMock'; +} from './__mocks__'; +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), @@ -35,17 +36,17 @@ export function providerForStore( api: MemoryApiMock, backend: BackendMock, actions: Array = [], -): DecoratorFunction { +): DecoratorFunction { const store = createStore(createApi(api), backend); actions?.forEach((action) => store.dispatch(action as AnyAction)); - return (story) => {story()}; + return (story) => ({story()}); } const defaultBackend = new BackendMock(); -const defaultStore = createStore(createApi(new MemoryApiMock()), defaultBackend); +export const defaultStore = createStore(createApi(new MemoryApiMock()), defaultBackend); -const withProvider: DecoratorFunction = (story) => {story()}; +const withProvider: DecoratorFunction = (story) => {story()}; export default withProvider; diff --git a/packages/react-app/stories/themeProvider.tsx b/packages/react-app/stories/themeProvider.tsx index 274fbe08e..7a8f2a83e 100644 --- a/packages/react-app/stories/themeProvider.tsx +++ b/packages/react-app/stories/themeProvider.tsx @@ -1,9 +1,10 @@ import { Theme } from '@emeraldwallet/ui'; import { ThemeProvider } from '@material-ui/core/styles'; -import { DecoratorFunction } from '@storybook/addons'; +import {Addon_DecoratorFunction} from "@storybook/types"; import * as React from 'react'; +import {ReactElement} from "react"; -const withTheme: DecoratorFunction = (story) => ( +const withTheme: Addon_DecoratorFunction = (story) => ( {story()} ); diff --git a/packages/react-app/stories/wallets.ts b/packages/react-app/stories/wallets.ts index b96298fec..11df9a362 100644 --- a/packages/react-app/stories/wallets.ts +++ b/packages/react-app/stories/wallets.ts @@ -3,6 +3,7 @@ import { BlockchainCode } from '@emeraldwallet/core'; import { accounts, settings, tokens } from '@emeraldwallet/store'; export const ledgerSeedId = '7befa8b6-670d-467a-8ddd-a9615087ba14'; +export const xpubSeedId = 'b00e3378-40e7-4eca-b287-a5ead2f747d4'; const wallet1: Wallet = { id: '8ff89b7d-8a73-4ee0-ad5b-8ac1f04a49ef', @@ -45,7 +46,7 @@ const wallet2: Wallet = { export const wallet3: Wallet = { id: 'f1fa1c12-5ac0-48f3-a76d-5bfb75be37b4', - name: 'Another Wallet', + name: 'My Savings', reserved: [{ seedId: 'b00e3378-40e7-4eca-b287-a5ead2f747d4', accountId: 3 }], entries: [ { @@ -57,7 +58,7 @@ export const wallet3: Wallet = { }, { // seed: lake cupboard yellow project spoil era educate behind move slide fluid early purpose stone panel - key: { type: 'hd-path', seedId: 'b00e3378-40e7-4eca-b287-a5ead2f747d4', hdPath: "m/84'/0'/3'/0/0" }, + key: { type: 'hd-path', seedId: xpubSeedId, hdPath: "m/84'/0'/3'/0/0" }, address: { type: 'xpub', value: @@ -73,6 +74,15 @@ export const wallet3: Wallet = { createdAt: new Date(), }; +export function wallet3SeedAddresses(): Array<[string, string]> { + return [ + ['m/84\'/0\'/0\'/0/0', 'bc1qqvc28z0kgc7fmdfu440sd7knpgzytgnurszh6t'], + ['m/84\'/0\'/1\'/0/0', 'bc1q0zsst3yy4k7jx0pv5gry7x0ajppqvkjny3mvg2'], + ['m/84\'/0\'/2\'/0/0', 'bc1q8uq8207k0k5clg2q836jmvfn8usdqej5fwj27f'], + ['m/84\'/0\'/3\'/0/0', 'bc1q4zph0rqgf7tphrdyn7zdrxn0zlkf3ufnhjpjq3'], + ] +} + export const wallet4: Wallet = { id: '5c455045-2259-43b3-8e81-5ec9d2be36d6', name: 'Current Spending (create from 0xF8806A3bF29025e86C6A45E3c2adCf9117c94f05)', @@ -202,10 +212,10 @@ export const setBalances = [ export const setRates = [ settings.actions.setRates({ - ETH: '205.1761', - ETC: '5.234', + ETH: '3810.6981', + ETC: '31.31', DAI: '1.001', USDT: '0.9985', - BTC: '11407.35', + BTC: '68216.29', }), ]; diff --git a/packages/ui/.storybook/main.js b/packages/ui/.storybook/main.js index 679bb4e87..3ac8eb343 100644 --- a/packages/ui/.storybook/main.js +++ b/packages/ui/.storybook/main.js @@ -1,5 +1,13 @@ -module.exports = { - core: { - builder: 'webpack5', - }, +// see { StorybookConfig } from '@storybook/react-webpack5'; +const config = { + framework: '@storybook/react-webpack5', + stories: [ + '../stories/**/*.stories.tsx' + ], + + docs: { + autodocs: true + } }; + +export default config; diff --git a/packages/ui/.storybook/preview.tsx b/packages/ui/.storybook/preview.tsx index 69fbbe7f9..9b5ce2767 100644 --- a/packages/ui/.storybook/preview.tsx +++ b/packages/ui/.storybook/preview.tsx @@ -1,13 +1,16 @@ -import { ThemeProvider } from '@material-ui/core/styles'; -import { addDecorator, configure } from '@storybook/react'; +import {Theme} from '@emeraldwallet/ui'; +import {ThemeProvider} from '@material-ui/core/styles'; import * as React from 'react'; -import theme from '../src/theme'; +import { Preview } from '@storybook/react'; -const req = require.context('../stories/', true, /\.tsx$/); +const preview: Preview = { + decorators: [ + (Story) => ( + + + + ), + ], +}; -function loadStories () { - addDecorator((story) => ({story()})); - req.keys().forEach((filename) => req(filename)); -} - -configure(loadStories, module); +export default preview; diff --git a/packages/ui/.storybook/tsconfig.json b/packages/ui/.storybook/tsconfig.json index e94586b2d..e41d1d6a2 100644 --- a/packages/ui/.storybook/tsconfig.json +++ b/packages/ui/.storybook/tsconfig.json @@ -22,6 +22,5 @@ "include": [ "../src/**/*.ts", "../src/**/*.tsx", - "../stories/**/*.tsx" ] } diff --git a/packages/ui/.storybook/webpack.config.js b/packages/ui/.storybook/webpack.config.js index 1881e3109..1841ff1f7 100644 --- a/packages/ui/.storybook/webpack.config.js +++ b/packages/ui/.storybook/webpack.config.js @@ -33,6 +33,7 @@ module.exports = ({ config }) => { config.resolve.fallback.https = require.resolve('https-browserify'); config.resolve.fallback.stream = require.resolve('stream-browserify'); config.resolve.fallback.zlib = require.resolve('browserify-zlib'); + config.resolve.fallback._stream_transform = require.resolve('readable-stream'); return config; }; diff --git a/packages/ui/package.json b/packages/ui/package.json index 4322eef12..4ea6ca1a6 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -10,7 +10,7 @@ "build": "yarn clean && yarn compile", "clean": "rimraf lib/ tsconfig.tsbuildinfo", "compile": "tsc -b", - "storybook": "start-storybook -p 9001 -c .storybook", + "storybook:build": "storybook dev -p 9001 -c .storybook", "test": "jest --env=jsdom", "test:coverage": "jest --env=jsdom --coverage" }, @@ -34,11 +34,14 @@ "sortablejs": "^1.15.0" }, "devDependencies": { - "@babel/core": "^7.22.9", - "@storybook/addon-actions": "6.5.16", - "@storybook/builder-webpack5": "6.5.16", - "@storybook/manager-webpack5": "6.5.16", - "@storybook/react": "6.5.16", + "@babel/core": "^7.24.6", + "@babel/preset-env": "^7.24.6", + "@babel/preset-react": "^7.24.6", + "@babel/preset-typescript": "^7.24.6", + "@storybook/addon-actions": "8.1.3", + "@storybook/cli": "^8.1.3", + "@storybook/react": "8.1.3", + "@storybook/react-webpack5": "8.1.3", "@testing-library/react": "12.1.5", "@types/jest": "^29.5.3", "@types/node": "^20.4.5", @@ -54,13 +57,14 @@ "jest": "^29.6.2", "jest-canvas-mock": "^2.5.2", "jest-transform-stub": "^2.0.0", + "readable-stream": "^4.5.2", "require-from-string": "^2.0.2", "rimraf": "^5.0.1", "ts-jest": "^29.1.1", "ts-loader": "^9.4.4", "ts-node": "^10.9.1", "typescript": "^5.1.6", - "webpack": "5.74.0" + "webpack": "5.91.0" }, "jest": { "preset": "ts-jest", diff --git a/packages/ui/src/components/common/ErrorDialog/ErrorDialog.tsx b/packages/ui/src/components/common/ErrorDialog/ErrorDialog.tsx index 4a84c44db..507f35876 100644 --- a/packages/ui/src/components/common/ErrorDialog/ErrorDialog.tsx +++ b/packages/ui/src/components/common/ErrorDialog/ErrorDialog.tsx @@ -1,4 +1,4 @@ -import { Dialog, DialogActions, DialogContent } from '@material-ui/core'; +import { Dialog, DialogActions, DialogContent, Typography } from '@material-ui/core'; import * as React from 'react'; import Button from '../Button'; @@ -16,10 +16,10 @@ export interface DispatchProps { const ErrorDialog: React.FC = ({ error, message, open, handleClose, handleSubmit }) => ( -

+ ERROR: An unexpected error has occurred. Please restart the Emerald Wallet. -

-

The error was: {message}

+ + The error was: {message}