@rango-dev/widget-embedded 0.25.0 → 0.25.1-next.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/CHANGELOG.md CHANGED
@@ -1,3 +1,22 @@
1
+ # [0.25.0](https://github.com/rango-exchange/rango-client/compare/widget-embedded@0.24.1...widget-embedded@0.25.0) (2024-04-09)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * address tooltips position ([5ee60d1](https://github.com/rango-exchange/rango-client/commit/5ee60d1622dab29091d97578d417a2187f2ca6cf))
7
+ * correct showing wallets on mobile screens ([89ead7f](https://github.com/rango-exchange/rango-client/commit/89ead7f68e88352dfd69c2a3d1c6cb0b8cf2e5d5))
8
+ * fix export refresh modal ([0c0ec6c](https://github.com/rango-exchange/rango-client/commit/0c0ec6c7f22116a9b5d5c8d2b6a74ebf421fc015))
9
+ * fix widget event hook ([c8547b6](https://github.com/rango-exchange/rango-client/commit/c8547b6a31354afe13aa32c0b72be5b62b3f0d67))
10
+
11
+
12
+ ### Features
13
+
14
+ * attach config object to window for debugging purposes ([70597b7](https://github.com/rango-exchange/rango-client/commit/70597b78e31ef2da1ef2d20ed398e5bdf0b59a63))
15
+ * implement hover state for full-expanded-route ([1c851d7](https://github.com/rango-exchange/rango-client/commit/1c851d7c62b71fe8f4aa6c05edbc0d6cc78d5437))
16
+ * show a modal with page reload when meta hasn't loaded ([0d3842f](https://github.com/rango-exchange/rango-client/commit/0d3842f9c2d7210cfd5a967d1f0e663ef3125421))
17
+
18
+
19
+
1
20
  ## [0.24.1](https://github.com/rango-exchange/rango-client/compare/widget-embedded@0.24.0...widget-embedded@0.24.1) (2024-03-12)
2
21
 
3
22
 
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=data.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"data.test.d.ts","sourceRoot":"","sources":["../../../src/store/slices/data.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,30 @@
1
+ import type { AppStoreState } from '../store/app';
2
+ import type { WidgetConfig } from '../types';
3
+ import type { BlockchainMeta, EvmBlockchainMeta, Token } from 'rango-sdk';
4
+ export declare function createToken(options?: {
5
+ blockchains?: string[];
6
+ }): {
7
+ address: string | null;
8
+ blockchain: string;
9
+ coinSource: string | null;
10
+ coinSourceUrl: string | null;
11
+ decimals: number;
12
+ usdPrice: number | null;
13
+ isPopular: boolean;
14
+ image: string;
15
+ symbol: string;
16
+ name: string | null;
17
+ supportedSwappers: string[] | undefined;
18
+ isSecondaryCoin: boolean;
19
+ };
20
+ export declare function createTokens(count: number, options?: {
21
+ blockchains?: string[];
22
+ }): Token[];
23
+ export declare function createEvmBlockchain(): EvmBlockchainMeta;
24
+ export declare function createEvmBlockchains(count: number): EvmBlockchainMeta[];
25
+ export declare function createInitialAppStore(): {
26
+ _tokens: Token[];
27
+ _blockchainsMapByName: Map<string, BlockchainMeta>;
28
+ };
29
+ export declare function updateAppStoreConfig(appStoreState: AppStoreState, config: Partial<WidgetConfig>): AppStoreState;
30
+ //# sourceMappingURL=fixtures.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fixtures.d.ts","sourceRoot":"","sources":["../../src/test-utils/fixtures.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,KAAK,EAAE,cAAc,EAAE,iBAAiB,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AA6I1E,wBAAgB,WAAW,CAAC,OAAO,CAAC,EAAE;IAAE,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE;;;;;;;;;;;;;EAmB/D;AACD,wBAAgB,YAAY,CAC1B,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE;IACR,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;CACxB,GACA,KAAK,EAAE,CAIT;AAED,wBAAgB,mBAAmB,IAAI,iBAAiB,CA2CvD;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,iBAAiB,EAAE,CAIvE;AAED,wBAAgB,qBAAqB;;;EAYpC;AAED,wBAAgB,oBAAoB,CAClC,aAAa,EAAE,aAAa,EAC5B,MAAM,EAAE,OAAO,CAAC,YAAY,CAAC,GAC5B,aAAa,CAOf"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rango-dev/widget-embedded",
3
- "version": "0.25.0",
3
+ "version": "0.25.1-next.0",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "source": "./src/index.ts",
@@ -16,7 +16,10 @@
16
16
  "ts-check": "tsc --declaration --emitDeclarationOnly -p ./tsconfig.json",
17
17
  "clean": "rimraf dist",
18
18
  "format": "prettier --write '{.,src}/**/*.{ts,tsx}'",
19
- "lint": "eslint \"**/*.{ts,tsx}\" --ignore-path ../../.eslintignore"
19
+ "lint": "eslint \"**/*.{ts,tsx}\" --ignore-path ../../.eslintignore",
20
+ "test": "vitest",
21
+ "test:watch": "vitest --watch",
22
+ "test:coverage": "vitest run --coverage"
20
23
  },
21
24
  "dependencies": {
22
25
  "@lingui/core": "4.2.1",
@@ -49,4 +52,4 @@
49
52
  "publishConfig": {
50
53
  "access": "public"
51
54
  }
52
- }
55
+ }
@@ -0,0 +1,349 @@
1
+ import type { AppStoreState } from '../app';
2
+ import type { EvmBlockchainMeta, Token } from 'rango-sdk';
3
+
4
+ import { assert, beforeEach, describe, expect, test } from 'vitest';
5
+
6
+ import {
7
+ createEvmBlockchain,
8
+ createInitialAppStore,
9
+ createToken,
10
+ updateAppStoreConfig,
11
+ } from '../../test-utils/fixtures';
12
+ import { createAppStore } from '../app';
13
+
14
+ let appStoreState: AppStoreState;
15
+ let customTokens: [Token, Token, Token];
16
+ let rangoBlockchain: EvmBlockchainMeta;
17
+
18
+ beforeEach(() => {
19
+ rangoBlockchain = createEvmBlockchain();
20
+
21
+ customTokens = [
22
+ {
23
+ ...createToken(),
24
+ symbol: 'RNG',
25
+ name: 'Rango',
26
+ blockchain: rangoBlockchain.name,
27
+ address: '0x0000000000000000068701000000000000000000',
28
+ isSecondaryCoin: false,
29
+ isPopular: false,
30
+ },
31
+ {
32
+ ...createToken(),
33
+ symbol: 'DJG',
34
+ name: 'Django',
35
+ blockchain: rangoBlockchain.name,
36
+ isSecondaryCoin: false,
37
+ isPopular: false,
38
+ },
39
+ {
40
+ ...createToken(),
41
+ symbol: 'RABO',
42
+ name: 'Rainbow',
43
+ blockchain: rangoBlockchain.name,
44
+ isSecondaryCoin: false,
45
+ isPopular: false,
46
+ },
47
+ ];
48
+
49
+ const initData = createInitialAppStore();
50
+ initData._blockchainsMapByName.set(rangoBlockchain.name, rangoBlockchain);
51
+ customTokens.forEach((token) => initData._tokens.push(token));
52
+
53
+ const appStore = createAppStore();
54
+ appStore.setState(initData);
55
+ appStoreState = appStore.getState();
56
+ });
57
+
58
+ describe('check sorting tokens is working correctly in app store', () => {
59
+ test('put pinned tokens first', () => {
60
+ const rangoToken = customTokens[0];
61
+
62
+ appStoreState = updateAppStoreConfig(appStoreState, {
63
+ from: {
64
+ pinnedTokens: [
65
+ {
66
+ symbol: rangoToken.symbol,
67
+ address: rangoToken.address,
68
+ blockchain: rangoToken.blockchain,
69
+ },
70
+ ],
71
+ },
72
+ });
73
+
74
+ const tokens = appStoreState.tokens({
75
+ type: 'source',
76
+ });
77
+
78
+ const firstResult = tokens[0].symbol;
79
+ expect(firstResult).toBe(rangoToken.symbol);
80
+ });
81
+
82
+ test('put tokens with balances first', () => {
83
+ const rangoToken = customTokens[0];
84
+
85
+ const tokens = appStoreState.tokens({
86
+ type: 'source',
87
+ getBalanceFor: (token: Token) => {
88
+ if (token.symbol === rangoToken.symbol) {
89
+ return {
90
+ amount: '100',
91
+ decimals: 12,
92
+ usdValue: '5000',
93
+ };
94
+ }
95
+ return null;
96
+ },
97
+ });
98
+
99
+ const firstResult = tokens[0].symbol;
100
+ expect(firstResult).toBe(rangoToken.symbol);
101
+ });
102
+
103
+ test('put native tokens first', () => {
104
+ const rangoToken = customTokens[0];
105
+ appStoreState._blockchainsMapByName.set(rangoToken.blockchain, {
106
+ ...rangoBlockchain,
107
+ feeAssets: [
108
+ {
109
+ address: rangoToken.address,
110
+ blockchain: rangoToken.blockchain,
111
+ symbol: rangoToken.symbol,
112
+ },
113
+ ],
114
+ });
115
+
116
+ const tokens = appStoreState.tokens({
117
+ type: 'source',
118
+ });
119
+
120
+ const firstResult = tokens[0].symbol;
121
+ expect(firstResult).toBe(rangoToken.symbol);
122
+ });
123
+
124
+ test('put popular tokens first', () => {
125
+ const tokens = appStoreState.tokens({
126
+ type: 'source',
127
+ });
128
+ const popularTokensCount = tokens.reduce((previousValue, current) => {
129
+ if (current.isPopular) {
130
+ return previousValue + 1;
131
+ }
132
+ return previousValue;
133
+ }, 0);
134
+
135
+ /*
136
+ * Getting an slice of tokens which is equals to how many popular tokens exist
137
+ * then we can check all of them should be on top of the list
138
+ */
139
+ const result = tokens.slice(0, popularTokensCount);
140
+ assert(result.every((token) => token.isPopular === true));
141
+ });
142
+
143
+ test('put secondary tokens at the end of list', () => {
144
+ const tokens = appStoreState.tokens({
145
+ type: 'source',
146
+ });
147
+ expect(tokens[tokens.length - 1]?.isSecondaryCoin).toBe(true);
148
+ });
149
+
150
+ test('put popular token with lowest blockchain sort at first', () => {
151
+ const rangoToken = customTokens[0];
152
+ const rangoIndex = appStoreState._tokens.findIndex(
153
+ (tokenItem) => tokenItem.symbol === rangoToken.symbol
154
+ );
155
+ appStoreState._tokens[rangoIndex].isPopular = true;
156
+ appStoreState._blockchainsMapByName.set(rangoToken.blockchain, {
157
+ ...rangoBlockchain,
158
+ sort: 0,
159
+ });
160
+
161
+ const tokens = appStoreState.tokens({
162
+ type: 'source',
163
+ });
164
+
165
+ const firstResult = tokens[0].symbol;
166
+ expect(firstResult).toBe(rangoToken.symbol);
167
+ });
168
+
169
+ test('put pinned token first and tokens with balances second', () => {
170
+ const rangoToken = customTokens[0];
171
+ const djangoToken = customTokens[1];
172
+
173
+ appStoreState = updateAppStoreConfig(appStoreState, {
174
+ from: {
175
+ pinnedTokens: [
176
+ {
177
+ symbol: rangoToken.symbol,
178
+ address: rangoToken.address,
179
+ blockchain: rangoToken.blockchain,
180
+ },
181
+ ],
182
+ },
183
+ });
184
+
185
+ const tokens = appStoreState.tokens({
186
+ type: 'source',
187
+ getBalanceFor: (token: Token) => {
188
+ if (token.symbol === djangoToken.symbol) {
189
+ return {
190
+ amount: '100',
191
+ decimals: 12,
192
+ usdValue: '5000',
193
+ };
194
+ }
195
+ return null;
196
+ },
197
+ });
198
+
199
+ const firstResult = tokens[0].symbol;
200
+ const secondResult = tokens[1].symbol;
201
+ expect(firstResult).toBe(rangoToken.symbol);
202
+ expect(secondResult).toBe(djangoToken.symbol);
203
+ });
204
+
205
+ test('put pinned token first and tokens with balances second and popular tokens followed', () => {
206
+ const rangoToken = customTokens[0];
207
+ const djangoToken = customTokens[1];
208
+
209
+ appStoreState = updateAppStoreConfig(appStoreState, {
210
+ from: {
211
+ pinnedTokens: [
212
+ {
213
+ symbol: rangoToken.symbol,
214
+ address: rangoToken.address,
215
+ blockchain: rangoToken.blockchain,
216
+ },
217
+ ],
218
+ },
219
+ });
220
+
221
+ const tokens = appStoreState.tokens({
222
+ type: 'source',
223
+ getBalanceFor: (token: Token) => {
224
+ if (token.symbol === djangoToken.symbol) {
225
+ return {
226
+ amount: '100',
227
+ decimals: 12,
228
+ usdValue: '5000',
229
+ };
230
+ }
231
+ return null;
232
+ },
233
+ });
234
+
235
+ const firstResult = tokens[0].symbol;
236
+ const secondResult = tokens[1].symbol;
237
+
238
+ const popularTokensCount = tokens.reduce((previousValue, current) => {
239
+ if (current.isPopular) {
240
+ return previousValue + 1;
241
+ }
242
+ return previousValue;
243
+ }, 0);
244
+ const popularResult = tokens.slice(2, popularTokensCount);
245
+
246
+ expect(firstResult).toBe(rangoToken.symbol);
247
+ expect(secondResult).toBe(djangoToken.symbol);
248
+ assert(popularResult.every((token) => token.isPopular === true));
249
+ });
250
+ });
251
+
252
+ describe('search in tokens', () => {
253
+ test('should be first result when the symbol is exactly equal to the search term', () => {
254
+ const tokens = appStoreState.tokens({
255
+ type: 'source',
256
+ searchFor: 'rng',
257
+ });
258
+ const firstResult = tokens[0]?.symbol;
259
+ expect(firstResult).toBe('RNG');
260
+ });
261
+
262
+ test('should be first result when the token name is exactly equal to the search term', () => {
263
+ const tokens = appStoreState.tokens({
264
+ type: 'source',
265
+ searchFor: 'Rango',
266
+ });
267
+
268
+ const firstResult = tokens[0]?.symbol;
269
+ expect(firstResult).toBe('RNG');
270
+ });
271
+
272
+ test('should be first result when symbol characters starts with search term ', () => {
273
+ const tokens = appStoreState.tokens({
274
+ type: 'source',
275
+ searchFor: 'dj',
276
+ });
277
+
278
+ const firstResult = tokens[0]?.symbol;
279
+ expect(firstResult).toBe('DJG');
280
+ });
281
+
282
+ test('should be first result when symbol characters contains search term', () => {
283
+ const tokens = appStoreState.tokens({
284
+ type: 'source',
285
+ searchFor: 'abo',
286
+ });
287
+
288
+ const firstResult = tokens[0]?.symbol;
289
+ expect(firstResult).toBe('RABO');
290
+ });
291
+
292
+ test('should be first result when token name characters starts with search term', () => {
293
+ const tokens = appStoreState.tokens({
294
+ type: 'source',
295
+ searchFor: 'rang',
296
+ });
297
+
298
+ const firstResult = tokens[0]?.symbol;
299
+ expect(firstResult).toBe('RNG');
300
+ });
301
+
302
+ test('should be first result when token name characters contains search term', () => {
303
+ const tokens = appStoreState.tokens({
304
+ type: 'source',
305
+ searchFor: 'ngo',
306
+ });
307
+
308
+ // If there is more than one result, priority is given to the string that is shorter
309
+ const firstResult = tokens[0]?.symbol;
310
+ expect(firstResult).toBe('RNG');
311
+ });
312
+
313
+ test('should be first result when address contains searched term', () => {
314
+ const tokens = appStoreState.tokens({
315
+ type: 'source',
316
+ searchFor: '68701',
317
+ });
318
+
319
+ const firstResult = tokens[0]?.symbol;
320
+ expect(firstResult).toBe('RNG');
321
+ });
322
+
323
+ test('put pinned token first and popular tokens followed when token name or symbol contains search term', () => {
324
+ const djangoToken = customTokens[1];
325
+
326
+ appStoreState = updateAppStoreConfig(appStoreState, {
327
+ from: {
328
+ pinnedTokens: [
329
+ {
330
+ symbol: djangoToken.symbol,
331
+ address: djangoToken.address,
332
+ blockchain: djangoToken.blockchain,
333
+ },
334
+ ],
335
+ },
336
+ });
337
+
338
+ const tokens = appStoreState.tokens({
339
+ type: 'source',
340
+ searchFor: 'ngo',
341
+ });
342
+
343
+ const firstResult = tokens[0]?.symbol;
344
+ const secondResult = tokens[1]?.symbol;
345
+
346
+ expect(firstResult).toBe(djangoToken.symbol);
347
+ expect(secondResult).toBe('RNG');
348
+ });
349
+ });
@@ -0,0 +1,250 @@
1
+ import type { AppStoreState } from '../store/app';
2
+ import type { WidgetConfig } from '../types';
3
+ import type { BlockchainMeta, EvmBlockchainMeta, Token } from 'rango-sdk';
4
+
5
+ import { faker } from '@faker-js/faker';
6
+ import { TransactionType } from 'rango-sdk';
7
+
8
+ const TOKENS_COUNT = 20;
9
+ const BLOCKCHAINS_COUNT = 20;
10
+
11
+ const listBlockchains = [
12
+ 'ETH',
13
+ 'BSC',
14
+ 'ARBITRUM',
15
+ 'POLYGON',
16
+ 'ZKSYNC',
17
+ 'STARKNET',
18
+ 'OPTIMISM',
19
+ 'AVAX_CCHAIN',
20
+ 'POLYGONZK',
21
+ 'BASE',
22
+ 'LINEA',
23
+ 'TRON',
24
+ 'BTC',
25
+ 'SCROLL',
26
+ 'COSMOS',
27
+ 'OSMOSIS',
28
+ 'METIS',
29
+ 'NEUTRON',
30
+ 'NOBLE',
31
+ 'DYDX',
32
+ 'SOLANA',
33
+ 'CRONOS',
34
+ 'BNB',
35
+ 'FANTOM',
36
+ 'AURORA',
37
+ 'MAYA',
38
+ 'THOR',
39
+ 'BOBA',
40
+ 'MOONBEAM',
41
+ 'MOONRIVER',
42
+ 'OKC',
43
+ 'BOBA_BNB',
44
+ 'BOBA_AVALANCHE',
45
+ 'LTC',
46
+ 'BCH',
47
+ 'HARMONY',
48
+ 'EVMOS',
49
+ 'HECO',
50
+ 'SIF',
51
+ 'BRISE',
52
+ 'STARGAZE',
53
+ 'FUSE',
54
+ 'CRYPTO_ORG',
55
+ 'CHIHUAHUA',
56
+ 'BANDCHAIN',
57
+ 'COMDEX',
58
+ 'REGEN',
59
+ 'IRIS',
60
+ 'EMONEY',
61
+ 'GNOSIS',
62
+ 'JUNO',
63
+ 'AXELAR',
64
+ 'STRIDE',
65
+ 'KCC',
66
+ 'MARS',
67
+ 'TERRA',
68
+ 'TELOS',
69
+ 'BITSONG',
70
+ 'AKASH',
71
+ 'KI',
72
+ 'PERSISTENCE',
73
+ 'MEDIBLOC',
74
+ 'KUJIRA',
75
+ 'SENTINEL',
76
+ 'INJECTIVE',
77
+ 'SECRET',
78
+ 'KONSTELLATION',
79
+ 'STARNAME',
80
+ 'BITCANNA',
81
+ 'UMEE',
82
+ 'DESMOS',
83
+ 'LUMNETWORK',
84
+ 'TERRA_CLASSIC',
85
+ 'DASH',
86
+ 'DOGE',
87
+ ];
88
+
89
+ const listTokens = [
90
+ 'BTC',
91
+ 'ETH',
92
+ 'USDT',
93
+ 'BNB',
94
+ 'AVAX',
95
+ 'DOT',
96
+ 'LINK',
97
+ 'MATIC',
98
+ 'TRX',
99
+ 'BCH',
100
+ 'NEAR',
101
+ 'LTC',
102
+ 'ICP',
103
+ 'FIL',
104
+ 'ETC',
105
+ 'DAI',
106
+ 'ATOM',
107
+ 'IMX',
108
+ 'OP',
109
+ 'HBAR',
110
+ 'INJ',
111
+ 'XLM',
112
+ 'CRO',
113
+ 'RNDR',
114
+ 'GRT',
115
+ 'OKB',
116
+ 'VET',
117
+ 'MNT',
118
+ 'KAS',
119
+ 'THETA',
120
+ 'LDO',
121
+ 'FDUSD',
122
+ 'XRP',
123
+ 'RUNE',
124
+ 'UNI',
125
+ 'USDC',
126
+ 'LEO',
127
+ 'ADA',
128
+ 'TON',
129
+ 'STX',
130
+ 'APT',
131
+ 'SOL',
132
+ 'TIA',
133
+ 'FLOKI',
134
+ 'DOGE',
135
+ 'ARB',
136
+ 'PEPE',
137
+ 'SHIB',
138
+ 'TON',
139
+ ];
140
+
141
+ const FAKER_SEED = 9595;
142
+ faker.seed(FAKER_SEED);
143
+
144
+ export function createToken(options?: { blockchains?: string[] }) {
145
+ const fromBlockchains = options?.blockchains ?? listBlockchains;
146
+
147
+ return {
148
+ address: faker.datatype.boolean() ? faker.finance.ethereumAddress() : null,
149
+ blockchain: faker.helpers.arrayElement(fromBlockchains),
150
+ coinSource: faker.datatype.boolean() ? faker.word.noun() : null,
151
+ coinSourceUrl: faker.datatype.boolean() ? faker.internet.url() : null,
152
+ decimals: faker.number.int(),
153
+ usdPrice: faker.datatype.boolean() ? faker.number.float() : null,
154
+ isPopular: faker.datatype.boolean(),
155
+ image: faker.internet.url(),
156
+ symbol: faker.helpers.arrayElement(listTokens),
157
+ name: faker.datatype.boolean() ? faker.hacker.verb() : null,
158
+ supportedSwappers: faker.datatype.boolean()
159
+ ? faker.helpers.multiple(faker.string.sample)
160
+ : undefined,
161
+ isSecondaryCoin: faker.datatype.boolean(),
162
+ };
163
+ }
164
+ export function createTokens(
165
+ count: number,
166
+ options?: {
167
+ blockchains?: string[];
168
+ }
169
+ ): Token[] {
170
+ return Array(count)
171
+ .fill(null)
172
+ .map(() => createToken({ blockchains: options?.blockchains }));
173
+ }
174
+
175
+ export function createEvmBlockchain(): EvmBlockchainMeta {
176
+ const name = faker.helpers.arrayElement(listBlockchains);
177
+ return {
178
+ name: name,
179
+ shortName: faker.string.alpha({
180
+ length: 3,
181
+ }),
182
+ displayName: faker.string.alpha(),
183
+ defaultDecimals: faker.number.int(),
184
+ addressPatterns: faker.helpers.multiple(faker.string.sample),
185
+ logo: faker.internet.url(),
186
+ color: faker.helpers.fake('#{{number.hex()}}'),
187
+ sort: faker.number.int({ min: 1, max: BLOCKCHAINS_COUNT }),
188
+ enabled: faker.datatype.boolean(),
189
+ feeAssets: [
190
+ {
191
+ blockchain: faker.helpers.arrayElement(
192
+ listBlockchains.filter((item) => item !== name)
193
+ ),
194
+ symbol: faker.helpers.arrayElement(listTokens),
195
+ address: faker.datatype.boolean()
196
+ ? faker.finance.ethereumAddress()
197
+ : null,
198
+ },
199
+ ],
200
+ type: TransactionType.EVM,
201
+ chainId: faker.string.hexadecimal({
202
+ length: 2,
203
+ }),
204
+ info: {
205
+ infoType: 'EvmMetaInfo',
206
+ chainName: faker.hacker.adjective(),
207
+ nativeCurrency: {
208
+ name: faker.hacker.noun(),
209
+ symbol: faker.helpers.arrayElement(listTokens),
210
+ decimals: faker.number.int(),
211
+ },
212
+ rpcUrls: faker.helpers.multiple(faker.internet.url),
213
+ blockExplorerUrls: faker.helpers.multiple(faker.internet.url),
214
+ addressUrl: faker.internet.url(),
215
+ transactionUrl: faker.internet.url(),
216
+ },
217
+ };
218
+ }
219
+
220
+ export function createEvmBlockchains(count: number): EvmBlockchainMeta[] {
221
+ return Array(count)
222
+ .fill(null)
223
+ .map(() => createEvmBlockchain());
224
+ }
225
+
226
+ export function createInitialAppStore() {
227
+ const blockchains = createEvmBlockchains(BLOCKCHAINS_COUNT);
228
+ const tokens = createTokens(TOKENS_COUNT, {
229
+ blockchains: blockchains.map((b) => b.name),
230
+ });
231
+
232
+ return {
233
+ _tokens: tokens,
234
+ _blockchainsMapByName: new Map<string, BlockchainMeta>(
235
+ blockchains.map((meta) => [meta.name, meta])
236
+ ),
237
+ };
238
+ }
239
+
240
+ export function updateAppStoreConfig(
241
+ appStoreState: AppStoreState,
242
+ config: Partial<WidgetConfig>
243
+ ): AppStoreState {
244
+ appStoreState.config = {
245
+ ...appStoreState.config,
246
+ ...config,
247
+ };
248
+
249
+ return appStoreState;
250
+ }