@uniswap/token-list-bridge-utils 1.3.3 → 2.1.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.
@@ -5,10 +5,14 @@ import {
5
5
  DAI,
6
6
  DAI_ARBITRUM_ONE,
7
7
  DAI_BNB,
8
+ DAI_AVALANCHE,
8
9
  DAI_OPTIMISM,
9
10
  DAI_POLYGON,
10
11
  USDT,
11
12
  USDT_BNB,
13
+ COINBASE_WRAPPED_STAKED_ETH,
14
+ COINBASE_WRAPPED_STAKED_ETH_BASE_GOERLI,
15
+ COINBASE_WRAPPED_STAKED_ETH_ARBITRUM_ONE,
12
16
  } from '../constants/tokens'
13
17
  import { compareTokenInfos } from '../utils'
14
18
 
@@ -16,9 +20,13 @@ export const Tokens: Partial<Record<ChainId, Record<string, TokenInfo>>> = {
16
20
  [ChainId.MAINNET]: {
17
21
  DAI: tokenToTokenInfo(DAI),
18
22
  USDT: tokenToTokenInfo(USDT),
23
+ COINBASE_WRAPPED_STAKED_ETH: tokenToTokenInfo(COINBASE_WRAPPED_STAKED_ETH),
19
24
  },
20
25
  [ChainId.ARBITRUM_ONE]: {
21
26
  DAI: tokenToTokenInfo(DAI_ARBITRUM_ONE),
27
+ COINBASE_WRAPPED_STAKED_ETH: tokenToTokenInfo(
28
+ COINBASE_WRAPPED_STAKED_ETH_ARBITRUM_ONE
29
+ ),
22
30
  },
23
31
  [ChainId.POLYGON]: {
24
32
  DAI: tokenToTokenInfo(DAI_POLYGON),
@@ -30,6 +38,14 @@ export const Tokens: Partial<Record<ChainId, Record<string, TokenInfo>>> = {
30
38
  DAI: tokenToTokenInfo(DAI_BNB),
31
39
  USDT: tokenToTokenInfo(USDT_BNB),
32
40
  },
41
+ [ChainId.AVALANCHE]: {
42
+ DAI: tokenToTokenInfo(DAI_AVALANCHE),
43
+ },
44
+ [ChainId.BASE_GOERLI]: {
45
+ COINBASE_WRAPPED_STAKED_ETH: tokenToTokenInfo(
46
+ COINBASE_WRAPPED_STAKED_ETH_BASE_GOERLI
47
+ ),
48
+ },
33
49
  }
34
50
 
35
51
  export const sampleL1TokenList: TokenList = {
@@ -54,6 +70,17 @@ export const sampleL1TokenList_2: TokenList = {
54
70
  tokens: [Tokens[ChainId.MAINNET]!.USDT],
55
71
  }
56
72
 
73
+ export const sampleL1TokenList_3: TokenList = {
74
+ name: 'Sample_3',
75
+ timestamp: new Date(1646146610).toISOString(),
76
+ version: {
77
+ major: 1,
78
+ minor: 0,
79
+ patch: 0,
80
+ },
81
+ tokens: [Tokens[ChainId.MAINNET]!.COINBASE_WRAPPED_STAKED_ETH],
82
+ }
83
+
57
84
  export const arbBridgeL2Address = '0x467194771dae2967aef3ecbedd3bf9a310c76c65'
58
85
  export const arbBridgeL1Address = '0xd3b5b60020504bc3489d6949d545893982ba3011'
59
86
 
@@ -114,6 +141,33 @@ export const polygonedSampleTokenList = {
114
141
  ].sort(compareTokenInfos),
115
142
  }
116
143
 
144
+ export const avalanchedSampleTokenList = {
145
+ ...sampleL1TokenList,
146
+ name: 'Avalanched Sample',
147
+ tokens: [
148
+ {
149
+ ...Tokens[ChainId.AVALANCHE]!.DAI,
150
+ extensions: {
151
+ bridgeInfo: {
152
+ [ChainId.MAINNET]: {
153
+ tokenAddress: DAI.address,
154
+ },
155
+ },
156
+ },
157
+ } as unknown as TokenInfo,
158
+ {
159
+ ...(Tokens[ChainId.MAINNET]!.DAI as unknown as TokenInfo),
160
+ extensions: {
161
+ bridgeInfo: {
162
+ [ChainId.AVALANCHE]: {
163
+ tokenAddress: DAI_AVALANCHE.address,
164
+ },
165
+ },
166
+ },
167
+ } as unknown as TokenInfo,
168
+ ].sort(compareTokenInfos),
169
+ }
170
+
117
171
  export const bnbedSampleTokenList = {
118
172
  ...sampleL1TokenList,
119
173
  name: 'BNBed Sample',
@@ -168,6 +222,34 @@ export const bnbedSampleTokenList_2 = {
168
222
  ].sort(compareTokenInfos),
169
223
  }
170
224
 
225
+ export const baseGoerliSampleTokenList_3 = {
226
+ ...sampleL1TokenList_3,
227
+ name: 'Base Goerli Sample_3',
228
+ tokens: [
229
+ {
230
+ ...Tokens[ChainId.BASE_GOERLI]!.COINBASE_WRAPPED_STAKED_ETH,
231
+ extensions: {
232
+ bridgeInfo: {
233
+ [ChainId.MAINNET]: {
234
+ tokenAddress: COINBASE_WRAPPED_STAKED_ETH.address,
235
+ },
236
+ },
237
+ },
238
+ } as unknown as TokenInfo,
239
+ {
240
+ ...(Tokens[ChainId.MAINNET]!
241
+ .COINBASE_WRAPPED_STAKED_ETH as unknown as TokenInfo),
242
+ extensions: {
243
+ bridgeInfo: {
244
+ [ChainId.BASE_GOERLI]: {
245
+ tokenAddress: COINBASE_WRAPPED_STAKED_ETH_BASE_GOERLI.address,
246
+ },
247
+ },
248
+ },
249
+ } as unknown as TokenInfo,
250
+ ].sort(compareTokenInfos),
251
+ }
252
+
171
253
  export const optimizedSampleTokenList = {
172
254
  ...sampleL1TokenList,
173
255
  name: 'Optimized Sample',
package/src/index.test.ts CHANGED
@@ -2,8 +2,12 @@ import { TokenInfo } from '@uniswap/token-lists'
2
2
  import { chainify, chainifyTokenList, mergeTokenLists } from '.'
3
3
  import { ChainId } from './constants/chainId'
4
4
  import {
5
+ COINBASE_WRAPPED_STAKED_ETH,
6
+ COINBASE_WRAPPED_STAKED_ETH_ARBITRUM_ONE,
7
+ COINBASE_WRAPPED_STAKED_ETH_BASE_GOERLI,
5
8
  DAI,
6
9
  DAI_ARBITRUM_ONE,
10
+ DAI_AVALANCHE,
7
11
  DAI_BNB,
8
12
  DAI_OPTIMISM,
9
13
  DAI_POLYGON,
@@ -17,6 +21,9 @@ import {
17
21
  Tokens,
18
22
  sampleL1TokenList_2,
19
23
  bnbedSampleTokenList_2,
24
+ avalanchedSampleTokenList,
25
+ sampleL1TokenList_3,
26
+ baseGoerliSampleTokenList_3,
20
27
  } from './fixtures'
21
28
 
22
29
  jest.setTimeout(15000)
@@ -87,6 +94,25 @@ describe(chainifyTokenList, () => {
87
94
  })
88
95
  })
89
96
 
97
+ it('outputs avalanche list correctly', async () => {
98
+ const tokenList = await chainifyTokenList(
99
+ [ChainId.AVALANCHE],
100
+ sampleL1TokenList
101
+ )
102
+ expect(tokenList).toBeDefined()
103
+ expect(tokenList?.version).toEqual(avalanchedSampleTokenList.version)
104
+ expect(
105
+ tokenList?.tokens.map((t) => [t.address, t.chainId, t.extensions])
106
+ ).toEqual(
107
+ // ignores other metadata
108
+ avalanchedSampleTokenList.tokens.map((t) => [
109
+ t.address,
110
+ t.chainId,
111
+ t.extensions,
112
+ ])
113
+ )
114
+ })
115
+
90
116
  it('outputs bnb list correctly', async () => {
91
117
  const tokenList = await chainifyTokenList([ChainId.BNB], sampleL1TokenList)
92
118
  expect(tokenList).toBeDefined()
@@ -115,6 +141,25 @@ it('outputs bnb list correctly with different decimals', async () => {
115
141
  )
116
142
  })
117
143
 
144
+ it('outputs base goerli list correctly', async () => {
145
+ const tokenList = await chainifyTokenList(
146
+ [ChainId.BASE_GOERLI],
147
+ sampleL1TokenList_3
148
+ )
149
+ expect(tokenList).toBeDefined()
150
+ expect(tokenList?.version).toEqual(baseGoerliSampleTokenList_3.version)
151
+ expect(
152
+ tokenList?.tokens.map((t) => [t.address, t.chainId, t.extensions])
153
+ ).toEqual(
154
+ // ignores other metadata
155
+ baseGoerliSampleTokenList_3.tokens.map((t) => [
156
+ t.address,
157
+ t.chainId,
158
+ t.extensions,
159
+ ])
160
+ )
161
+ })
162
+
118
163
  describe(mergeTokenLists, () => {
119
164
  it('correctly deduplicates', () => {
120
165
  const merged = mergeTokenLists(sampleL1TokenList, sampleL1TokenList)
@@ -210,6 +255,93 @@ describe(mergeTokenLists, () => {
210
255
  })
211
256
  })
212
257
  describe(chainify, () => {
258
+ it('creates tokenMap correctly in chainify', async () => {
259
+ const chainified = await chainify(sampleL1TokenList)
260
+
261
+ expect(chainified.tokenMap).toEqual({
262
+ '10_0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1': {
263
+ ...Tokens[ChainId.OPTIMISM]!.DAI,
264
+ name: 'Dai Stablecoin',
265
+ extensions: {
266
+ bridgeInfo: {
267
+ [ChainId.MAINNET]: {
268
+ tokenAddress: DAI.address,
269
+ },
270
+ },
271
+ },
272
+ },
273
+ '137_0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063': {
274
+ ...Tokens[ChainId.POLYGON]!.DAI,
275
+ extensions: {
276
+ bridgeInfo: {
277
+ [ChainId.MAINNET]: {
278
+ tokenAddress: DAI.address,
279
+ },
280
+ },
281
+ },
282
+ },
283
+ '1_0x6B175474E89094C44Da98b954EedeAC495271d0F': {
284
+ ...Tokens[ChainId.MAINNET]!.DAI,
285
+ extensions: {
286
+ bridgeInfo: {
287
+ [ChainId.BNB]: {
288
+ tokenAddress: DAI_BNB.address,
289
+ },
290
+ [ChainId.AVALANCHE]: {
291
+ tokenAddress: DAI_AVALANCHE.address,
292
+ },
293
+ [ChainId.OPTIMISM]: {
294
+ tokenAddress: DAI_OPTIMISM.address,
295
+ },
296
+ [ChainId.POLYGON]: {
297
+ tokenAddress: DAI_POLYGON.address,
298
+ },
299
+ [ChainId.ARBITRUM_ONE]: {
300
+ tokenAddress: DAI_ARBITRUM_ONE.address,
301
+ // destBridgeAddress: arbBridgeL2Address,
302
+ // originBridgeAddress: arbBridgeL1Address,
303
+ },
304
+ },
305
+ },
306
+ },
307
+ '42161_0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1': {
308
+ ...Tokens[ChainId.ARBITRUM_ONE]!.DAI,
309
+ extensions: {
310
+ bridgeInfo: {
311
+ [ChainId.MAINNET]: {
312
+ tokenAddress: DAI.address,
313
+ // originBridgeAddress: arbBridgeL2Address,
314
+ // destBridgeAddress: arbBridgeL1Address,
315
+ },
316
+ },
317
+ },
318
+ name: 'Dai Stablecoin',
319
+ },
320
+ '43114_0xd586E7F844cEa2F87f50152665BCbc2C279D8d70': {
321
+ ...Tokens[ChainId.AVALANCHE]!.DAI,
322
+ name: 'Dai Stablecoin',
323
+ symbol: 'DAI',
324
+ extensions: {
325
+ bridgeInfo: {
326
+ [ChainId.MAINNET]: {
327
+ tokenAddress: DAI.address,
328
+ },
329
+ },
330
+ },
331
+ },
332
+ '56_0x1AF3F329e8BE154074D8769D1FFa4eE058B1DBc3': {
333
+ ...Tokens[ChainId.BNB]!.DAI,
334
+ extensions: {
335
+ bridgeInfo: {
336
+ [ChainId.MAINNET]: {
337
+ tokenAddress: DAI.address,
338
+ },
339
+ },
340
+ },
341
+ },
342
+ })
343
+ })
344
+
213
345
  it('provides bridge extensions', async () => {
214
346
  const chainified = await chainify(sampleL1TokenList)
215
347
 
@@ -221,6 +353,9 @@ describe(chainify, () => {
221
353
  [ChainId.BNB]: {
222
354
  tokenAddress: DAI_BNB.address,
223
355
  },
356
+ [ChainId.AVALANCHE]: {
357
+ tokenAddress: DAI_AVALANCHE.address,
358
+ },
224
359
  [ChainId.OPTIMISM]: {
225
360
  tokenAddress: DAI_OPTIMISM.address,
226
361
  },
@@ -279,6 +414,60 @@ describe(chainify, () => {
279
414
  },
280
415
  name: 'Dai Stablecoin',
281
416
  },
417
+ {
418
+ ...Tokens[ChainId.AVALANCHE]!.DAI,
419
+ name: 'Dai Stablecoin',
420
+ symbol: 'DAI',
421
+ extensions: {
422
+ bridgeInfo: {
423
+ [ChainId.MAINNET]: {
424
+ tokenAddress: DAI.address,
425
+ },
426
+ },
427
+ },
428
+ },
429
+ ])
430
+ })
431
+
432
+ it('provides bridge extensions for base goerli list', async () => {
433
+ const chainified = await chainify(sampleL1TokenList_3)
434
+
435
+ expect(chainified.tokens).toEqual([
436
+ {
437
+ ...Tokens[ChainId.MAINNET]!.COINBASE_WRAPPED_STAKED_ETH,
438
+ extensions: {
439
+ bridgeInfo: {
440
+ [ChainId.ARBITRUM_ONE]: {
441
+ tokenAddress: COINBASE_WRAPPED_STAKED_ETH_ARBITRUM_ONE.address,
442
+ },
443
+ [ChainId.BASE_GOERLI]: {
444
+ tokenAddress: COINBASE_WRAPPED_STAKED_ETH_BASE_GOERLI.address,
445
+ },
446
+ },
447
+ },
448
+ },
449
+ {
450
+ ...Tokens[ChainId.ARBITRUM_ONE]!.COINBASE_WRAPPED_STAKED_ETH,
451
+ name: 'Coinbase Wrapped Staked ETH',
452
+ extensions: {
453
+ bridgeInfo: {
454
+ [ChainId.MAINNET]: {
455
+ tokenAddress: COINBASE_WRAPPED_STAKED_ETH.address,
456
+ },
457
+ },
458
+ },
459
+ },
460
+ {
461
+ ...Tokens[ChainId.BASE_GOERLI]!.COINBASE_WRAPPED_STAKED_ETH,
462
+ name: 'Coinbase Wrapped Staked ETH',
463
+ extensions: {
464
+ bridgeInfo: {
465
+ [ChainId.MAINNET]: {
466
+ tokenAddress: COINBASE_WRAPPED_STAKED_ETH.address,
467
+ },
468
+ },
469
+ },
470
+ },
282
471
  ])
283
472
  })
284
473
  })
package/src/index.ts CHANGED
@@ -24,13 +24,23 @@ export async function chainify(
24
24
  ChainId.OPTIMISM,
25
25
  ChainId.CELO,
26
26
  ChainId.BNB,
27
+ ChainId.AVALANCHE,
28
+ ChainId.BASE_GOERLI,
27
29
  ]
28
30
 
29
31
  const chainified = await chainifyTokenList(l2Chains, l1TokenListOrPathOrUrl)
30
- return mergeTokenLists(
32
+ const merged = mergeTokenLists(
31
33
  l1TokenList, // providing l1 first to make sure duplicated tokens resolve to this list
32
34
  chainified
33
35
  )
36
+
37
+ const tokenMap = {}
38
+ if (merged.tokens && merged.tokens.length > 0) {
39
+ merged.tokens.forEach((token) => {
40
+ tokenMap[`${token.chainId}_${token.address}`] = token
41
+ })
42
+ }
43
+ return { ...merged, tokenMap }
34
44
  }
35
45
 
36
46
  /**