@exodus/ethereum-api 2.9.0 → 2.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@exodus/ethereum-api",
3
- "version": "2.9.0",
3
+ "version": "2.11.0",
4
4
  "description": "Ethereum Api",
5
5
  "main": "src/index.js",
6
6
  "author": "Exodus Movement, Inc.",
@@ -27,5 +27,5 @@
27
27
  "@exodus/assets-base": "^8.0.136",
28
28
  "@exodus/models": "^8.7.2"
29
29
  },
30
- "gitHead": "9b43c68f9c0ef99d743c5e780356bd1b417b604d"
30
+ "gitHead": "5fc7dbd1598091cb3a3df33b6b20a2a5e9bfbb7e"
31
31
  }
@@ -136,7 +136,8 @@ export function create(defaultURL) {
136
136
  },
137
137
 
138
138
  async sendRawTransaction(data) {
139
- return requestWithRetry('proxy', { method: 'eth_sendRawTransaction', hex: '0x' + data })
139
+ const hex = data.startsWith('0x') ? data : '0x' + data
140
+ return requestWithRetry('proxy', { method: 'eth_sendRawTransaction', hex })
140
141
  },
141
142
 
142
143
  async estimateGas(data, tag = 'latest') {
@@ -153,13 +153,15 @@ export class EthereumMonitor extends BaseMonitor {
153
153
  const assetSource = { asset: this.asset.name, walletAccount }
154
154
 
155
155
  const derivedData = await this.deriveData({ assetSource, tokens })
156
+ const derivedIndex = derivedData.currentAccountState?.index
156
157
 
157
158
  const { allTransactionsFromServer, index } = await getHistoryFromServer({
158
159
  server: this.server,
159
160
  ourWalletAddress: derivedData.ourWalletAddress,
160
161
  minimumConfirmations: derivedData.minimumConfirmations,
161
- index: refresh ? 0 : derivedData.currentAccountState?.index ?? 0,
162
+ index: refresh ? 0 : derivedIndex ?? 0,
162
163
  })
164
+ const hasNewIndex = !derivedIndex || index > derivedIndex
163
165
 
164
166
  const logItemsByAsset = getAllLogItemsByAsset({
165
167
  ourWalletAddress: derivedData.ourWalletAddress,
@@ -186,6 +188,15 @@ export class EthereumMonitor extends BaseMonitor {
186
188
 
187
189
  await this.removeFromTxLog(txsToRemove)
188
190
  await this.updateTxLogByAsset({ logItemsByAsset, walletAccount, refresh })
191
+ if (refresh || hasNewIndex) {
192
+ const unknownTokenAddresses = this._getUnknownTokenAddresses({
193
+ transactions: allTransactionsFromServer,
194
+ tokensByAddress,
195
+ })
196
+ if (unknownTokenAddresses.length > 0) {
197
+ this.emit('unknown-tokens', unknownTokenAddresses)
198
+ }
199
+ }
189
200
  }
190
201
 
191
202
  async updateGasPrice(newGasPrice) {
@@ -244,6 +255,20 @@ export class EthereumMonitor extends BaseMonitor {
244
255
  })
245
256
  }
246
257
 
258
+ _getUnknownTokenAddresses({ transactions, tokensByAddress }) {
259
+ const set = transactions.reduce((acc, txn) => {
260
+ const transfers = txn.erc20 || []
261
+ transfers.forEach((transfer) => {
262
+ const addr = transfer.address.toLowerCase()
263
+ if (!tokensByAddress.has(addr)) {
264
+ acc.add(addr)
265
+ }
266
+ }, acc)
267
+ return acc
268
+ }, new Set())
269
+ return Array.from(set)
270
+ }
271
+
247
272
  async beforeStart() {
248
273
  const addressesByWalletAccount = await this.getReceiveAddressesByWalletAccount()
249
274
  enableWSUpdates({
@@ -1,22 +0,0 @@
1
- import { InMemoryAssetClientInterface } from './in-memory-asset-client-interface'
2
- import assetMap from './assets-for-test-helper'
3
- import assert from 'minimalistic-assert'
4
-
5
- export const createAssetClientInterface = ({ logger, walletPublicKeys }) =>
6
- new InMemoryAssetClientInterface({
7
- logger,
8
- assets: assetMap,
9
- walletAccounts: { exodus0: { index: 0 }, exodus1: { index: 1 } },
10
- wallet: {
11
- genPublicKey: async ({ accountIndex, baseAssetName }) => {
12
- const publicKey = walletPublicKeys[baseAssetName][accountIndex]
13
- assert(
14
- publicKey,
15
- `public key for asset ${baseAssetName} index ${accountIndex} cannot be resolved!`
16
- )
17
- return Promise.resolve({
18
- publicKey,
19
- })
20
- },
21
- },
22
- })
@@ -1,30 +0,0 @@
1
- import { mapValues } from 'lodash'
2
- import rawAssetMap from '@exodus/assets'
3
- import { encodePublic, isEthereumLike } from '@exodus/ethereum-lib'
4
-
5
- const copiedAssetMap = mapValues(rawAssetMap, (rawAsset) => ({ ...rawAsset }))
6
-
7
- export const keys = {
8
- encodePublic,
9
- }
10
-
11
- // simulates how clients transform assets from @exodus/assets
12
- const expandRawAsset = (asset) => {
13
- const rawAsset = rawAssetMap[asset.name]
14
- asset.baseAsset = rawAssetMap[rawAsset.baseAsset.name]
15
- asset.feeAsset = rawAssetMap[rawAsset.feeAsset.name]
16
- if (asset.isCombined) {
17
- asset.combinedAssetNames = asset.combinedAssetNames.filter((assetName) => asset[assetName])
18
- asset.combinedAssets = asset.combinedAssetNames.map((assetName) => asset[assetName])
19
- }
20
- if (isEthereumLike(asset)) {
21
- asset.keys = keys
22
- }
23
- if (asset.contract?.current) {
24
- // transformation hack
25
- asset.contract.address = asset.contract.current
26
- }
27
- return [asset.name, asset]
28
- }
29
-
30
- export default Object.fromEntries(Object.values(copiedAssetMap).map(expandRawAsset))
@@ -1,94 +0,0 @@
1
- export default {
2
- '0x90e481d9a664ebbe4be180d9501962255463036d': [
3
- [
4
- {
5
- blockHash: '0xe8487b0e2a6f8410b2e05536e06fd75eaf2f091d6ab8d91c920b9916673e2757',
6
- blockNumber: '0x10208d9',
7
- timestamp: '0x6256c8f5',
8
- confirmations: 1142596,
9
- addressIndex: 0,
10
- hash: '0xcf8d3f903e38b15ed0a32a0137faed35d74ebc15dec8b99f0300eb72be19b0b0',
11
- nonce: '0x109',
12
- gasPrice: '0x174876e80',
13
- gas: '0x6f952',
14
- gasUsed: '0x5cfc5',
15
- to: '0xc748673057861a797275cd8a068abb95a902e8de',
16
- from: '0xa9866ef5574a256b4b85ad2b80880da2ef1b0011',
17
- value: '0x0',
18
- status: 1,
19
- error: null,
20
- internal: [],
21
- erc20: [
22
- {
23
- events: true,
24
- address: '0xc748673057861a797275cd8a068abb95a902e8de',
25
- from: '0xa9866ef5574a256b4b85ad2b80880da2ef1b0011',
26
- to: '0x90e481d9a664ebbe4be180d9501962255463036d',
27
- value: '0xcc74a8c9c5124',
28
- },
29
- {
30
- events: false,
31
- address: '0xc748673057861a797275cd8a068abb95a902e8de',
32
- from: '0xa9866ef5574a256b4b85ad2b80880da2ef1b0011',
33
- to: '0x90e481d9a664ebbe4be180d9501962255463036d',
34
- value: '0xe32c49c3be860',
35
- },
36
- ],
37
- erc721: [],
38
- data:
39
- '0xa9059cbb00000000000000000000000090e481d9a664ebbe4be180d9501962255463036d000000000000000000000000000000000000000000000000000e32c49c3be860',
40
- },
41
- {
42
- blockHash: '0x499b9ba9c99064eeaded737c8a3135b52a10bbed460a064b14efe08810887ef3',
43
- blockNumber: '0x1051668',
44
- timestamp: '0x6260033c',
45
- confirmations: 942517,
46
- addressIndex: 2,
47
- hash: '0xd9602fd41cb44e8d17e965de0c057245d4cb39c1250a3874b7c9f2dc3c9fe78e',
48
- nonce: '0x4873d6',
49
- gasPrice: '0x2540be400',
50
- gas: '0x32918',
51
- gasUsed: '0x5208',
52
- to: '0x90e481d9a664ebbe4be180d9501962255463036d',
53
- from: '0xa180fe01b906a1be37be6c534a3300785b20d947',
54
- value: '0x21c0331d5dc000',
55
- status: 1,
56
- error: null,
57
- internal: [],
58
- erc20: [],
59
- erc721: [],
60
- data: '0x',
61
- },
62
- {
63
- blockHash: '0x0b4e6b2aa26af46f803e55a644312fcda2b4b905b0023a9b995bdf38ccf0f8f7',
64
- blockNumber: '0x1052328',
65
- timestamp: '0x62602980',
66
- confirmations: 939253,
67
- addressIndex: 3,
68
- hash: '0x7bcca25c1672d3de101a9a848c04413b40667fa77e97b939a366e775b89d62cd',
69
- nonce: '0x88e362',
70
- gasPrice: '0x2540be400',
71
- gas: '0x32918',
72
- gasUsed: '0xc7ab',
73
- to: '0x0e09fabb73bd3ade0a17ecc321fd13a19e81ce82',
74
- from: '0xe2fc31f816a9b94326492132018c3aecc4a93ae1',
75
- value: '0x0',
76
- status: 1,
77
- error: null,
78
- internal: [],
79
- erc20: [
80
- {
81
- events: true,
82
- address: '0x0e09fabb73bd3ade0a17ecc321fd13a19e81ce82',
83
- from: '0xe2fc31f816a9b94326492132018c3aecc4a93ae1',
84
- to: '0x90e481d9a664ebbe4be180d9501962255463036d',
85
- value: '0x1fdd07d5d44c0000',
86
- },
87
- ],
88
- erc721: [],
89
- data:
90
- '0xa9059cbb00000000000000000000000090e481d9a664ebbe4be180d9501962255463036d0000000000000000000000000000000000000000000000001fdd07d5d44c0000',
91
- },
92
- ],
93
- ],
94
- }
@@ -1,166 +0,0 @@
1
- import { EthereumMonitor } from '../ethereum-monitor'
2
- import { size, omit } from 'lodash'
3
- import { AccountState } from '@exodus/models'
4
- import { once } from 'events'
5
- import { bsc as feeData } from '@exodus/ethereum-lib/src/fee-data'
6
- import assetMap from './assets-for-test-helper'
7
- import { createAssetClientInterface } from './asset-client-interface-test-helper'
8
- import { create } from '../../exodus-eth-server/api'
9
-
10
- const EXODUS_BSC_SERVER_URL = 'https://bsc.a.exodus.io/wallet/v1/'
11
-
12
- jest.setTimeout(10000)
13
-
14
- export const logger = {
15
- trace: jest.fn(),
16
- debug: jest.fn(),
17
- log: jest.fn(),
18
- info: jest.fn(),
19
- warn: jest.fn(),
20
- error: jest.fn(),
21
- }
22
-
23
- afterEach(() => {
24
- Object.values(logger).forEach((fn) => fn.mockReset())
25
- })
26
-
27
- const { bsc } = assetMap
28
-
29
- // Replacing default gasPrice to be sure WS will change it
30
- const dummyGasPrice = bsc.currency.Gwei(1) // 1 is the min fee...
31
- const feeDataMock = feeData.update({ gasPrice: dummyGasPrice.toString() })
32
- expect(feeDataMock.gasPrice).toEqual(dummyGasPrice)
33
-
34
- export default class EthereumAccountState extends AccountState {
35
- static defaults = {
36
- cursor: '',
37
- balance: bsc.currency.ZERO,
38
- tokenBalances: {},
39
- }
40
- }
41
-
42
- bsc.api = {
43
- createAccountState: () => EthereumAccountState,
44
- getConfirmationsNumber: () => 2,
45
- getFeeData: () => feeDataMock,
46
- }
47
-
48
- // Fernando's dev wallet. Profile 1 and Profile 2
49
- export const walletPublicKeys = {
50
- bsc: [
51
- Buffer.from('0273c38a3c31c31b361dc8d6b93e56c316e34991c478d3a14ea3fcd1ab552bc25e', 'hex'),
52
- Buffer.from('02f33b1edf1016f6720518c776da30567fc7b7052ae6b596dd22909e0a87164f8d', 'hex'),
53
- ],
54
- }
55
-
56
- describe('bsc monitor', () => {
57
- test('can start monitor and update txs', async () => {
58
- const assetClientInterface = createAssetClientInterface({ logger, walletPublicKeys })
59
- const server = create(EXODUS_BSC_SERVER_URL)
60
- const getHistoryV2 = jest.fn(async (...args) => {
61
- const transactions = await server.getHistoryV2(...args)
62
- return transactions.filter((tx) => {
63
- return parseInt(tx.blockNumber, 16) < 0x1052330
64
- })
65
- })
66
- const monitor = new EthereumMonitor({
67
- interval: 20,
68
- asset: bsc,
69
- assetClientInterface,
70
- logger,
71
- server: { ...server, getHistoryV2 },
72
- })
73
- try {
74
- await monitor.start()
75
- expect(logger.error).not.toBeCalled()
76
- expect(logger.warn).not.toBeCalled()
77
- const toBalanceFromTx = (txSet) => {
78
- return txSet.getMutations().slice(-1)[0].balance
79
- }
80
- // Sintax sugar
81
- const txs = (walletAccount, assetName) => {
82
- return assetClientInterface.getTxLog({ walletAccount, assetName })
83
- }
84
- const state = (walletAccount, assetName) => {
85
- return assetClientInterface.getAccountState({ walletAccount, assetName })
86
- }
87
-
88
- const expectSameValue = (actual, expected) => {
89
- expect(actual.toDefault()).toEqual(expected.toDefault())
90
- expect(actual.equals(expected)).toEqual(true)
91
- }
92
-
93
- expect((await txs('exodus0', 'bsc')).size).toEqual(1)
94
- expect((await txs('exodus0', 'pancakeswap')).size).toEqual(1)
95
- expect((await txs('exodus0', 'babydoge_bsc')).size).toEqual(1)
96
-
97
- expectSameValue(
98
- toBalanceFromTx(await txs('exodus0', 'bsc')),
99
- bsc.currency.baseUnit(9500000000000000)
100
- )
101
- expectSameValue(
102
- toBalanceFromTx(await txs('exodus0', 'pancakeswap')),
103
- assetMap.pancakeswap.currency.defaultUnit(2.296)
104
- )
105
- const txBabyDodge = assetMap.babydoge_bsc.currency.defaultUnit('3596822.721089828')
106
- expectSameValue(toBalanceFromTx(await txs('exodus0', 'babydoge_bsc')), txBabyDodge)
107
-
108
- // Bsc and babydoge_bsc are special. Balance is loaded from getBalance RPC, not from transaction.
109
- // see isRpcBalanceAsset
110
- // It seems eth balances and tokenBalances are not being filled. Clients need to read tx like above
111
- // NOTE THAT THESE BALANCE ASSERTIONS MAY FAIL IF TRANSFERING FUNDS..
112
- expectSameValue(
113
- (await state('exodus0', 'bsc')).balance,
114
- assetMap.bsc.currency.defaultUnit(0.0095)
115
- )
116
- // Baby dodge balance is greater than tx balance due to the offchain rewards...
117
- expect((await state('exodus0', 'bsc')).tokenBalances.babydoge_bsc.gt(txBabyDodge)).toEqual(
118
- true
119
- )
120
- expectSameValue((await state('exodus1', 'bsc')).balance, bsc.currency.baseUnit(0))
121
- expect((await state('exodus1', 'bsc')).tokenBalances).toEqual({
122
- babydoge_bsc: assetMap.babydoge_bsc.currency.baseUnit(0),
123
- })
124
- expect(size(assetClientInterface.states)).toEqual(2)
125
- } finally {
126
- await monitor.stop()
127
- }
128
- expect(logger.error).not.toBeCalled()
129
- expect(logger.warn).not.toBeCalled()
130
- expect(monitor.timer.isRunning).toEqual(false)
131
- })
132
-
133
- test('can start and update gas price', async () => {
134
- // ws is not reliable enough to finish on time.
135
- const server = create(EXODUS_BSC_SERVER_URL)
136
- const assetClientInterface = createAssetClientInterface({ logger, walletPublicKeys })
137
- const monitor = new EthereumMonitor({
138
- interval: 20,
139
- asset: bsc,
140
- assetClientInterface,
141
- logger,
142
- server,
143
- })
144
- try {
145
- expect(await assetClientInterface.getFeeData({ assetName: bsc.name })).toEqual(feeDataMock)
146
-
147
- const oncePromise = once(assetClientInterface, 'fee-config-updated')
148
- await monitor.start()
149
- await oncePromise
150
- // Once started, feeData gets updated
151
- expect(await assetClientInterface.getFeeData({ assetName: bsc.name })).not.toEqual(
152
- feeDataMock
153
- )
154
- // gas price and origin are the changed ones.
155
- expect(
156
- omit(await assetClientInterface.getFeeData({ assetName: bsc.name }), 'gasPrice', 'origin')
157
- ).toEqual(omit(feeDataMock, 'gasPrice', 'origin'))
158
- } finally {
159
- await monitor.stop()
160
- }
161
-
162
- expect(logger.error).not.toBeCalled()
163
- expect(logger.warn).not.toBeCalled()
164
- expect(monitor.timer.isRunning).toEqual(false)
165
- })
166
- })
@@ -1,184 +0,0 @@
1
- import { EthereumMonitor } from '../ethereum-monitor'
2
- import { encodePublic } from '@exodus/ethereum-lib'
3
- import { createAssetClientInterface } from './asset-client-interface-test-helper'
4
- import assetMap from './assets-for-test-helper'
5
- import { AccountState } from '@exodus/models'
6
- import { bsc as feeData } from '@exodus/ethereum-lib/src/fee-data'
7
- import historyReturnValuesForTest from './bsc-history-return-values-for-test-helper'
8
- import { size, cloneDeep } from 'lodash'
9
-
10
- const { bsc } = assetMap
11
-
12
- export default class EthereumAccountState extends AccountState {
13
- static defaults = {
14
- cursor: '',
15
- balance: bsc.currency.ZERO,
16
- tokenBalances: {},
17
- }
18
- }
19
-
20
- bsc.api = {
21
- createAccountState: () => EthereumAccountState,
22
- getConfirmationsNumber: () => 2,
23
- getFeeData: () => feeData,
24
- }
25
-
26
- export const logger = {
27
- trace: jest.fn(),
28
- debug: jest.fn(),
29
- log: jest.fn(),
30
- info: jest.fn(),
31
- warn: jest.fn(),
32
- error: jest.fn((...args) => console.error(args)),
33
- }
34
-
35
- afterEach(() => {
36
- Object.values(logger).forEach((fn) => fn.mockReset())
37
- })
38
-
39
- // Fernando's dev wallet. Profile 1 and Profile 2
40
- export const walletPublicKeys = {
41
- bsc: [
42
- Buffer.from('0273c38a3c31c31b361dc8d6b93e56c316e34991c478d3a14ea3fcd1ab552bc25e', 'hex'),
43
- Buffer.from('02f33b1edf1016f6720518c776da30567fc7b7052ae6b596dd22909e0a87164f8d', 'hex'),
44
- ],
45
- }
46
-
47
- describe('bsc monitor', () => {
48
- test('can create monitor', () => {
49
- const server = {
50
- getURL() {
51
- return 'https://mockMe'
52
- },
53
- ws: { watch: jest.fn(), events: { on: jest.fn() } },
54
-
55
- getHistoryV2: jest.fn(() => {
56
- return Promise.resolve([])
57
- }),
58
- }
59
- const monitor = new EthereumMonitor({
60
- interval: 20,
61
- asset: bsc,
62
- assetClientInterface: createAssetClientInterface({ logger }),
63
- logger,
64
- server: server,
65
- })
66
- expect(monitor.server.getURL()).toEqual('https://mockMe')
67
-
68
- expect(logger.warn).not.toBeCalled()
69
- expect(logger.error).not.toBeCalled()
70
- })
71
-
72
- test('can start and stop monitor using simulated data', async () => {
73
- const assetClientInterface = createAssetClientInterface({ logger, walletPublicKeys })
74
-
75
- const getHistoryV2Returns = cloneDeep(historyReturnValuesForTest)
76
- const server = {
77
- getURL() {
78
- return 'https://mockMe'
79
- },
80
- ws: { watch: jest.fn(), events: { on: jest.fn() }, open: jest.fn() },
81
-
82
- getHistoryV2: jest.fn((address) => {
83
- const history = getHistoryV2Returns[address]
84
- const txPage = history?.shift()
85
- return Promise.resolve(txPage || [])
86
- }),
87
-
88
- balanceOf: jest.fn((walletAddress, contractAddress) => {
89
- // jest doesn't to have when-some-arg-then-some-value kind of mocking
90
- // https://github.com/facebook/jest/issues/6180
91
- const balances = {
92
- [`${encodePublic(walletPublicKeys.bsc[0])}-${
93
- assetMap.babydoge_bsc.contract.address
94
- }`.toLowerCase()]: 3610932917151657,
95
- }
96
- const expectedKey = `${walletAddress}-${contractAddress}`.toLowerCase()
97
- const balance = balances[expectedKey] || 0
98
- return Promise.resolve({
99
- confirmed: {
100
- [contractAddress]: balance,
101
- },
102
- })
103
- }),
104
-
105
- getBalance: jest.fn((walletAddress) => {
106
- const balances = {
107
- [encodePublic(walletPublicKeys.bsc[0]).toLowerCase()]: 10500000000000000,
108
- }
109
- const balance = `${balances[walletAddress.toLowerCase()] || 0}`
110
- return Promise.resolve({ confirmed: { value: balance } })
111
- }),
112
- }
113
-
114
- const monitor = new EthereumMonitor({
115
- interval: 20,
116
- asset: bsc,
117
- assetClientInterface,
118
- logger,
119
- server: server,
120
- })
121
- await monitor.start()
122
- await monitor.stop()
123
- expect(logger.warn).not.toBeCalled()
124
- expect(logger.error).not.toBeCalled()
125
-
126
- const toBalanceFromTx = (txSet) => {
127
- return txSet.getMutations().slice(-1)[0].balance
128
- }
129
-
130
- // Sintax sugar
131
- const txs = (walletAccount, assetName) => {
132
- return assetClientInterface.getTxLog({ walletAccount, assetName })
133
- }
134
- const state = (walletAccount, assetName) => {
135
- return assetClientInterface.getAccountState({ walletAccount, assetName })
136
- }
137
-
138
- const expectSameValue = (actual, expected) => {
139
- expect(actual.toDefault()).toEqual(expected.toDefault())
140
- expect(actual.equals(expected)).toEqual(true)
141
- }
142
-
143
- expect((await txs('exodus0', 'bsc')).size).toEqual(1)
144
- expect((await txs('exodus0', 'pancakeswap')).size).toEqual(1)
145
- expect((await txs('exodus0', 'babydoge_bsc')).size).toEqual(1)
146
-
147
- expectSameValue(toBalanceFromTx(await txs('exodus0', 'bsc')), bsc.currency.defaultUnit(0.0095))
148
- expectSameValue(
149
- toBalanceFromTx(await txs('exodus0', 'pancakeswap')),
150
- assetMap.pancakeswap.currency.defaultUnit(2.296)
151
- )
152
- expectSameValue(
153
- toBalanceFromTx(await txs('exodus0', 'babydoge_bsc')),
154
- assetMap.babydoge_bsc.currency.defaultUnit('3596822.721089828')
155
- )
156
-
157
- // Bsc and babydoge_bsc are special. Balance is loaded from getBalance RPC, not from transaction.
158
- // see isRpcBalanceAsset
159
- // It seems eth balances and tokenBalances are not being filled. Clients need to read tx like above
160
- expectSameValue((await state('exodus0', 'bsc')).balance, bsc.currency.defaultUnit(0.0105))
161
- // balance is grater than transaction balance due to the off-chain rewards.
162
- expect((await state('exodus0', 'bsc')).tokenBalances).toEqual({
163
- babydoge_bsc: assetMap.babydoge_bsc.currency.baseUnit(3610932917151657),
164
- })
165
- expectSameValue((await state('exodus1', 'bsc')).balance, assetMap.bsc.currency.baseUnit(0))
166
- expect((await state('exodus1', 'bsc')).tokenBalances).toEqual({
167
- babydoge_bsc: assetMap.babydoge_bsc.currency.baseUnit(0),
168
- })
169
- expect(size(assetClientInterface.states)).toEqual(2)
170
-
171
- expect(logger.error).not.toBeCalled()
172
- expect(logger.warn).not.toBeCalled()
173
- expect(monitor.timer.isRunning).toEqual(false)
174
- })
175
-
176
- test('validate address', () => {
177
- expect(encodePublic(walletPublicKeys.bsc[0])).toEqual(
178
- '0x90E481d9A664ebbE4Be180d9501962255463036d'
179
- )
180
- expect(encodePublic(walletPublicKeys.bsc[1])).toEqual(
181
- '0xf6c138C36341138dDFC314a11038dA8264B7Ef09'
182
- )
183
- })
184
- })