@uniswap/token-list-bridge-utils 1.0.5 → 1.0.8
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/README.md +7 -7
- package/dist/abis/erc20.d.ts +3 -0
- package/dist/token-list-bridge-utils.cjs.development.js +498 -205
- 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 +497 -205
- package/dist/token-list-bridge-utils.esm.js.map +1 -1
- package/dist/utils.d.ts +4 -0
- package/package.json +4 -2
- package/src/abis/erc20.ts +226 -0
- package/src/arbitrum/set_rpc.ts +4 -3
- package/src/index.test.ts +1 -2
- package/src/providers/index.ts +33 -13
- package/src/utils.ts +28 -0
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
import { AbiItem } from 'web3-utils'
|
|
2
|
+
|
|
3
|
+
const abi: AbiItem[] = [
|
|
4
|
+
{
|
|
5
|
+
constant: true,
|
|
6
|
+
inputs: [],
|
|
7
|
+
name: 'name',
|
|
8
|
+
outputs: [
|
|
9
|
+
{
|
|
10
|
+
name: '',
|
|
11
|
+
type: 'string',
|
|
12
|
+
},
|
|
13
|
+
],
|
|
14
|
+
payable: false,
|
|
15
|
+
stateMutability: 'view',
|
|
16
|
+
type: 'function',
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
constant: false,
|
|
20
|
+
inputs: [
|
|
21
|
+
{
|
|
22
|
+
name: '_spender',
|
|
23
|
+
type: 'address',
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
name: '_value',
|
|
27
|
+
type: 'uint256',
|
|
28
|
+
},
|
|
29
|
+
],
|
|
30
|
+
name: 'approve',
|
|
31
|
+
outputs: [
|
|
32
|
+
{
|
|
33
|
+
name: '',
|
|
34
|
+
type: 'bool',
|
|
35
|
+
},
|
|
36
|
+
],
|
|
37
|
+
payable: false,
|
|
38
|
+
stateMutability: 'nonpayable',
|
|
39
|
+
type: 'function',
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
constant: true,
|
|
43
|
+
inputs: [],
|
|
44
|
+
name: 'totalSupply',
|
|
45
|
+
outputs: [
|
|
46
|
+
{
|
|
47
|
+
name: '',
|
|
48
|
+
type: 'uint256',
|
|
49
|
+
},
|
|
50
|
+
],
|
|
51
|
+
payable: false,
|
|
52
|
+
stateMutability: 'view',
|
|
53
|
+
type: 'function',
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
constant: false,
|
|
57
|
+
inputs: [
|
|
58
|
+
{
|
|
59
|
+
name: '_from',
|
|
60
|
+
type: 'address',
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
name: '_to',
|
|
64
|
+
type: 'address',
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
name: '_value',
|
|
68
|
+
type: 'uint256',
|
|
69
|
+
},
|
|
70
|
+
],
|
|
71
|
+
name: 'transferFrom',
|
|
72
|
+
outputs: [
|
|
73
|
+
{
|
|
74
|
+
name: '',
|
|
75
|
+
type: 'bool',
|
|
76
|
+
},
|
|
77
|
+
],
|
|
78
|
+
payable: false,
|
|
79
|
+
stateMutability: 'nonpayable',
|
|
80
|
+
type: 'function',
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
constant: true,
|
|
84
|
+
inputs: [],
|
|
85
|
+
name: 'decimals',
|
|
86
|
+
outputs: [
|
|
87
|
+
{
|
|
88
|
+
name: '',
|
|
89
|
+
type: 'uint8',
|
|
90
|
+
},
|
|
91
|
+
],
|
|
92
|
+
payable: false,
|
|
93
|
+
stateMutability: 'view',
|
|
94
|
+
type: 'function',
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
constant: true,
|
|
98
|
+
inputs: [
|
|
99
|
+
{
|
|
100
|
+
name: '_owner',
|
|
101
|
+
type: 'address',
|
|
102
|
+
},
|
|
103
|
+
],
|
|
104
|
+
name: 'balanceOf',
|
|
105
|
+
outputs: [
|
|
106
|
+
{
|
|
107
|
+
name: 'balance',
|
|
108
|
+
type: 'uint256',
|
|
109
|
+
},
|
|
110
|
+
],
|
|
111
|
+
payable: false,
|
|
112
|
+
stateMutability: 'view',
|
|
113
|
+
type: 'function',
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
constant: true,
|
|
117
|
+
inputs: [],
|
|
118
|
+
name: 'symbol',
|
|
119
|
+
outputs: [
|
|
120
|
+
{
|
|
121
|
+
name: '',
|
|
122
|
+
type: 'string',
|
|
123
|
+
},
|
|
124
|
+
],
|
|
125
|
+
payable: false,
|
|
126
|
+
stateMutability: 'view',
|
|
127
|
+
type: 'function',
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
constant: false,
|
|
131
|
+
inputs: [
|
|
132
|
+
{
|
|
133
|
+
name: '_to',
|
|
134
|
+
type: 'address',
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
name: '_value',
|
|
138
|
+
type: 'uint256',
|
|
139
|
+
},
|
|
140
|
+
],
|
|
141
|
+
name: 'transfer',
|
|
142
|
+
outputs: [
|
|
143
|
+
{
|
|
144
|
+
name: '',
|
|
145
|
+
type: 'bool',
|
|
146
|
+
},
|
|
147
|
+
],
|
|
148
|
+
payable: false,
|
|
149
|
+
stateMutability: 'nonpayable',
|
|
150
|
+
type: 'function',
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
constant: true,
|
|
154
|
+
inputs: [
|
|
155
|
+
{
|
|
156
|
+
name: '_owner',
|
|
157
|
+
type: 'address',
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
name: '_spender',
|
|
161
|
+
type: 'address',
|
|
162
|
+
},
|
|
163
|
+
],
|
|
164
|
+
name: 'allowance',
|
|
165
|
+
outputs: [
|
|
166
|
+
{
|
|
167
|
+
name: '',
|
|
168
|
+
type: 'uint256',
|
|
169
|
+
},
|
|
170
|
+
],
|
|
171
|
+
payable: false,
|
|
172
|
+
stateMutability: 'view',
|
|
173
|
+
type: 'function',
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
payable: true,
|
|
177
|
+
stateMutability: 'payable',
|
|
178
|
+
type: 'fallback',
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
anonymous: false,
|
|
182
|
+
inputs: [
|
|
183
|
+
{
|
|
184
|
+
indexed: true,
|
|
185
|
+
name: 'owner',
|
|
186
|
+
type: 'address',
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
indexed: true,
|
|
190
|
+
name: 'spender',
|
|
191
|
+
type: 'address',
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
indexed: false,
|
|
195
|
+
name: 'value',
|
|
196
|
+
type: 'uint256',
|
|
197
|
+
},
|
|
198
|
+
],
|
|
199
|
+
name: 'Approval',
|
|
200
|
+
type: 'event',
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
anonymous: false,
|
|
204
|
+
inputs: [
|
|
205
|
+
{
|
|
206
|
+
indexed: true,
|
|
207
|
+
name: 'from',
|
|
208
|
+
type: 'address',
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
indexed: true,
|
|
212
|
+
name: 'to',
|
|
213
|
+
type: 'address',
|
|
214
|
+
},
|
|
215
|
+
{
|
|
216
|
+
indexed: false,
|
|
217
|
+
name: 'value',
|
|
218
|
+
type: 'uint256',
|
|
219
|
+
},
|
|
220
|
+
],
|
|
221
|
+
name: 'Transfer',
|
|
222
|
+
type: 'event',
|
|
223
|
+
},
|
|
224
|
+
]
|
|
225
|
+
|
|
226
|
+
export default abi
|
package/src/arbitrum/set_rpc.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { config } from 'dotenv'
|
|
2
|
+
import { ChainId } from '../constants/chainId'
|
|
3
|
+
import { getRpcUrl } from '../utils'
|
|
2
4
|
|
|
3
|
-
// fall back to https://cloudflare-eth.com/ if MAINNET_RPC not provided in an .env file
|
|
5
|
+
// MAINNET_RPC value is required for arb-sdk. fall back to https://cloudflare-eth.com/ if MAINNET_RPC not provided in an .env file
|
|
4
6
|
config()
|
|
5
|
-
process.env.MAINNET_RPC
|
|
6
|
-
process.env.MAINNET_RPC || 'https://cloudflare-eth.com/'
|
|
7
|
+
process.env.MAINNET_RPC ??= getRpcUrl(ChainId.MAINNET)
|
package/src/index.test.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { TokenInfo } from '@uniswap/token-lists'
|
|
2
2
|
import { chainify, chainifyTokenList, mergeTokenLists } from '.'
|
|
3
3
|
import { ChainId } from './constants/chainId'
|
|
4
|
-
import { ArbitrumMappingProvider } from './providers/ArbitrumMappingProvider'
|
|
5
4
|
import {
|
|
6
5
|
DAI,
|
|
7
6
|
DAI_ARBITRUM_ONE,
|
|
@@ -237,4 +236,4 @@ describe(chainify, () => {
|
|
|
237
236
|
},
|
|
238
237
|
])
|
|
239
238
|
})
|
|
240
|
-
})
|
|
239
|
+
})
|
package/src/providers/index.ts
CHANGED
|
@@ -1,15 +1,26 @@
|
|
|
1
1
|
import { ChainId } from '../constants/chainId'
|
|
2
|
+
import { Contract } from 'web3-eth-contract'
|
|
2
3
|
import { ArbitrumMappingProvider } from './ArbitrumMappingProvider'
|
|
3
4
|
import { OptimismMappingProvider } from './OptimismMappingProvider'
|
|
4
5
|
import { PolygonMappingProvider } from './PolygonMappingProvider'
|
|
5
6
|
import { TokenInfo, TokenList } from '@uniswap/token-lists'
|
|
6
|
-
import { compareTokenInfos } from '../utils'
|
|
7
7
|
import { ethers } from 'ethers'
|
|
8
|
+
import {
|
|
9
|
+
compareTokenInfos,
|
|
10
|
+
getRpcUrl,
|
|
11
|
+
getTokenSymbolFromContract,
|
|
12
|
+
} from '../utils'
|
|
13
|
+
import ERC20Abi from '../abis/erc20'
|
|
14
|
+
// TODO: use ethers for contract calls (without performance reduction).
|
|
15
|
+
import Web3 from 'web3'
|
|
16
|
+
|
|
17
|
+
const web3 = new Web3()
|
|
8
18
|
|
|
9
19
|
export async function buildList(
|
|
10
20
|
chainId: ChainId,
|
|
11
21
|
l1TokenList: TokenList
|
|
12
22
|
): Promise<TokenList> {
|
|
23
|
+
web3.setProvider(getRpcUrl(chainId))
|
|
13
24
|
const tokenAddressMap = await getMappingProvider(
|
|
14
25
|
chainId,
|
|
15
26
|
l1TokenList
|
|
@@ -17,9 +28,15 @@ export async function buildList(
|
|
|
17
28
|
const mappedTokens = []
|
|
18
29
|
for (const rootToken of l1TokenList.tokens) {
|
|
19
30
|
const childToken = tokenAddressMap[rootToken.address.toLowerCase()]
|
|
31
|
+
const childTokenAddress = childToken
|
|
32
|
+
? ethers.utils.getAddress(
|
|
33
|
+
typeof childToken === 'object' ? childToken.child_token : childToken
|
|
34
|
+
)
|
|
35
|
+
: undefined
|
|
20
36
|
const childTokenValid = Boolean(
|
|
21
|
-
|
|
22
|
-
(typeof childToken === 'object' ? !childToken.deleted : true)
|
|
37
|
+
childTokenAddress &&
|
|
38
|
+
(typeof childToken === 'object' ? !childToken.deleted : true) &&
|
|
39
|
+
(await hasExistingTokenContract(childTokenAddress, chainId))
|
|
23
40
|
)
|
|
24
41
|
|
|
25
42
|
if (rootToken.chainId === ChainId.MAINNET) {
|
|
@@ -41,11 +58,7 @@ export async function buildList(
|
|
|
41
58
|
extensions: {
|
|
42
59
|
bridgeInfo: {
|
|
43
60
|
[chainId]: {
|
|
44
|
-
tokenAddress:
|
|
45
|
-
typeof childToken === 'object'
|
|
46
|
-
? childToken.child_token
|
|
47
|
-
: childToken!
|
|
48
|
-
),
|
|
61
|
+
tokenAddress: childTokenAddress,
|
|
49
62
|
},
|
|
50
63
|
},
|
|
51
64
|
},
|
|
@@ -61,11 +74,7 @@ export async function buildList(
|
|
|
61
74
|
const childTokenInfo: TokenInfo = {
|
|
62
75
|
...rootToken,
|
|
63
76
|
chainId: chainId,
|
|
64
|
-
address:
|
|
65
|
-
typeof childToken === 'object'
|
|
66
|
-
? childToken.child_token
|
|
67
|
-
: childToken!
|
|
68
|
-
),
|
|
77
|
+
address: childTokenAddress,
|
|
69
78
|
...toRootExtensions,
|
|
70
79
|
} as unknown as TokenInfo
|
|
71
80
|
mappedTokens.push(childTokenInfo)
|
|
@@ -83,6 +92,17 @@ export async function buildList(
|
|
|
83
92
|
return tokenList
|
|
84
93
|
}
|
|
85
94
|
|
|
95
|
+
// using a symbol lookup contract call to check whether the token exists on the L2
|
|
96
|
+
async function hasExistingTokenContract(address: string, chainId: ChainId) {
|
|
97
|
+
try {
|
|
98
|
+
const contract: Contract = new web3.eth.Contract(ERC20Abi, address)
|
|
99
|
+
await getTokenSymbolFromContract(contract)
|
|
100
|
+
} catch {
|
|
101
|
+
return false
|
|
102
|
+
}
|
|
103
|
+
return true
|
|
104
|
+
}
|
|
105
|
+
|
|
86
106
|
function getMappingProvider(chainId: ChainId, l1TokenList: TokenList) {
|
|
87
107
|
switch (chainId) {
|
|
88
108
|
case ChainId.ARBITRUM_ONE:
|
package/src/utils.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { TokenInfo, TokenList } from '@uniswap/token-lists'
|
|
2
2
|
import { readFileSync, existsSync } from 'fs'
|
|
3
3
|
import axios from 'axios'
|
|
4
|
+
import { ChainId } from './constants/chainId'
|
|
5
|
+
import { Contract } from 'web3-eth-contract'
|
|
4
6
|
|
|
5
7
|
export type TokenListOrFetchableTokenList = TokenList | string
|
|
6
8
|
|
|
@@ -89,3 +91,29 @@ export const isTokenList = (obj: any) => {
|
|
|
89
91
|
throw new Error('tokenlist typeguard error: token missing required key')
|
|
90
92
|
}
|
|
91
93
|
}
|
|
94
|
+
|
|
95
|
+
export function getRpcUrl(chainId: ChainId): string {
|
|
96
|
+
switch (chainId) {
|
|
97
|
+
case ChainId.MAINNET:
|
|
98
|
+
return 'https://cloudflare-eth.com/'
|
|
99
|
+
case ChainId.OPTIMISM:
|
|
100
|
+
return 'https://mainnet.optimism.io'
|
|
101
|
+
case ChainId.OPTIMISTIC_KOVAN:
|
|
102
|
+
return 'https://kovan.optimism.io'
|
|
103
|
+
case ChainId.ARBITRUM_ONE:
|
|
104
|
+
return 'https://arb1.arbitrum.io/rpc'
|
|
105
|
+
case ChainId.ARBITRUM_RINKEBY:
|
|
106
|
+
return 'https://rinkeby.arbitrum.io/rpc'
|
|
107
|
+
case ChainId.POLYGON:
|
|
108
|
+
return 'https://polygon-rpc.com/'
|
|
109
|
+
case ChainId.POLYGON_MUMBAI:
|
|
110
|
+
return 'https://rpc-endpoints.superfluid.dev/mumbai'
|
|
111
|
+
default:
|
|
112
|
+
}
|
|
113
|
+
throw new Error('Unsupported ChainId')
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export async function getTokenSymbolFromContract(tokenContract: Contract) {
|
|
117
|
+
const symbol = await Promise.all([tokenContract.methods.symbol().call()])
|
|
118
|
+
return symbol
|
|
119
|
+
}
|