@uniswap/token-list-bridge-utils 2.1.0 → 2.3.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/dist/constants/chainId.d.ts +2 -0
- package/dist/constants/tokens.d.ts +5 -0
- package/dist/fixtures/index.d.ts +24 -0
- package/dist/providers/BaseMappingProvider.d.ts +9 -0
- package/dist/providers/CeloMappingProvider.d.ts +5 -0
- package/dist/token-list-bridge-utils.cjs.development.js +184 -44
- package/dist/token-list-bridge-utils.cjs.development.js.map +1 -1
- package/dist/token-list-bridge-utils.cjs.production.min.js +1 -1
- package/dist/token-list-bridge-utils.cjs.production.min.js.map +1 -1
- package/dist/token-list-bridge-utils.esm.js +184 -44
- package/dist/token-list-bridge-utils.esm.js.map +1 -1
- package/package.json +13 -22
- package/src/arbitrum/instantiate_bridge.ts +10 -2
- package/src/constants/chainId.ts +3 -0
- package/src/constants/tokens.ts +41 -1
- package/src/fixtures/index.ts +73 -0
- package/src/index.test.ts +90 -85
- package/src/index.ts +6 -8
- package/src/local_mappings/celo.json +19 -0
- package/src/providers/BaseGoerliMappingProvider.ts +1 -1
- package/src/providers/BaseMappingProvider.ts +42 -0
- package/src/providers/CeloMappingProvider.ts +10 -0
- package/src/providers/OptimismMappingProvider.ts +19 -6
- package/src/providers/PolygonMappingProvider.ts +2 -1
- package/src/providers/index.ts +22 -6
- package/src/utils.ts +6 -0
|
@@ -3,6 +3,14 @@ import { providers } from 'ethers'
|
|
|
3
3
|
|
|
4
4
|
const networkID = 42161
|
|
5
5
|
|
|
6
|
+
const l2Rpc = (chainId: number) => {
|
|
7
|
+
if (chainId === 42161) return 'https://arb1.arbitrum.io/rpc'
|
|
8
|
+
else if (chainId === 421611) return 'https://rinkeby.arbitrum.io/rpc'
|
|
9
|
+
else if (chainId === 42170) return 'https://nova.arbitrum.io/rpc'
|
|
10
|
+
else if (chainId === 421613) return 'https://goerli-rollup.arbitrum.io/rpc'
|
|
11
|
+
throw new Error('No L2 RPC detected')
|
|
12
|
+
}
|
|
13
|
+
|
|
6
14
|
// ref: https://github.com/OffchainLabs/arb-token-lists/blob/master/src/lib/instantiate_bridge.ts
|
|
7
15
|
export const getNetworkConfig = async () => {
|
|
8
16
|
const { getL1Network, getL2Network, MultiCaller } = await import(
|
|
@@ -11,8 +19,8 @@ export const getNetworkConfig = async () => {
|
|
|
11
19
|
const l2Network = await getL2Network(networkID)
|
|
12
20
|
const l1Network = await getL1Network(l2Network.partnerChainID)
|
|
13
21
|
|
|
14
|
-
const arbProvider = new providers.JsonRpcProvider(l2Network.
|
|
15
|
-
const ethProvider = new providers.JsonRpcProvider(
|
|
22
|
+
const arbProvider = new providers.JsonRpcProvider(l2Rpc(l2Network.chainID))
|
|
23
|
+
const ethProvider = new providers.JsonRpcProvider(process.env.MAINNET_RPC)
|
|
16
24
|
|
|
17
25
|
const l1MultiCaller = await MultiCaller.fromProvider(ethProvider)
|
|
18
26
|
const l2MultiCaller = await MultiCaller.fromProvider(arbProvider)
|
package/src/constants/chainId.ts
CHANGED
package/src/constants/tokens.ts
CHANGED
|
@@ -11,7 +11,15 @@ export const COINBASE_WRAPPED_STAKED_ETH = new Token(
|
|
|
11
11
|
|
|
12
12
|
export const COINBASE_WRAPPED_STAKED_ETH_BASE_GOERLI = new Token(
|
|
13
13
|
ChainId.BASE_GOERLI,
|
|
14
|
-
'
|
|
14
|
+
'0x4fC531f8Ae7A7808E0dccCA08F1e3c7694582950',
|
|
15
|
+
18,
|
|
16
|
+
'cbETH',
|
|
17
|
+
'Coinbase Wrapped Staked ETH'
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
export const COINBASE_WRAPPED_STAKED_ETH_BASE = new Token(
|
|
21
|
+
ChainId.BASE,
|
|
22
|
+
'0x2Ae3F1Ec7F1F5012CFEab0185bfc7aa3cf0DEc22',
|
|
15
23
|
18,
|
|
16
24
|
'cbETH',
|
|
17
25
|
'Coinbase Wrapped Staked ETH'
|
|
@@ -25,6 +33,14 @@ export const COINBASE_WRAPPED_STAKED_ETH_ARBITRUM_ONE = new Token(
|
|
|
25
33
|
'Coinbase Wrapped Staked ETH'
|
|
26
34
|
)
|
|
27
35
|
|
|
36
|
+
export const COINBASE_WRAPPED_STAKED_ETH_OPTIMISM = new Token(
|
|
37
|
+
ChainId.OPTIMISM,
|
|
38
|
+
'0xadDb6A0412DE1BA0F936DCaeb8Aaa24578dcF3B2',
|
|
39
|
+
18,
|
|
40
|
+
'cbETH',
|
|
41
|
+
'Coinbase Wrapped Staked ETH'
|
|
42
|
+
)
|
|
43
|
+
|
|
28
44
|
export const DAI = new Token(
|
|
29
45
|
ChainId.MAINNET,
|
|
30
46
|
'0x6B175474E89094C44Da98b954EedeAC495271d0F',
|
|
@@ -70,6 +86,22 @@ export const DAI_AVALANCHE = new Token(
|
|
|
70
86
|
'DAI.e'
|
|
71
87
|
)
|
|
72
88
|
|
|
89
|
+
export const DAI_BASE = new Token(
|
|
90
|
+
ChainId.BASE,
|
|
91
|
+
'0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb',
|
|
92
|
+
18,
|
|
93
|
+
'DAI',
|
|
94
|
+
'Dai Stablecoin'
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
export const DAI_BASE_GOERLI = new Token(
|
|
98
|
+
ChainId.BASE_GOERLI,
|
|
99
|
+
'0x174956bDfbCEb6e53089297cce4fE2825E58d92C',
|
|
100
|
+
18,
|
|
101
|
+
'DAI',
|
|
102
|
+
'Dai Stablecoin'
|
|
103
|
+
)
|
|
104
|
+
|
|
73
105
|
export const USDT = new Token(
|
|
74
106
|
ChainId.MAINNET,
|
|
75
107
|
'0xdAC17F958D2ee523a2206206994597C13D831ec7',
|
|
@@ -85,3 +117,11 @@ export const USDT_BNB = new Token(
|
|
|
85
117
|
'USDT',
|
|
86
118
|
'Tether USD'
|
|
87
119
|
)
|
|
120
|
+
|
|
121
|
+
export const USDT_CELO = new Token(
|
|
122
|
+
ChainId.CELO,
|
|
123
|
+
'0x617f3112bf5397D0467D315cC709EF968D9ba546',
|
|
124
|
+
6,
|
|
125
|
+
'USDT',
|
|
126
|
+
'Tether USD'
|
|
127
|
+
)
|
package/src/fixtures/index.ts
CHANGED
|
@@ -13,6 +13,11 @@ import {
|
|
|
13
13
|
COINBASE_WRAPPED_STAKED_ETH,
|
|
14
14
|
COINBASE_WRAPPED_STAKED_ETH_BASE_GOERLI,
|
|
15
15
|
COINBASE_WRAPPED_STAKED_ETH_ARBITRUM_ONE,
|
|
16
|
+
COINBASE_WRAPPED_STAKED_ETH_BASE,
|
|
17
|
+
DAI_BASE_GOERLI,
|
|
18
|
+
COINBASE_WRAPPED_STAKED_ETH_OPTIMISM,
|
|
19
|
+
DAI_BASE,
|
|
20
|
+
USDT_CELO,
|
|
16
21
|
} from '../constants/tokens'
|
|
17
22
|
import { compareTokenInfos } from '../utils'
|
|
18
23
|
|
|
@@ -33,6 +38,9 @@ export const Tokens: Partial<Record<ChainId, Record<string, TokenInfo>>> = {
|
|
|
33
38
|
},
|
|
34
39
|
[ChainId.OPTIMISM]: {
|
|
35
40
|
DAI: tokenToTokenInfo(DAI_OPTIMISM),
|
|
41
|
+
COINBASE_WRAPPED_STAKED_ETH: tokenToTokenInfo(
|
|
42
|
+
COINBASE_WRAPPED_STAKED_ETH_OPTIMISM
|
|
43
|
+
),
|
|
36
44
|
},
|
|
37
45
|
[ChainId.BNB]: {
|
|
38
46
|
DAI: tokenToTokenInfo(DAI_BNB),
|
|
@@ -41,11 +49,21 @@ export const Tokens: Partial<Record<ChainId, Record<string, TokenInfo>>> = {
|
|
|
41
49
|
[ChainId.AVALANCHE]: {
|
|
42
50
|
DAI: tokenToTokenInfo(DAI_AVALANCHE),
|
|
43
51
|
},
|
|
52
|
+
[ChainId.BASE]: {
|
|
53
|
+
DAI: tokenToTokenInfo(DAI_BASE),
|
|
54
|
+
COINBASE_WRAPPED_STAKED_ETH: tokenToTokenInfo(
|
|
55
|
+
COINBASE_WRAPPED_STAKED_ETH_BASE
|
|
56
|
+
),
|
|
57
|
+
},
|
|
44
58
|
[ChainId.BASE_GOERLI]: {
|
|
59
|
+
DAI: tokenToTokenInfo(DAI_BASE_GOERLI),
|
|
45
60
|
COINBASE_WRAPPED_STAKED_ETH: tokenToTokenInfo(
|
|
46
61
|
COINBASE_WRAPPED_STAKED_ETH_BASE_GOERLI
|
|
47
62
|
),
|
|
48
63
|
},
|
|
64
|
+
[ChainId.CELO]: {
|
|
65
|
+
USDT: tokenToTokenInfo(USDT_CELO),
|
|
66
|
+
},
|
|
49
67
|
}
|
|
50
68
|
|
|
51
69
|
export const sampleL1TokenList: TokenList = {
|
|
@@ -222,6 +240,33 @@ export const bnbedSampleTokenList_2 = {
|
|
|
222
240
|
].sort(compareTokenInfos),
|
|
223
241
|
}
|
|
224
242
|
|
|
243
|
+
export const celoedSampleTokenList = {
|
|
244
|
+
...sampleL1TokenList_2,
|
|
245
|
+
name: 'Celo Sample',
|
|
246
|
+
tokens: [
|
|
247
|
+
{
|
|
248
|
+
...Tokens[ChainId.CELO]!.USDT,
|
|
249
|
+
extensions: {
|
|
250
|
+
bridgeInfo: {
|
|
251
|
+
[ChainId.MAINNET]: {
|
|
252
|
+
tokenAddress: USDT.address,
|
|
253
|
+
},
|
|
254
|
+
},
|
|
255
|
+
},
|
|
256
|
+
} as unknown as TokenInfo,
|
|
257
|
+
{
|
|
258
|
+
...(Tokens[ChainId.MAINNET]!.USDT as unknown as TokenInfo),
|
|
259
|
+
extensions: {
|
|
260
|
+
bridgeInfo: {
|
|
261
|
+
[ChainId.CELO]: {
|
|
262
|
+
tokenAddress: USDT_CELO.address,
|
|
263
|
+
},
|
|
264
|
+
},
|
|
265
|
+
},
|
|
266
|
+
} as unknown as TokenInfo,
|
|
267
|
+
].sort(compareTokenInfos),
|
|
268
|
+
}
|
|
269
|
+
|
|
225
270
|
export const baseGoerliSampleTokenList_3 = {
|
|
226
271
|
...sampleL1TokenList_3,
|
|
227
272
|
name: 'Base Goerli Sample_3',
|
|
@@ -250,6 +295,34 @@ export const baseGoerliSampleTokenList_3 = {
|
|
|
250
295
|
].sort(compareTokenInfos),
|
|
251
296
|
}
|
|
252
297
|
|
|
298
|
+
export const baseSampleTokenList_3 = {
|
|
299
|
+
...sampleL1TokenList_3,
|
|
300
|
+
name: 'Base Sample_3',
|
|
301
|
+
tokens: [
|
|
302
|
+
{
|
|
303
|
+
...Tokens[ChainId.BASE]!.COINBASE_WRAPPED_STAKED_ETH,
|
|
304
|
+
extensions: {
|
|
305
|
+
bridgeInfo: {
|
|
306
|
+
[ChainId.MAINNET]: {
|
|
307
|
+
tokenAddress: COINBASE_WRAPPED_STAKED_ETH.address,
|
|
308
|
+
},
|
|
309
|
+
},
|
|
310
|
+
},
|
|
311
|
+
} as unknown as TokenInfo,
|
|
312
|
+
{
|
|
313
|
+
...(Tokens[ChainId.MAINNET]!
|
|
314
|
+
.COINBASE_WRAPPED_STAKED_ETH as unknown as TokenInfo),
|
|
315
|
+
extensions: {
|
|
316
|
+
bridgeInfo: {
|
|
317
|
+
[ChainId.BASE]: {
|
|
318
|
+
tokenAddress: COINBASE_WRAPPED_STAKED_ETH_BASE.address,
|
|
319
|
+
},
|
|
320
|
+
},
|
|
321
|
+
},
|
|
322
|
+
} as unknown as TokenInfo,
|
|
323
|
+
].sort(compareTokenInfos),
|
|
324
|
+
}
|
|
325
|
+
|
|
253
326
|
export const optimizedSampleTokenList = {
|
|
254
327
|
...sampleL1TokenList,
|
|
255
328
|
name: 'Optimized Sample',
|
package/src/index.test.ts
CHANGED
|
@@ -4,10 +4,14 @@ import { ChainId } from './constants/chainId'
|
|
|
4
4
|
import {
|
|
5
5
|
COINBASE_WRAPPED_STAKED_ETH,
|
|
6
6
|
COINBASE_WRAPPED_STAKED_ETH_ARBITRUM_ONE,
|
|
7
|
+
COINBASE_WRAPPED_STAKED_ETH_BASE,
|
|
7
8
|
COINBASE_WRAPPED_STAKED_ETH_BASE_GOERLI,
|
|
9
|
+
COINBASE_WRAPPED_STAKED_ETH_OPTIMISM,
|
|
8
10
|
DAI,
|
|
9
11
|
DAI_ARBITRUM_ONE,
|
|
10
12
|
DAI_AVALANCHE,
|
|
13
|
+
DAI_BASE,
|
|
14
|
+
DAI_BASE_GOERLI,
|
|
11
15
|
DAI_BNB,
|
|
12
16
|
DAI_OPTIMISM,
|
|
13
17
|
DAI_POLYGON,
|
|
@@ -24,6 +28,8 @@ import {
|
|
|
24
28
|
avalanchedSampleTokenList,
|
|
25
29
|
sampleL1TokenList_3,
|
|
26
30
|
baseGoerliSampleTokenList_3,
|
|
31
|
+
baseSampleTokenList_3,
|
|
32
|
+
celoedSampleTokenList,
|
|
27
33
|
} from './fixtures'
|
|
28
34
|
|
|
29
35
|
jest.setTimeout(15000)
|
|
@@ -125,6 +131,22 @@ it('outputs bnb list correctly', async () => {
|
|
|
125
131
|
)
|
|
126
132
|
})
|
|
127
133
|
|
|
134
|
+
it('outputs celo list correctly', async () => {
|
|
135
|
+
const tokenList = await chainifyTokenList([ChainId.CELO], sampleL1TokenList_2)
|
|
136
|
+
expect(tokenList).toBeDefined()
|
|
137
|
+
expect(tokenList?.version).toEqual(celoedSampleTokenList.version)
|
|
138
|
+
expect(
|
|
139
|
+
tokenList?.tokens.map((t) => [t.address, t.chainId, t.extensions])
|
|
140
|
+
).toEqual(
|
|
141
|
+
// ignores other metadata
|
|
142
|
+
celoedSampleTokenList.tokens.map((t) => [
|
|
143
|
+
t.address,
|
|
144
|
+
t.chainId,
|
|
145
|
+
t.extensions,
|
|
146
|
+
])
|
|
147
|
+
)
|
|
148
|
+
})
|
|
149
|
+
|
|
128
150
|
it('outputs bnb list correctly with different decimals', async () => {
|
|
129
151
|
const tokenList = await chainifyTokenList([ChainId.BNB], sampleL1TokenList_2)
|
|
130
152
|
expect(tokenList).toBeDefined()
|
|
@@ -160,6 +182,22 @@ it('outputs base goerli list correctly', async () => {
|
|
|
160
182
|
)
|
|
161
183
|
})
|
|
162
184
|
|
|
185
|
+
it('outputs base list correctly', async () => {
|
|
186
|
+
const tokenList = await chainifyTokenList([ChainId.BASE], sampleL1TokenList_3)
|
|
187
|
+
expect(tokenList).toBeDefined()
|
|
188
|
+
expect(tokenList?.version).toEqual(baseSampleTokenList_3.version)
|
|
189
|
+
expect(
|
|
190
|
+
tokenList?.tokens.map((t) => [t.address, t.chainId, t.extensions])
|
|
191
|
+
).toEqual(
|
|
192
|
+
// ignores other metadata
|
|
193
|
+
baseSampleTokenList_3.tokens.map((t) => [
|
|
194
|
+
t.address,
|
|
195
|
+
t.chainId,
|
|
196
|
+
t.extensions,
|
|
197
|
+
])
|
|
198
|
+
)
|
|
199
|
+
})
|
|
200
|
+
|
|
163
201
|
describe(mergeTokenLists, () => {
|
|
164
202
|
it('correctly deduplicates', () => {
|
|
165
203
|
const merged = mergeTokenLists(sampleL1TokenList, sampleL1TokenList)
|
|
@@ -255,32 +293,11 @@ describe(mergeTokenLists, () => {
|
|
|
255
293
|
})
|
|
256
294
|
})
|
|
257
295
|
describe(chainify, () => {
|
|
258
|
-
it('
|
|
296
|
+
it('provides bridge extensions', async () => {
|
|
259
297
|
const chainified = await chainify(sampleL1TokenList)
|
|
260
298
|
|
|
261
|
-
expect(chainified.
|
|
262
|
-
|
|
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': {
|
|
299
|
+
expect(chainified.tokens).toEqual([
|
|
300
|
+
{
|
|
284
301
|
...Tokens[ChainId.MAINNET]!.DAI,
|
|
285
302
|
extensions: {
|
|
286
303
|
bridgeInfo: {
|
|
@@ -301,26 +318,18 @@ describe(chainify, () => {
|
|
|
301
318
|
// destBridgeAddress: arbBridgeL2Address,
|
|
302
319
|
// originBridgeAddress: arbBridgeL1Address,
|
|
303
320
|
},
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
extensions: {
|
|
310
|
-
bridgeInfo: {
|
|
311
|
-
[ChainId.MAINNET]: {
|
|
312
|
-
tokenAddress: DAI.address,
|
|
313
|
-
// originBridgeAddress: arbBridgeL2Address,
|
|
314
|
-
// destBridgeAddress: arbBridgeL1Address,
|
|
321
|
+
[ChainId.BASE]: {
|
|
322
|
+
tokenAddress: DAI_BASE.address,
|
|
323
|
+
},
|
|
324
|
+
[ChainId.BASE_GOERLI]: {
|
|
325
|
+
tokenAddress: DAI_BASE_GOERLI.address,
|
|
315
326
|
},
|
|
316
327
|
},
|
|
317
328
|
},
|
|
318
|
-
name: 'Dai Stablecoin',
|
|
319
329
|
},
|
|
320
|
-
|
|
321
|
-
...Tokens[ChainId.
|
|
330
|
+
{
|
|
331
|
+
...Tokens[ChainId.OPTIMISM]!.DAI,
|
|
322
332
|
name: 'Dai Stablecoin',
|
|
323
|
-
symbol: 'DAI',
|
|
324
333
|
extensions: {
|
|
325
334
|
bridgeInfo: {
|
|
326
335
|
[ChainId.MAINNET]: {
|
|
@@ -329,7 +338,7 @@ describe(chainify, () => {
|
|
|
329
338
|
},
|
|
330
339
|
},
|
|
331
340
|
},
|
|
332
|
-
|
|
341
|
+
{
|
|
333
342
|
...Tokens[ChainId.BNB]!.DAI,
|
|
334
343
|
extensions: {
|
|
335
344
|
bridgeInfo: {
|
|
@@ -339,40 +348,8 @@ describe(chainify, () => {
|
|
|
339
348
|
},
|
|
340
349
|
},
|
|
341
350
|
},
|
|
342
|
-
})
|
|
343
|
-
})
|
|
344
|
-
|
|
345
|
-
it('provides bridge extensions', async () => {
|
|
346
|
-
const chainified = await chainify(sampleL1TokenList)
|
|
347
|
-
|
|
348
|
-
expect(chainified.tokens).toEqual([
|
|
349
|
-
{
|
|
350
|
-
...Tokens[ChainId.MAINNET]!.DAI,
|
|
351
|
-
extensions: {
|
|
352
|
-
bridgeInfo: {
|
|
353
|
-
[ChainId.BNB]: {
|
|
354
|
-
tokenAddress: DAI_BNB.address,
|
|
355
|
-
},
|
|
356
|
-
[ChainId.AVALANCHE]: {
|
|
357
|
-
tokenAddress: DAI_AVALANCHE.address,
|
|
358
|
-
},
|
|
359
|
-
[ChainId.OPTIMISM]: {
|
|
360
|
-
tokenAddress: DAI_OPTIMISM.address,
|
|
361
|
-
},
|
|
362
|
-
[ChainId.POLYGON]: {
|
|
363
|
-
tokenAddress: DAI_POLYGON.address,
|
|
364
|
-
},
|
|
365
|
-
[ChainId.ARBITRUM_ONE]: {
|
|
366
|
-
tokenAddress: DAI_ARBITRUM_ONE.address,
|
|
367
|
-
// destBridgeAddress: arbBridgeL2Address,
|
|
368
|
-
// originBridgeAddress: arbBridgeL1Address,
|
|
369
|
-
},
|
|
370
|
-
},
|
|
371
|
-
},
|
|
372
|
-
},
|
|
373
351
|
{
|
|
374
|
-
...Tokens[ChainId.
|
|
375
|
-
name: 'Dai Stablecoin',
|
|
352
|
+
...Tokens[ChainId.POLYGON]!.DAI,
|
|
376
353
|
extensions: {
|
|
377
354
|
bridgeInfo: {
|
|
378
355
|
[ChainId.MAINNET]: {
|
|
@@ -382,7 +359,7 @@ describe(chainify, () => {
|
|
|
382
359
|
},
|
|
383
360
|
},
|
|
384
361
|
{
|
|
385
|
-
...Tokens[ChainId.
|
|
362
|
+
...Tokens[ChainId.BASE]!.DAI,
|
|
386
363
|
extensions: {
|
|
387
364
|
bridgeInfo: {
|
|
388
365
|
[ChainId.MAINNET]: {
|
|
@@ -392,32 +369,32 @@ describe(chainify, () => {
|
|
|
392
369
|
},
|
|
393
370
|
},
|
|
394
371
|
{
|
|
395
|
-
...Tokens[ChainId.
|
|
372
|
+
...Tokens[ChainId.ARBITRUM_ONE]!.DAI,
|
|
396
373
|
extensions: {
|
|
397
374
|
bridgeInfo: {
|
|
398
375
|
[ChainId.MAINNET]: {
|
|
399
376
|
tokenAddress: DAI.address,
|
|
377
|
+
// originBridgeAddress: arbBridgeL2Address,
|
|
378
|
+
// destBridgeAddress: arbBridgeL1Address,
|
|
400
379
|
},
|
|
401
380
|
},
|
|
402
381
|
},
|
|
382
|
+
name: 'Dai Stablecoin',
|
|
403
383
|
},
|
|
404
384
|
{
|
|
405
|
-
...Tokens[ChainId.
|
|
385
|
+
...Tokens[ChainId.AVALANCHE]!.DAI,
|
|
386
|
+
name: 'Dai Stablecoin',
|
|
387
|
+
symbol: 'DAI',
|
|
406
388
|
extensions: {
|
|
407
389
|
bridgeInfo: {
|
|
408
390
|
[ChainId.MAINNET]: {
|
|
409
391
|
tokenAddress: DAI.address,
|
|
410
|
-
// originBridgeAddress: arbBridgeL2Address,
|
|
411
|
-
// destBridgeAddress: arbBridgeL1Address,
|
|
412
392
|
},
|
|
413
393
|
},
|
|
414
394
|
},
|
|
415
|
-
name: 'Dai Stablecoin',
|
|
416
395
|
},
|
|
417
396
|
{
|
|
418
|
-
...Tokens[ChainId.
|
|
419
|
-
name: 'Dai Stablecoin',
|
|
420
|
-
symbol: 'DAI',
|
|
397
|
+
...Tokens[ChainId.BASE_GOERLI]!.DAI,
|
|
421
398
|
extensions: {
|
|
422
399
|
bridgeInfo: {
|
|
423
400
|
[ChainId.MAINNET]: {
|
|
@@ -429,7 +406,7 @@ describe(chainify, () => {
|
|
|
429
406
|
])
|
|
430
407
|
})
|
|
431
408
|
|
|
432
|
-
it('provides bridge extensions for base
|
|
409
|
+
it('provides bridge extensions for base list', async () => {
|
|
433
410
|
const chainified = await chainify(sampleL1TokenList_3)
|
|
434
411
|
|
|
435
412
|
expect(chainified.tokens).toEqual([
|
|
@@ -437,12 +414,40 @@ describe(chainify, () => {
|
|
|
437
414
|
...Tokens[ChainId.MAINNET]!.COINBASE_WRAPPED_STAKED_ETH,
|
|
438
415
|
extensions: {
|
|
439
416
|
bridgeInfo: {
|
|
440
|
-
[ChainId.
|
|
441
|
-
tokenAddress:
|
|
417
|
+
[ChainId.OPTIMISM]: {
|
|
418
|
+
tokenAddress: COINBASE_WRAPPED_STAKED_ETH_OPTIMISM.address,
|
|
419
|
+
},
|
|
420
|
+
[ChainId.BASE]: {
|
|
421
|
+
tokenAddress: COINBASE_WRAPPED_STAKED_ETH_BASE.address,
|
|
442
422
|
},
|
|
443
423
|
[ChainId.BASE_GOERLI]: {
|
|
444
424
|
tokenAddress: COINBASE_WRAPPED_STAKED_ETH_BASE_GOERLI.address,
|
|
445
425
|
},
|
|
426
|
+
[ChainId.ARBITRUM_ONE]: {
|
|
427
|
+
tokenAddress: COINBASE_WRAPPED_STAKED_ETH_ARBITRUM_ONE.address,
|
|
428
|
+
},
|
|
429
|
+
},
|
|
430
|
+
},
|
|
431
|
+
},
|
|
432
|
+
{
|
|
433
|
+
...Tokens[ChainId.OPTIMISM]!.COINBASE_WRAPPED_STAKED_ETH,
|
|
434
|
+
name: 'Coinbase Wrapped Staked ETH',
|
|
435
|
+
extensions: {
|
|
436
|
+
bridgeInfo: {
|
|
437
|
+
[ChainId.MAINNET]: {
|
|
438
|
+
tokenAddress: COINBASE_WRAPPED_STAKED_ETH.address,
|
|
439
|
+
},
|
|
440
|
+
},
|
|
441
|
+
},
|
|
442
|
+
},
|
|
443
|
+
{
|
|
444
|
+
...Tokens[ChainId.BASE]!.COINBASE_WRAPPED_STAKED_ETH,
|
|
445
|
+
name: 'Coinbase Wrapped Staked ETH',
|
|
446
|
+
extensions: {
|
|
447
|
+
bridgeInfo: {
|
|
448
|
+
[ChainId.MAINNET]: {
|
|
449
|
+
tokenAddress: COINBASE_WRAPPED_STAKED_ETH.address,
|
|
450
|
+
},
|
|
446
451
|
},
|
|
447
452
|
},
|
|
448
453
|
},
|
package/src/index.ts
CHANGED
|
@@ -25,6 +25,7 @@ export async function chainify(
|
|
|
25
25
|
ChainId.CELO,
|
|
26
26
|
ChainId.BNB,
|
|
27
27
|
ChainId.AVALANCHE,
|
|
28
|
+
ChainId.BASE,
|
|
28
29
|
ChainId.BASE_GOERLI,
|
|
29
30
|
]
|
|
30
31
|
|
|
@@ -34,13 +35,7 @@ export async function chainify(
|
|
|
34
35
|
chainified
|
|
35
36
|
)
|
|
36
37
|
|
|
37
|
-
|
|
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 }
|
|
38
|
+
return merged
|
|
44
39
|
}
|
|
45
40
|
|
|
46
41
|
/**
|
|
@@ -81,7 +76,10 @@ export function mergeTokenLists(
|
|
|
81
76
|
}
|
|
82
77
|
|
|
83
78
|
const merged = merge(group[0], group[1])
|
|
84
|
-
if (
|
|
79
|
+
if (
|
|
80
|
+
merged.extensions?.bridgeInfo &&
|
|
81
|
+
typeof merged.extensions.bridgeInfo === 'object'
|
|
82
|
+
) {
|
|
85
83
|
// remove reference to self-chain from merge
|
|
86
84
|
delete merged.extensions.bridgeInfo[merged.chainId]
|
|
87
85
|
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"0xdac17f958d2ee523a2206206994597c13d831ec7": {
|
|
3
|
+
"childToken": "0x617f3112bf5397D0467D315cC709EF968D9ba546",
|
|
4
|
+
"decimals": 18
|
|
5
|
+
},
|
|
6
|
+
"0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599": {
|
|
7
|
+
"childToken": "0xd71Ffd0940c920786eC4DbB5A12306669b5b81EF",
|
|
8
|
+
"decimals": 18
|
|
9
|
+
},
|
|
10
|
+
"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2": {
|
|
11
|
+
"childToken": "0xb829b68f57CC546dA7E5806A929e53bE32a4625D",
|
|
12
|
+
"decimals": 18
|
|
13
|
+
},
|
|
14
|
+
"0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48": {
|
|
15
|
+
"childToken": "0x37f750B7cC259A2f741AF45294f6a16572CF5cAd",
|
|
16
|
+
"decimals": 6
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
@@ -17,7 +17,7 @@ export class BaseGoerliMappingProvider implements MappingProvider {
|
|
|
17
17
|
|
|
18
18
|
let allTokens = await getTokenList(baseGoerliTokenListURL)
|
|
19
19
|
|
|
20
|
-
let opTokenId_baseGoerliAddressMap = {}
|
|
20
|
+
let opTokenId_baseGoerliAddressMap: Record<string, string> = {}
|
|
21
21
|
allTokens.tokens.forEach((token) => {
|
|
22
22
|
if (token.chainId === ChainId.BASE_GOERLI) {
|
|
23
23
|
if (typeof token.extensions?.opTokenId === 'string') {
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { MappingProvider } from './MappingProvider'
|
|
2
|
+
import { ChainId } from '../constants/chainId'
|
|
3
|
+
import { getTokenList } from '../utils'
|
|
4
|
+
import { GenericMappedTokenData } from '../constants/types'
|
|
5
|
+
|
|
6
|
+
const baseGoerliTokenListURL =
|
|
7
|
+
'https://raw.githubusercontent.com/' +
|
|
8
|
+
'ethereum-optimism/ethereum-optimism.github.io/master/optimism.tokenlist.json'
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* The Base mapping (linked above) is manually maintained by the Coinbase team
|
|
12
|
+
* in this repository: https://github.com/ethereum-optimism/ethereum-optimism.github.io.
|
|
13
|
+
*/
|
|
14
|
+
export class BaseMappingProvider implements MappingProvider {
|
|
15
|
+
async provide(): Promise<GenericMappedTokenData> {
|
|
16
|
+
const tokens: { [key: string]: string | undefined } = {}
|
|
17
|
+
|
|
18
|
+
let allTokens = await getTokenList(baseGoerliTokenListURL)
|
|
19
|
+
|
|
20
|
+
let opTokenId_baseAddressMap: Record<string, string> = {}
|
|
21
|
+
allTokens.tokens.forEach((token) => {
|
|
22
|
+
if (token.chainId === ChainId.BASE) {
|
|
23
|
+
if (typeof token.extensions?.opTokenId === 'string') {
|
|
24
|
+
opTokenId_baseAddressMap[token.extensions.opTokenId] = token.address
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
allTokens.tokens.forEach((token) => {
|
|
30
|
+
if (
|
|
31
|
+
token.chainId === ChainId.MAINNET &&
|
|
32
|
+
typeof token.extensions?.opTokenId === 'string' &&
|
|
33
|
+
token.extensions!.opTokenId in opTokenId_baseAddressMap
|
|
34
|
+
) {
|
|
35
|
+
tokens[token.address.toLowerCase()] =
|
|
36
|
+
opTokenId_baseAddressMap[token.extensions!.opTokenId]
|
|
37
|
+
}
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
return tokens
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { MappingProvider } from './MappingProvider'
|
|
2
|
+
import { MappedTokenData } from '../constants/types'
|
|
3
|
+
import celoMappings from '../local_mappings/celo.json'
|
|
4
|
+
|
|
5
|
+
// barring a better external source, we use a local source of mappings for celo
|
|
6
|
+
export class CeloMappingProvider implements MappingProvider {
|
|
7
|
+
async provide(): Promise<MappedTokenData> {
|
|
8
|
+
return celoMappings as MappedTokenData
|
|
9
|
+
}
|
|
10
|
+
}
|
|
@@ -5,7 +5,7 @@ import { GenericMappedTokenData } from '../constants/types'
|
|
|
5
5
|
|
|
6
6
|
const optimismTokenListURL =
|
|
7
7
|
'https://raw.githubusercontent.com/' +
|
|
8
|
-
'ethereum-optimism/ethereum-optimism.github.io/
|
|
8
|
+
'ethereum-optimism/ethereum-optimism.github.io/master/optimism.tokenlist.json'
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* The Optimism L2 mapping (linked above) is manually maintained by the Optimism team.
|
|
@@ -16,14 +16,27 @@ export class OptimismMappingProvider implements MappingProvider {
|
|
|
16
16
|
async provide(): Promise<GenericMappedTokenData> {
|
|
17
17
|
const tokens: { [key: string]: string | undefined } = {}
|
|
18
18
|
|
|
19
|
-
let
|
|
19
|
+
let allTokens = await getTokenList(optimismTokenListURL)
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
let opTokenId_baseAddressMap: Record<string, string> = {}
|
|
22
|
+
allTokens.tokens.forEach((token) => {
|
|
23
|
+
if (token.chainId === ChainId.OPTIMISM) {
|
|
24
|
+
if (typeof token.extensions?.opTokenId === 'string') {
|
|
25
|
+
opTokenId_baseAddressMap[token.extensions.opTokenId] = token.address
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
allTokens.tokens.forEach((token) => {
|
|
31
|
+
if (
|
|
32
|
+
token.chainId === ChainId.MAINNET &&
|
|
33
|
+
typeof token.extensions?.opTokenId === 'string' &&
|
|
34
|
+
token.extensions!.opTokenId in opTokenId_baseAddressMap
|
|
35
|
+
) {
|
|
23
36
|
tokens[token.address.toLowerCase()] =
|
|
24
|
-
token
|
|
37
|
+
opTokenId_baseAddressMap[token.extensions!.opTokenId]
|
|
25
38
|
}
|
|
26
|
-
}
|
|
39
|
+
})
|
|
27
40
|
|
|
28
41
|
return tokens
|
|
29
42
|
}
|
|
@@ -3,7 +3,8 @@ import { MappingProvider } from './MappingProvider'
|
|
|
3
3
|
import { PolygonMappedTokenData } from '../constants/types'
|
|
4
4
|
|
|
5
5
|
// called from https://mapper.polygon.technology
|
|
6
|
-
const url =
|
|
6
|
+
const url =
|
|
7
|
+
'https://api-polygon-tokens.polygon.technology/api/v1/info/all-mappings'
|
|
7
8
|
const access_token = '504afd90-3228-4df9-9d88-9b4d70646101'
|
|
8
9
|
|
|
9
10
|
/**
|