@uniswap/token-list-bridge-utils 0.1.1-beta.1 → 0.1.1-beta.2
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/arbitrum/gateway.d.ts +2 -0
- package/dist/{arb-token-lists/src/lib → arbitrum}/instantiate_bridge.d.ts +3 -4
- package/dist/constants/types.d.ts +30 -0
- package/dist/fixtures/index.d.ts +9 -0
- package/dist/providers/ArbitrumMappingProvider.d.ts +7 -6
- package/dist/providers/MappingProvider.d.ts +4 -2
- package/dist/providers/OptimismMappingProvider.d.ts +5 -4
- package/dist/providers/PolygonMappingProvider.d.ts +4 -2
- package/dist/providers/index.d.ts +2 -4
- package/dist/token-list-bridge-utils.cjs.development.js +324 -904
- 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 +326 -900
- package/dist/token-list-bridge-utils.esm.js.map +1 -1
- package/dist/utils.d.ts +4 -0
- package/package.json +7 -4
- package/src/arbitrum/gateway.ts +25 -0
- package/src/{arb-token-lists/src/lib → arbitrum}/instantiate_bridge.ts +11 -15
- package/src/constants/types.ts +28 -0
- package/src/fixtures/index.ts +40 -5
- package/src/index.test.ts +60 -18
- package/src/index.ts +5 -7
- package/src/providers/ArbitrumMappingProvider.ts +31 -21
- package/src/providers/MappingProvider.ts +4 -2
- package/src/providers/OptimismMappingProvider.ts +21 -5
- package/src/providers/PolygonMappingProvider.ts +22 -114
- package/src/providers/index.ts +81 -2
- package/src/utils.ts +71 -1
- package/dist/arb-token-lists/server/app.d.ts +0 -1
- package/dist/arb-token-lists/src/lib/getClargs.d.ts +0 -8
- package/dist/arb-token-lists/src/lib/graph.d.ts +0 -2
- package/dist/arb-token-lists/src/lib/token_list_gen.d.ts +0 -23
- package/dist/arb-token-lists/src/lib/types.d.ts +0 -36
- package/dist/arb-token-lists/src/lib/utils.d.ts +0 -18
- package/dist/arb-token-lists/src/main.d.ts +0 -1
- package/src/arb-token-lists/.env.sample +0 -4
- package/src/arb-token-lists/.eslintrc.js +0 -43
- package/src/arb-token-lists/.gitignore +0 -4
- package/src/arb-token-lists/package.json +0 -40
- package/src/arb-token-lists/readme.md +0 -14
- package/src/arb-token-lists/server/app.ts +0 -21
- package/src/arb-token-lists/src/Assets/coingecko_uris.json +0 -5108
- package/src/arb-token-lists/src/Assets/logo_uris.json +0 -44
- package/src/arb-token-lists/src/WarningList/warningTokens.json +0 -290
- package/src/arb-token-lists/src/lib/getClargs.ts +0 -32
- package/src/arb-token-lists/src/lib/graph.ts +0 -116
- package/src/arb-token-lists/src/lib/token_list_gen.ts +0 -334
- package/src/arb-token-lists/src/lib/types.ts +0 -44
- package/src/arb-token-lists/src/lib/utils.ts +0 -285
- package/src/arb-token-lists/src/main.ts +0 -54
- package/src/arb-token-lists/tsconfig.json +0 -20
- package/src/arb-token-lists/update_all +0 -6
- package/src/arb-token-lists/yarn.lock +0 -4273
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export interface PolygonMappedToken {
|
|
2
|
+
chainId: number
|
|
3
|
+
child_address_passed_by_user: boolean
|
|
4
|
+
child_token: string
|
|
5
|
+
count: number
|
|
6
|
+
created_at: string
|
|
7
|
+
decimals: number
|
|
8
|
+
deleted: boolean
|
|
9
|
+
id: number
|
|
10
|
+
map_type: 'POS'
|
|
11
|
+
mintable: boolean
|
|
12
|
+
name: string
|
|
13
|
+
new_child_token: string
|
|
14
|
+
new_mintable: boolean
|
|
15
|
+
owner: string
|
|
16
|
+
reason: string
|
|
17
|
+
reason_for_remapping: string
|
|
18
|
+
remapping_allowed: boolean
|
|
19
|
+
remapping_request_submitted: boolean
|
|
20
|
+
remapping_verified: boolean
|
|
21
|
+
root_token: string
|
|
22
|
+
status: number
|
|
23
|
+
symbol: string
|
|
24
|
+
token_type: string // ERC20
|
|
25
|
+
updated_at: string
|
|
26
|
+
uri: string
|
|
27
|
+
}
|
|
28
|
+
export type PolygonMappedTokenData = { [key: string]: PolygonMappedToken }
|
package/src/fixtures/index.ts
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import { Token } from '@uniswap/sdk-core'
|
|
2
2
|
import { TokenInfo, TokenList } from '@uniswap/token-lists'
|
|
3
3
|
import { ChainId } from '../constants/chainId'
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
DAI,
|
|
6
|
+
DAI_ARBITRUM_ONE,
|
|
7
|
+
DAI_OPTIMISM,
|
|
8
|
+
DAI_POLYGON,
|
|
9
|
+
} from '../constants/tokens'
|
|
5
10
|
import { compareTokenInfos } from '../utils'
|
|
6
11
|
|
|
7
12
|
export const Tokens: Partial<Record<ChainId, Record<string, TokenInfo>>> = {
|
|
@@ -14,6 +19,9 @@ export const Tokens: Partial<Record<ChainId, Record<string, TokenInfo>>> = {
|
|
|
14
19
|
[ChainId.POLYGON]: {
|
|
15
20
|
DAI: tokenToTokenInfo(DAI_POLYGON),
|
|
16
21
|
},
|
|
22
|
+
[ChainId.OPTIMISM]: {
|
|
23
|
+
DAI: tokenToTokenInfo(DAI_OPTIMISM),
|
|
24
|
+
},
|
|
17
25
|
}
|
|
18
26
|
|
|
19
27
|
export const sampleL1TokenList: TokenList = {
|
|
@@ -40,8 +48,8 @@ export const arbedSampleTokenList = {
|
|
|
40
48
|
bridgeInfo: {
|
|
41
49
|
[ChainId.MAINNET]: {
|
|
42
50
|
tokenAddress: DAI.address,
|
|
43
|
-
originBridgeAddress: arbBridgeL2Address,
|
|
44
|
-
destBridgeAddress: arbBridgeL1Address,
|
|
51
|
+
// originBridgeAddress: arbBridgeL2Address,
|
|
52
|
+
// destBridgeAddress: arbBridgeL1Address,
|
|
45
53
|
},
|
|
46
54
|
},
|
|
47
55
|
},
|
|
@@ -52,8 +60,8 @@ export const arbedSampleTokenList = {
|
|
|
52
60
|
bridgeInfo: {
|
|
53
61
|
[ChainId.ARBITRUM_ONE]: {
|
|
54
62
|
tokenAddress: DAI_ARBITRUM_ONE.address,
|
|
55
|
-
destBridgeAddress: arbBridgeL2Address,
|
|
56
|
-
originBridgeAddress: arbBridgeL1Address,
|
|
63
|
+
// destBridgeAddress: arbBridgeL2Address,
|
|
64
|
+
// originBridgeAddress: arbBridgeL1Address,
|
|
57
65
|
},
|
|
58
66
|
},
|
|
59
67
|
},
|
|
@@ -87,6 +95,33 @@ export const polygonedSampleTokenList = {
|
|
|
87
95
|
].sort(compareTokenInfos),
|
|
88
96
|
}
|
|
89
97
|
|
|
98
|
+
export const optimizedSampleTokenList = {
|
|
99
|
+
...sampleL1TokenList,
|
|
100
|
+
name: 'Optimized Sample',
|
|
101
|
+
tokens: [
|
|
102
|
+
{
|
|
103
|
+
...Tokens[ChainId.OPTIMISM]!.DAI,
|
|
104
|
+
extensions: {
|
|
105
|
+
bridgeInfo: {
|
|
106
|
+
[ChainId.MAINNET]: {
|
|
107
|
+
tokenAddress: DAI.address,
|
|
108
|
+
},
|
|
109
|
+
},
|
|
110
|
+
},
|
|
111
|
+
} as unknown as TokenInfo,
|
|
112
|
+
{
|
|
113
|
+
...(Tokens[ChainId.MAINNET]!.DAI as unknown as TokenInfo),
|
|
114
|
+
extensions: {
|
|
115
|
+
bridgeInfo: {
|
|
116
|
+
[ChainId.OPTIMISM]: {
|
|
117
|
+
tokenAddress: DAI_OPTIMISM.address,
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
} as unknown as TokenInfo,
|
|
122
|
+
].sort(compareTokenInfos),
|
|
123
|
+
}
|
|
124
|
+
|
|
90
125
|
function tokenToTokenInfo({
|
|
91
126
|
chainId,
|
|
92
127
|
address,
|
package/src/index.test.ts
CHANGED
|
@@ -1,27 +1,46 @@
|
|
|
1
1
|
import { TokenInfo } from '@uniswap/token-lists'
|
|
2
2
|
import { chainify, chainifyTokenList, mergeTokenLists } from '.'
|
|
3
3
|
import { ChainId } from './constants/chainId'
|
|
4
|
-
import {
|
|
4
|
+
import { ArbitrumMappingProvider } from './providers/ArbitrumMappingProvider'
|
|
5
|
+
import {
|
|
6
|
+
DAI,
|
|
7
|
+
DAI_ARBITRUM_ONE,
|
|
8
|
+
DAI_OPTIMISM,
|
|
9
|
+
DAI_POLYGON,
|
|
10
|
+
} from './constants/tokens'
|
|
5
11
|
import {
|
|
6
|
-
arbBridgeL1Address,
|
|
7
|
-
arbBridgeL2Address,
|
|
8
12
|
arbedSampleTokenList,
|
|
13
|
+
optimizedSampleTokenList,
|
|
9
14
|
polygonedSampleTokenList,
|
|
10
15
|
sampleL1TokenList,
|
|
11
16
|
Tokens,
|
|
12
17
|
} from './fixtures'
|
|
13
18
|
|
|
19
|
+
jest.setTimeout(15000)
|
|
20
|
+
|
|
14
21
|
describe(chainifyTokenList, () => {
|
|
15
|
-
it('
|
|
22
|
+
it('outputs Optimism list correctly', async () => {
|
|
16
23
|
const tokenList = await chainifyTokenList(
|
|
17
|
-
ChainId.
|
|
24
|
+
ChainId.OPTIMISM,
|
|
18
25
|
sampleL1TokenList
|
|
19
26
|
)
|
|
20
27
|
|
|
21
|
-
expect(tokenList).
|
|
28
|
+
expect(tokenList).toBeDefined()
|
|
29
|
+
expect(tokenList?.version).toEqual(polygonedSampleTokenList.version)
|
|
30
|
+
expect(
|
|
31
|
+
tokenList?.tokens.map((t) => [t.address, t.chainId, t.extensions])
|
|
32
|
+
).toEqual(
|
|
33
|
+
// ignores other metadata
|
|
34
|
+
optimizedSampleTokenList.tokens.map((t) => [
|
|
35
|
+
t.address,
|
|
36
|
+
t.chainId,
|
|
37
|
+
t.extensions,
|
|
38
|
+
])
|
|
39
|
+
)
|
|
22
40
|
})
|
|
23
41
|
|
|
24
42
|
it('outputs arbitrum list correctly', async () => {
|
|
43
|
+
mockArbitrumProvider()
|
|
25
44
|
const tokenList = await chainifyTokenList(
|
|
26
45
|
ChainId.ARBITRUM_ONE,
|
|
27
46
|
sampleL1TokenList
|
|
@@ -129,8 +148,8 @@ describe(mergeTokenLists, () => {
|
|
|
129
148
|
},
|
|
130
149
|
[ChainId.ARBITRUM_ONE]: {
|
|
131
150
|
tokenAddress: DAI_ARBITRUM_ONE.address,
|
|
132
|
-
destBridgeAddress: arbBridgeL2Address,
|
|
133
|
-
originBridgeAddress: arbBridgeL1Address,
|
|
151
|
+
// destBridgeAddress: arbBridgeL2Address,
|
|
152
|
+
// originBridgeAddress: arbBridgeL1Address,
|
|
134
153
|
},
|
|
135
154
|
},
|
|
136
155
|
},
|
|
@@ -151,8 +170,8 @@ describe(mergeTokenLists, () => {
|
|
|
151
170
|
bridgeInfo: {
|
|
152
171
|
[ChainId.MAINNET]: {
|
|
153
172
|
tokenAddress: DAI.address,
|
|
154
|
-
originBridgeAddress: arbBridgeL2Address,
|
|
155
|
-
destBridgeAddress: arbBridgeL1Address,
|
|
173
|
+
// originBridgeAddress: arbBridgeL2Address,
|
|
174
|
+
// destBridgeAddress: arbBridgeL1Address,
|
|
156
175
|
},
|
|
157
176
|
},
|
|
158
177
|
},
|
|
@@ -160,9 +179,9 @@ describe(mergeTokenLists, () => {
|
|
|
160
179
|
])
|
|
161
180
|
})
|
|
162
181
|
})
|
|
163
|
-
|
|
164
182
|
describe(chainify, () => {
|
|
165
183
|
it('provides bridge extensions', async () => {
|
|
184
|
+
mockArbitrumProvider()
|
|
166
185
|
const chainified = await chainify(sampleL1TokenList)
|
|
167
186
|
|
|
168
187
|
expect(chainified.tokens).toEqual([
|
|
@@ -170,13 +189,27 @@ describe(chainify, () => {
|
|
|
170
189
|
...Tokens[ChainId.MAINNET]!.DAI,
|
|
171
190
|
extensions: {
|
|
172
191
|
bridgeInfo: {
|
|
192
|
+
[ChainId.OPTIMISM]: {
|
|
193
|
+
tokenAddress: DAI_OPTIMISM.address,
|
|
194
|
+
},
|
|
173
195
|
[ChainId.POLYGON]: {
|
|
174
196
|
tokenAddress: DAI_POLYGON.address,
|
|
175
197
|
},
|
|
176
198
|
[ChainId.ARBITRUM_ONE]: {
|
|
177
199
|
tokenAddress: DAI_ARBITRUM_ONE.address,
|
|
178
|
-
destBridgeAddress: arbBridgeL2Address,
|
|
179
|
-
originBridgeAddress: arbBridgeL1Address,
|
|
200
|
+
// destBridgeAddress: arbBridgeL2Address,
|
|
201
|
+
// originBridgeAddress: arbBridgeL1Address,
|
|
202
|
+
},
|
|
203
|
+
},
|
|
204
|
+
},
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
...Tokens[ChainId.OPTIMISM]!.DAI,
|
|
208
|
+
name: 'Dai Stablecoin',
|
|
209
|
+
extensions: {
|
|
210
|
+
bridgeInfo: {
|
|
211
|
+
[ChainId.MAINNET]: {
|
|
212
|
+
tokenAddress: DAI.address,
|
|
180
213
|
},
|
|
181
214
|
},
|
|
182
215
|
},
|
|
@@ -196,16 +229,25 @@ describe(chainify, () => {
|
|
|
196
229
|
extensions: {
|
|
197
230
|
bridgeInfo: {
|
|
198
231
|
[ChainId.MAINNET]: {
|
|
199
|
-
tokenAddress: DAI.address
|
|
200
|
-
originBridgeAddress: arbBridgeL2Address,
|
|
201
|
-
destBridgeAddress: arbBridgeL1Address,
|
|
232
|
+
tokenAddress: DAI.address,
|
|
233
|
+
// originBridgeAddress: arbBridgeL2Address,
|
|
234
|
+
// destBridgeAddress: arbBridgeL1Address,
|
|
202
235
|
},
|
|
203
236
|
},
|
|
204
237
|
},
|
|
205
|
-
logoURI:
|
|
206
|
-
'https://assets.coingecko.com/coins/images/9956/thumb/4943.png?1636636734',
|
|
207
238
|
name: 'Dai Stablecoin',
|
|
208
239
|
},
|
|
209
240
|
])
|
|
210
241
|
})
|
|
211
242
|
})
|
|
243
|
+
|
|
244
|
+
// Mocking arb provider due to required infura key for network call
|
|
245
|
+
function mockArbitrumProvider() {
|
|
246
|
+
let arbTokenMap: { [key: string]: string | undefined } = {}
|
|
247
|
+
const DAI_ADDRESS: string = DAI.address.toLowerCase()
|
|
248
|
+
arbTokenMap[DAI_ADDRESS.toLowerCase()] =
|
|
249
|
+
DAI_ARBITRUM_ONE.address.toLowerCase()
|
|
250
|
+
var mockArbProvide = jest.fn()
|
|
251
|
+
mockArbProvide.mockImplementation(() => Promise.resolve(arbTokenMap))
|
|
252
|
+
ArbitrumMappingProvider.prototype.provide = mockArbProvide
|
|
253
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { TokenList } from '@uniswap/token-lists'
|
|
2
2
|
import { cloneDeep, groupBy, merge } from 'lodash'
|
|
3
3
|
import { ChainId } from './constants/chainId'
|
|
4
|
-
import {
|
|
4
|
+
import { buildList } from './providers'
|
|
5
5
|
import {
|
|
6
6
|
compareTokenInfos,
|
|
7
7
|
getTokenList,
|
|
8
|
-
TokenListOrFetchableTokenList
|
|
8
|
+
TokenListOrFetchableTokenList,
|
|
9
9
|
} from './utils'
|
|
10
10
|
import { verifyExtensions } from './verify'
|
|
11
11
|
|
|
@@ -49,9 +49,8 @@ export async function chainifyTokenList(
|
|
|
49
49
|
l1TokenListOrPathOrUrl: TokenListOrFetchableTokenList
|
|
50
50
|
): Promise<TokenList> {
|
|
51
51
|
try {
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
)
|
|
52
|
+
const l1TokenList = await getTokenList(l1TokenListOrPathOrUrl)
|
|
53
|
+
const tokenList = await buildList(chainId, l1TokenList)
|
|
55
54
|
return verifyExtensions(tokenList)
|
|
56
55
|
} catch (e) {
|
|
57
56
|
throw new Error(`An error occured: ${e}`)
|
|
@@ -79,7 +78,6 @@ export function mergeTokenLists(
|
|
|
79
78
|
const merged = merge(group[0], group[1])
|
|
80
79
|
if (merged.extensions?.bridgeInfo) {
|
|
81
80
|
// remove reference to self-chain from merge
|
|
82
|
-
// @ts-expect-error TokenList schema doesn't yet define objects
|
|
83
81
|
delete merged.extensions.bridgeInfo[merged.chainId]
|
|
84
82
|
}
|
|
85
83
|
return merged
|
|
@@ -89,4 +87,4 @@ export function mergeTokenLists(
|
|
|
89
87
|
...primary,
|
|
90
88
|
tokens: merged.sort(compareTokenInfos),
|
|
91
89
|
})
|
|
92
|
-
}
|
|
90
|
+
}
|
|
@@ -1,28 +1,38 @@
|
|
|
1
|
-
import { TokenList } from '@uniswap/token-lists'
|
|
2
|
-
import { generateTokenList } from '../arb-token-lists/src/lib/token_list_gen'
|
|
3
|
-
import { compareTokenInfos } from '../utils'
|
|
4
1
|
import { MappingProvider } from './MappingProvider'
|
|
2
|
+
import { getNetworkConfig } from '../arbitrum/instantiate_bridge'
|
|
3
|
+
import { getL2TokenAddressesFromL1 } from '../arbitrum/gateway'
|
|
4
|
+
import { TokenList } from '@uniswap/token-lists'
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
*
|
|
8
|
-
* token list.
|
|
9
|
-
*
|
|
10
|
-
* The provider simply invokes this package which we host as a submodule.
|
|
7
|
+
* This provider provides the l1->l2(Arbitrum) address mappings using the arbitrum SDK.
|
|
11
8
|
*/
|
|
12
|
-
|
|
13
9
|
export class ArbitrumMappingProvider implements MappingProvider {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
10
|
+
l1TokenList: TokenList
|
|
11
|
+
|
|
12
|
+
constructor(l1TokenList: TokenList) {
|
|
13
|
+
this.l1TokenList = l1TokenList
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
async provide(): Promise<{ [key: string]: string | undefined }> {
|
|
17
|
+
let tokens: { [key: string]: string | undefined } = {}
|
|
18
|
+
|
|
19
|
+
const { l1, l2 } = await getNetworkConfig()
|
|
20
|
+
|
|
21
|
+
let tokenAddresses = this.l1TokenList.tokens.map((token) =>
|
|
22
|
+
token.address.toLowerCase()
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
const l2AddressesFromL1 = await getL2TokenAddressesFromL1(
|
|
26
|
+
tokenAddresses,
|
|
27
|
+
l1.multiCaller,
|
|
28
|
+
l2.network.tokenBridge.l1GatewayRouter
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
tokens = tokenAddresses.reduce(
|
|
32
|
+
(obj, key, index) => ({ ...obj, [key]: l2AddressesFromL1[index] }),
|
|
33
|
+
{}
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
return tokens
|
|
27
37
|
}
|
|
28
38
|
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { PolygonMappedTokenData } from '../constants/types'
|
|
2
2
|
|
|
3
3
|
export interface MappingProvider {
|
|
4
|
-
provide(
|
|
4
|
+
provide(): Promise<
|
|
5
|
+
PolygonMappedTokenData | { [key: string]: string | undefined }
|
|
6
|
+
>
|
|
5
7
|
}
|
|
@@ -1,13 +1,29 @@
|
|
|
1
|
-
import { TokenList } from '@uniswap/token-lists'
|
|
2
1
|
import { MappingProvider } from './MappingProvider'
|
|
2
|
+
import { ChainId } from '../constants/chainId'
|
|
3
|
+
import { getTokenList } from '../utils'
|
|
4
|
+
|
|
5
|
+
const optimismTokenListURL =
|
|
6
|
+
'https://raw.githubusercontent.com/' +
|
|
7
|
+
'ethereum-optimism/ethereum-optimism.github.io/2138386277e4156d159615d1840882cecc398437/optimism.tokenlist.json'
|
|
3
8
|
|
|
4
9
|
/**
|
|
5
|
-
* The Optimism L2 mapping is manually maintained by the Optimism team.
|
|
10
|
+
* The Optimism L2 mapping (linked above) is manually maintained by the Optimism team.
|
|
6
11
|
*
|
|
7
|
-
* This provider
|
|
12
|
+
* This provider provides the l1->l2(Optimism) token mappings.
|
|
8
13
|
*/
|
|
9
14
|
export class OptimismMappingProvider implements MappingProvider {
|
|
10
|
-
async provide(
|
|
11
|
-
|
|
15
|
+
async provide(): Promise<{ [key: string]: string | undefined }> {
|
|
16
|
+
const tokens: { [key: string]: string | undefined } = {}
|
|
17
|
+
|
|
18
|
+
let optimismTokens = await getTokenList(optimismTokenListURL)
|
|
19
|
+
|
|
20
|
+
for (const token of optimismTokens.tokens) {
|
|
21
|
+
if (token.chainId === ChainId.MAINNET) {
|
|
22
|
+
tokens[token.address.toLowerCase()] =
|
|
23
|
+
token?.extensions?.bridgeInfo![ChainId.OPTIMISM].tokenAddress
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return tokens
|
|
12
28
|
}
|
|
13
29
|
}
|
|
@@ -1,127 +1,35 @@
|
|
|
1
|
-
import { TokenInfo, TokenList } from '@uniswap/token-lists'
|
|
2
1
|
import axios from 'axios'
|
|
3
|
-
import { compareTokenInfos } from '../utils'
|
|
4
2
|
import { MappingProvider } from './MappingProvider'
|
|
3
|
+
import { PolygonMappedTokenData } from '../constants/types'
|
|
5
4
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
child_address_passed_by_user: boolean
|
|
9
|
-
child_token: string
|
|
10
|
-
count: number
|
|
11
|
-
created_at: string
|
|
12
|
-
decimals: number
|
|
13
|
-
deleted: boolean
|
|
14
|
-
id: number
|
|
15
|
-
map_type: 'POS'
|
|
16
|
-
mintable: boolean
|
|
17
|
-
name: string
|
|
18
|
-
new_child_token: string
|
|
19
|
-
new_mintable: boolean
|
|
20
|
-
owner: string
|
|
21
|
-
reason: string
|
|
22
|
-
reason_for_remapping: string
|
|
23
|
-
remapping_allowed: boolean
|
|
24
|
-
remapping_request_submitted: boolean
|
|
25
|
-
remapping_verified: boolean
|
|
26
|
-
root_token: string
|
|
27
|
-
status: number
|
|
28
|
-
symbol: string
|
|
29
|
-
token_type: string // ERC20
|
|
30
|
-
updated_at: string
|
|
31
|
-
uri: string
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
type PolygonMappedTokenData = { [key: string]: PolygonMappedToken }
|
|
5
|
+
const url = 'https://tokenmapper.api.matic.today/api/v1/mapping?'
|
|
6
|
+
const params = 'map_type=[%22POS%22]&chain_id=137&limit=200&offset='
|
|
35
7
|
|
|
36
8
|
/**
|
|
37
9
|
* The Polygon team manually maintains the mapping via user submissions at
|
|
38
10
|
* https://mapper.polygon.technology.
|
|
11
|
+
*
|
|
12
|
+
* This provider provides the l1->l2(Polygon) token mappings.
|
|
39
13
|
*/
|
|
40
14
|
export class PolygonMappingProvider implements MappingProvider {
|
|
41
|
-
async provide(
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
},
|
|
57
|
-
},
|
|
58
|
-
},
|
|
59
|
-
}
|
|
60
|
-
: {}
|
|
61
|
-
const toChildExtensions = childTokenValid
|
|
62
|
-
? {
|
|
63
|
-
extensions: {
|
|
64
|
-
bridgeInfo: {
|
|
65
|
-
[childToken.chainId]: {
|
|
66
|
-
tokenAddress: childToken.child_token,
|
|
67
|
-
},
|
|
68
|
-
},
|
|
69
|
-
},
|
|
70
|
-
}
|
|
71
|
-
: {}
|
|
72
|
-
|
|
73
|
-
const rootTokenInfo: TokenInfo = {
|
|
74
|
-
...rootToken,
|
|
75
|
-
...toChildExtensions,
|
|
76
|
-
} as unknown as TokenInfo
|
|
77
|
-
|
|
78
|
-
const childTokenInfo: TokenInfo = {
|
|
79
|
-
...rootToken,
|
|
80
|
-
chainId: childToken.chainId,
|
|
81
|
-
name: childToken.name ?? rootToken.name,
|
|
82
|
-
symbol: childToken.symbol ?? rootToken.symbol,
|
|
83
|
-
address: childToken.child_token,
|
|
84
|
-
...toRootExtensions,
|
|
85
|
-
} as unknown as TokenInfo
|
|
86
|
-
|
|
87
|
-
mappedTokens.push(rootTokenInfo)
|
|
88
|
-
mappedTokens.push(childTokenInfo)
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
const tokenList = {
|
|
92
|
-
name: `Polygon ${l1TokenList.name}`,
|
|
93
|
-
timestamp: new Date().toISOString(),
|
|
94
|
-
version: l1TokenList.version,
|
|
95
|
-
tokens: mappedTokens.sort(compareTokenInfos),
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
return tokenList
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
const url = 'https://tokenmapper.api.matic.today/api/v1/mapping?'
|
|
103
|
-
const params = 'map_type=[%22POS%22]&chain_id=137&limit=200&offset='
|
|
104
|
-
|
|
105
|
-
async function fetchPolygonMappedTokens(): Promise<PolygonMappedTokenData> {
|
|
106
|
-
let offset = 0
|
|
107
|
-
const tokens: PolygonMappedTokenData = {}
|
|
108
|
-
|
|
109
|
-
while (true) {
|
|
110
|
-
const response = await axios.get(`${url}${params}${offset}`)
|
|
111
|
-
|
|
112
|
-
if (response.data.message === 'success') {
|
|
113
|
-
for (const token of response.data.data.mapping) {
|
|
114
|
-
tokens[token.root_token.toLowerCase()] = token
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
if (response.data.data.has_next_page === true) {
|
|
118
|
-
offset += 200
|
|
119
|
-
continue
|
|
15
|
+
async provide(): Promise<PolygonMappedTokenData> {
|
|
16
|
+
let offset = 0
|
|
17
|
+
const tokens: PolygonMappedTokenData = {}
|
|
18
|
+
while (true) {
|
|
19
|
+
const response = await axios.get(`${url}${params}${offset}`)
|
|
20
|
+
|
|
21
|
+
if (response.data.message === 'success') {
|
|
22
|
+
for (const token of response.data.data.mapping) {
|
|
23
|
+
tokens[token.root_token.toLowerCase()] = token
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (response.data.data.has_next_page === true) {
|
|
27
|
+
offset += 200
|
|
28
|
+
continue
|
|
29
|
+
}
|
|
120
30
|
}
|
|
31
|
+
break
|
|
121
32
|
}
|
|
122
|
-
|
|
123
|
-
break
|
|
33
|
+
return tokens
|
|
124
34
|
}
|
|
125
|
-
|
|
126
|
-
return tokens
|
|
127
35
|
}
|
package/src/providers/index.ts
CHANGED
|
@@ -2,11 +2,90 @@ import { ChainId } from '../constants/chainId'
|
|
|
2
2
|
import { ArbitrumMappingProvider } from './ArbitrumMappingProvider'
|
|
3
3
|
import { OptimismMappingProvider } from './OptimismMappingProvider'
|
|
4
4
|
import { PolygonMappingProvider } from './PolygonMappingProvider'
|
|
5
|
+
import { TokenInfo, TokenList } from '@uniswap/token-lists'
|
|
6
|
+
import { compareTokenInfos } from '../utils'
|
|
7
|
+
import { ethers } from 'ethers'
|
|
5
8
|
|
|
6
|
-
export function
|
|
9
|
+
export async function buildList(
|
|
10
|
+
chainId: ChainId,
|
|
11
|
+
l1TokenList: TokenList
|
|
12
|
+
): Promise<TokenList> {
|
|
13
|
+
const tokenAddressMap = await getMappingProvider(
|
|
14
|
+
chainId,
|
|
15
|
+
l1TokenList
|
|
16
|
+
).provide()
|
|
17
|
+
const mappedTokens = []
|
|
18
|
+
for (const rootToken of l1TokenList.tokens) {
|
|
19
|
+
const childToken = tokenAddressMap[rootToken.address.toLowerCase()]
|
|
20
|
+
const childTokenValid = Boolean(
|
|
21
|
+
childToken &&
|
|
22
|
+
(typeof childToken === 'object' ? !childToken.deleted : true)
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
if (rootToken.chainId === ChainId.MAINNET) {
|
|
26
|
+
// build extension info if available
|
|
27
|
+
const toRootExtensions = childTokenValid
|
|
28
|
+
? {
|
|
29
|
+
extensions: {
|
|
30
|
+
bridgeInfo: {
|
|
31
|
+
[rootToken.chainId]: {
|
|
32
|
+
tokenAddress: ethers.utils.getAddress(rootToken.address),
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
}
|
|
37
|
+
: {}
|
|
38
|
+
|
|
39
|
+
const toChildExtensions = childTokenValid
|
|
40
|
+
? {
|
|
41
|
+
extensions: {
|
|
42
|
+
bridgeInfo: {
|
|
43
|
+
[chainId]: {
|
|
44
|
+
tokenAddress: ethers.utils.getAddress(
|
|
45
|
+
typeof childToken === 'object'
|
|
46
|
+
? childToken.child_token
|
|
47
|
+
: childToken!
|
|
48
|
+
),
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
}
|
|
53
|
+
: {}
|
|
54
|
+
|
|
55
|
+
const rootTokenInfo: TokenInfo = {
|
|
56
|
+
...rootToken,
|
|
57
|
+
...toChildExtensions,
|
|
58
|
+
} as unknown as TokenInfo
|
|
59
|
+
|
|
60
|
+
const childTokenInfo: TokenInfo = {
|
|
61
|
+
...rootToken,
|
|
62
|
+
chainId: chainId,
|
|
63
|
+
address: ethers.utils.getAddress(
|
|
64
|
+
typeof childToken === 'object' ? childToken.child_token : childToken!
|
|
65
|
+
),
|
|
66
|
+
...toRootExtensions,
|
|
67
|
+
} as unknown as TokenInfo
|
|
68
|
+
|
|
69
|
+
mappedTokens.push(rootTokenInfo)
|
|
70
|
+
if (childTokenValid) {
|
|
71
|
+
mappedTokens.push(childTokenInfo)
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
const tokenList = {
|
|
76
|
+
name: `(ChainId: ${chainId}) ${l1TokenList.name}`,
|
|
77
|
+
timestamp: new Date().toISOString(),
|
|
78
|
+
version: l1TokenList.version,
|
|
79
|
+
tokens: mappedTokens.sort(compareTokenInfos),
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return tokenList
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function getMappingProvider(chainId: ChainId, l1TokenList: TokenList) {
|
|
7
86
|
switch (chainId) {
|
|
8
87
|
case ChainId.ARBITRUM_ONE:
|
|
9
|
-
return new ArbitrumMappingProvider()
|
|
88
|
+
return new ArbitrumMappingProvider(l1TokenList)
|
|
10
89
|
case ChainId.OPTIMISM:
|
|
11
90
|
return new OptimismMappingProvider()
|
|
12
91
|
case ChainId.POLYGON:
|