@snowbridge/registry 0.3.3 → 0.4.1-beta.1
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/.turbo/turbo-build.log +1 -2
- package/dist/index.d.ts +6 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +27 -2
- package/dist/local_e2e_bridge_info.g.d.ts +141 -0
- package/dist/local_e2e_bridge_info.g.d.ts.map +1 -0
- package/dist/local_e2e_bridge_info.g.js +142 -0
- package/dist/paseo_sepolia_bridge_info.g.d.ts +331 -0
- package/dist/paseo_sepolia_bridge_info.g.d.ts.map +1 -0
- package/dist/paseo_sepolia_bridge_info.g.js +351 -0
- package/dist/polkadot_mainnet_bridge_info.g.d.ts +2137 -0
- package/dist/polkadot_mainnet_bridge_info.g.d.ts.map +1 -0
- package/dist/polkadot_mainnet_bridge_info.g.js +2454 -0
- package/dist/transfers.d.ts +3 -8
- package/dist/transfers.d.ts.map +1 -1
- package/dist/transfers.js +73 -215
- package/dist/westend_sepolia_bridge_info.g.d.ts +432 -0
- package/dist/westend_sepolia_bridge_info.g.d.ts.map +1 -0
- package/dist/westend_sepolia_bridge_info.g.js +487 -0
- package/package.json +7 -7
- package/scripts/buildRegistry.ts +609 -37
- package/src/index.ts +27 -2
- package/src/local_e2e_bridge_info.g.ts +140 -0
- package/src/paseo_sepolia_bridge_info.g.ts +350 -0
- package/src/polkadot_mainnet_bridge_info.g.ts +2477 -0
- package/src/transfers.ts +72 -265
- package/src/westend_sepolia_bridge_info.g.ts +495 -0
- package/dist/environment.d.ts +0 -3
- package/dist/environment.d.ts.map +0 -1
- package/dist/environment.js +0 -181
- package/dist/local_e2e.registry.json +0 -391
- package/dist/paseo_sepolia.registry.json +0 -231
- package/dist/polkadot_mainnet.registry.json +0 -1805
- package/dist/registry.d.ts +0 -3
- package/dist/registry.d.ts.map +0 -1
- package/dist/registry.js +0 -61
- package/dist/westend_sepolia.registry.json +0 -283
- package/src/environment.ts +0 -185
- package/src/local_e2e.registry.json +0 -391
- package/src/paseo_sepolia.registry.json +0 -231
- package/src/polkadot_mainnet.registry.json +0 -1805
- package/src/registry.ts +0 -63
- package/src/westend_sepolia.registry.json +0 -283
package/scripts/buildRegistry.ts
CHANGED
|
@@ -16,15 +16,530 @@ import {
|
|
|
16
16
|
PrecompileMap,
|
|
17
17
|
XC20TokenMap,
|
|
18
18
|
XcmVersion,
|
|
19
|
+
BridgeInfo,
|
|
20
|
+
TransferRoute,
|
|
21
|
+
ChainId,
|
|
22
|
+
ChainKey,
|
|
23
|
+
ParachainKind,
|
|
19
24
|
} from "@snowbridge/base-types"
|
|
20
25
|
import { ApiPromise, HttpProvider, WsProvider } from "@polkadot/api"
|
|
21
26
|
import { isFunction } from "@polkadot/util"
|
|
22
27
|
import { writeFile } from "fs/promises"
|
|
23
|
-
import { environmentFor } from "../src"
|
|
24
28
|
import { AbstractProvider, Contract, ethers } from "ethers"
|
|
25
29
|
import { IGatewayV1__factory as IGateway__factory } from "@snowbridge/contract-types"
|
|
26
30
|
import { parachains as ParaImpl, xcmBuilder, assetsV2 } from "@snowbridge/api"
|
|
27
31
|
|
|
32
|
+
export type Path = {
|
|
33
|
+
source: ChainId
|
|
34
|
+
destination: ChainId
|
|
35
|
+
asset: string
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const SNOWBRIDGE_ENV: { [env: string]: Environment } = {
|
|
39
|
+
local_e2e: {
|
|
40
|
+
name: "local_e2e",
|
|
41
|
+
ethChainId: 11155111,
|
|
42
|
+
beaconApiUrl: "http://127.0.0.1:9596",
|
|
43
|
+
ethereumChains: {
|
|
44
|
+
"11155111": "ws://127.0.0.1:8546",
|
|
45
|
+
},
|
|
46
|
+
relaychainUrl: "ws://127.0.0.1:9944",
|
|
47
|
+
parachains: {
|
|
48
|
+
"1000": "ws://127.0.0.1:12144",
|
|
49
|
+
"1002": "ws://127.0.0.1:11144",
|
|
50
|
+
"2000": "ws://127.0.0.1:13144",
|
|
51
|
+
},
|
|
52
|
+
gatewayContract: "0xb1185ede04202fe62d38f5db72f71e38ff3e8305",
|
|
53
|
+
beefyContract: "0x83428c7db9815f482a39a1715684dcf755021997",
|
|
54
|
+
assetHubParaId: 1000,
|
|
55
|
+
bridgeHubParaId: 1002,
|
|
56
|
+
v2_parachains: [1000],
|
|
57
|
+
indexerGraphQlUrl: "http://127.0.0.1/does/not/exist",
|
|
58
|
+
},
|
|
59
|
+
paseo_sepolia: {
|
|
60
|
+
name: "paseo_sepolia",
|
|
61
|
+
ethChainId: 11155111,
|
|
62
|
+
beaconApiUrl: "https://lodestar-sepolia.chainsafe.io",
|
|
63
|
+
ethereumChains: {
|
|
64
|
+
"11155111": "https://ethereum-sepolia-rpc.publicnode.com",
|
|
65
|
+
},
|
|
66
|
+
relaychainUrl: "wss://paseo-rpc.n.dwellir.com",
|
|
67
|
+
parachains: {
|
|
68
|
+
"1000": "wss://asset-hub-paseo-rpc.n.dwellir.com",
|
|
69
|
+
"1002": "wss://bridge-hub-paseo.dotters.network",
|
|
70
|
+
"3369": "wss://paseo-muse-rpc.polkadot.io",
|
|
71
|
+
"2043": `wss://parachain-testnet-rpc.origin-trail.network`,
|
|
72
|
+
},
|
|
73
|
+
gatewayContract: "0x1607c1368bc943130258318c91bbd8cff3d063e6",
|
|
74
|
+
beefyContract: "0x2c780945beb1241fe9c645800110cb9c4bbbb639",
|
|
75
|
+
assetHubParaId: 1000,
|
|
76
|
+
bridgeHubParaId: 1002,
|
|
77
|
+
v2_parachains: [1000],
|
|
78
|
+
indexerGraphQlUrl:
|
|
79
|
+
"https://snowbridge.squids.live/snowbridge-subsquid-paseo@v1/api/graphql",
|
|
80
|
+
metadataOverrides: {
|
|
81
|
+
// Change the name of TRAC
|
|
82
|
+
"0xef32abea56beff54f61da319a7311098d6fbcea9": {
|
|
83
|
+
name: "OriginTrail TRAC",
|
|
84
|
+
symbol: "TRAC",
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
polkadot_mainnet: {
|
|
89
|
+
name: "polkadot_mainnet",
|
|
90
|
+
ethChainId: 1,
|
|
91
|
+
beaconApiUrl: "https://lodestar-mainnet.chainsafe.io",
|
|
92
|
+
ethereumChains: {
|
|
93
|
+
"1": "https://ethereum-rpc.publicnode.com",
|
|
94
|
+
"1284": "https://rpc.api.moonbeam.network",
|
|
95
|
+
"8453": "https://base-rpc.publicnode.com",
|
|
96
|
+
"42161": "https://arbitrum-one-rpc.publicnode.com",
|
|
97
|
+
"10": "https://optimism-rpc.publicnode.com",
|
|
98
|
+
},
|
|
99
|
+
relaychainUrl: "https://polkadot-rpc.n.dwellir.com",
|
|
100
|
+
parachains: {
|
|
101
|
+
"1000": "wss://polkadot-asset-hub-rpc.polkadot.io",
|
|
102
|
+
"1002": "wss://polkadot-bridge-hub-rpc.polkadot.io",
|
|
103
|
+
"3369": "wss://polkadot-mythos-rpc.polkadot.io",
|
|
104
|
+
"2034": "wss://hydration-rpc.n.dwellir.com",
|
|
105
|
+
"2030": "wss://bifrost-polkadot.ibp.network",
|
|
106
|
+
"2004": "wss://moonbeam.ibp.network",
|
|
107
|
+
"2000": "wss://acala-rpc-0.aca-api.network",
|
|
108
|
+
"2043": "wss://parachain-rpc.origin-trail.network",
|
|
109
|
+
// TODO: Add back in jampton once we have an indexer in place.
|
|
110
|
+
//"3397": "wss://rpc.jamton.network",
|
|
111
|
+
},
|
|
112
|
+
gatewayContract: "0x27ca963c279c93801941e1eb8799c23f407d68e7",
|
|
113
|
+
beefyContract: "0x1817874feab3ce053d0f40abc23870db35c2affc",
|
|
114
|
+
assetHubParaId: 1000,
|
|
115
|
+
bridgeHubParaId: 1002,
|
|
116
|
+
v2_parachains: [1000],
|
|
117
|
+
indexerGraphQlUrl:
|
|
118
|
+
"https://subsquid.snowbridge.network/graphql",
|
|
119
|
+
kusama: {
|
|
120
|
+
assetHubParaId: 1000,
|
|
121
|
+
bridgeHubParaId: 1002,
|
|
122
|
+
parachains: {
|
|
123
|
+
"1000": "wss://asset-hub-kusama-rpc.n.dwellir.com",
|
|
124
|
+
"1002": "https://bridge-hub-kusama-rpc.n.dwellir.com",
|
|
125
|
+
},
|
|
126
|
+
},
|
|
127
|
+
precompiles: {
|
|
128
|
+
// Add override for mythos token and add precompile for moonbeam
|
|
129
|
+
"2004": "0x000000000000000000000000000000000000081a",
|
|
130
|
+
},
|
|
131
|
+
metadataOverrides: {
|
|
132
|
+
// Change the name of TRAC
|
|
133
|
+
"0xaa7a9ca87d3694b5755f213b5d04094b8d0f0a6f": {
|
|
134
|
+
name: "OriginTrail TRAC",
|
|
135
|
+
},
|
|
136
|
+
},
|
|
137
|
+
l2Bridge: {
|
|
138
|
+
acrossAPIUrl: "https://app.across.to/api",
|
|
139
|
+
l1AdapterAddress: "0xd3b11c36404b092645522b682832fcdee07d2668",
|
|
140
|
+
l1HandlerAddress: "0x924a9f036260ddd5808007e1aa95f08ed08aa569",
|
|
141
|
+
l1FeeTokenAddress: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
|
|
142
|
+
l1SwapQuoterAddress: "0x61ffe014ba17989e743c5f6cb21bf9697530b21e",
|
|
143
|
+
l1SwapRouterAddress: "0xe592427a0aece92de3edee1f18e0157c05861564",
|
|
144
|
+
l2Chains: {
|
|
145
|
+
"8453": {
|
|
146
|
+
adapterAddress: "0x07fe4E7340976FC873B74bAfe3C3e5b0e01f3665".toLowerCase(),
|
|
147
|
+
feeTokenAddress: "0x4200000000000000000000000000000000000006",
|
|
148
|
+
swapRoutes: [
|
|
149
|
+
// WETH
|
|
150
|
+
{
|
|
151
|
+
inputToken: "0x4200000000000000000000000000000000000006",
|
|
152
|
+
outputToken: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
|
|
153
|
+
swapFee: 0,
|
|
154
|
+
},
|
|
155
|
+
// USDC
|
|
156
|
+
{
|
|
157
|
+
inputToken: "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",
|
|
158
|
+
outputToken: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
|
|
159
|
+
swapFee: 500,
|
|
160
|
+
},
|
|
161
|
+
],
|
|
162
|
+
},
|
|
163
|
+
"42161": {
|
|
164
|
+
adapterAddress: "0x836895Ad176235Dfe9C59b3df56C7579d90ea338".toLowerCase(),
|
|
165
|
+
feeTokenAddress: "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1".toLowerCase(),
|
|
166
|
+
swapRoutes: [
|
|
167
|
+
// WETH
|
|
168
|
+
{
|
|
169
|
+
inputToken: "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1".toLowerCase(),
|
|
170
|
+
outputToken: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
|
|
171
|
+
swapFee: 0,
|
|
172
|
+
},
|
|
173
|
+
// USDC
|
|
174
|
+
{
|
|
175
|
+
inputToken: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831".toLowerCase(),
|
|
176
|
+
outputToken: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
|
|
177
|
+
swapFee: 500,
|
|
178
|
+
},
|
|
179
|
+
],
|
|
180
|
+
},
|
|
181
|
+
"10": {
|
|
182
|
+
adapterAddress: "0x836895Ad176235Dfe9C59b3df56C7579d90ea338".toLowerCase(),
|
|
183
|
+
feeTokenAddress: "0x4200000000000000000000000000000000000006".toLowerCase(),
|
|
184
|
+
swapRoutes: [
|
|
185
|
+
// WETH
|
|
186
|
+
{
|
|
187
|
+
inputToken: "0x4200000000000000000000000000000000000006".toLowerCase(),
|
|
188
|
+
outputToken: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
|
|
189
|
+
swapFee: 0,
|
|
190
|
+
},
|
|
191
|
+
// USDC
|
|
192
|
+
{
|
|
193
|
+
inputToken: "0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85".toLowerCase(),
|
|
194
|
+
outputToken: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
|
|
195
|
+
swapFee: 500,
|
|
196
|
+
},
|
|
197
|
+
],
|
|
198
|
+
},
|
|
199
|
+
},
|
|
200
|
+
},
|
|
201
|
+
},
|
|
202
|
+
westend_sepolia: {
|
|
203
|
+
name: "westend_sepolia",
|
|
204
|
+
ethChainId: 11155111,
|
|
205
|
+
beaconApiUrl: "https://lodestar-sepolia.chainsafe.io",
|
|
206
|
+
ethereumChains: {
|
|
207
|
+
"11155111": "https://ethereum-sepolia-rpc.publicnode.com",
|
|
208
|
+
"84532": "https://base-sepolia-rpc.publicnode.com",
|
|
209
|
+
"421614": "https://arbitrum-sepolia-rpc.publicnode.com",
|
|
210
|
+
},
|
|
211
|
+
relaychainUrl: "https://westend-rpc.polkadot.io",
|
|
212
|
+
parachains: {
|
|
213
|
+
"1000": "https://westend-asset-hub-rpc.polkadot.io",
|
|
214
|
+
"1002": "https://westend-bridge-hub-rpc.polkadot.io",
|
|
215
|
+
},
|
|
216
|
+
gatewayContract: "0x9ed8b47bc3417e3bd0507adc06e56e2fa360a4e9",
|
|
217
|
+
beefyContract: "0xEBD1CFcF82BaA170b86BDe532f69A6A49c6c790D".toLowerCase(),
|
|
218
|
+
assetHubParaId: 1000,
|
|
219
|
+
bridgeHubParaId: 1002,
|
|
220
|
+
v2_parachains: [1000],
|
|
221
|
+
indexerGraphQlUrl:
|
|
222
|
+
"https://snowbridge.squids.live/snowbridge-subsquid-westend@v1/api/graphql",
|
|
223
|
+
l2Bridge: {
|
|
224
|
+
acrossAPIUrl: "https://testnet.across.to/api",
|
|
225
|
+
l1AdapterAddress: "0xCDa9bFf39cdF39E95F4B699422E422195091126d".toLowerCase(),
|
|
226
|
+
l1HandlerAddress: "0x924a9f036260ddd5808007e1aa95f08ed08aa569",
|
|
227
|
+
l1FeeTokenAddress: "0xfff9976782d46cc05630d1f6ebab18b2324d6b14",
|
|
228
|
+
l1SwapRouterAddress: "0x3bfa4769fb09eefc5a80d6e87c3b9c650f7ae48e",
|
|
229
|
+
l1SwapQuoterAddress: "0xed1f6473345f45b75f8179591dd5ba1888cf2fb3",
|
|
230
|
+
l2Chains: {
|
|
231
|
+
"84532": {
|
|
232
|
+
adapterAddress: "0xf06939613a3838af11104c898758220db9093679",
|
|
233
|
+
feeTokenAddress: "0x4200000000000000000000000000000000000006",
|
|
234
|
+
swapRoutes: [
|
|
235
|
+
// WETH
|
|
236
|
+
{
|
|
237
|
+
inputToken: "0x4200000000000000000000000000000000000006",
|
|
238
|
+
outputToken: "0xfff9976782d46cc05630d1f6ebab18b2324d6b14",
|
|
239
|
+
swapFee: 0,
|
|
240
|
+
},
|
|
241
|
+
// USDC
|
|
242
|
+
{
|
|
243
|
+
inputToken: "0x036cbd53842c5426634e7929541ec2318f3dcf7e",
|
|
244
|
+
outputToken: "0x1c7d4b196cb0c7b01d743fbc6116a902379c7238",
|
|
245
|
+
swapFee: 500,
|
|
246
|
+
},
|
|
247
|
+
],
|
|
248
|
+
},
|
|
249
|
+
"421614": {
|
|
250
|
+
adapterAddress: "0xcB3d8043bDbfB0D9b30de279A09132073d1dE561".toLowerCase(),
|
|
251
|
+
feeTokenAddress: "0x980B62Da83eFf3D4576C647993b0c1D7faf17c73".toLowerCase(),
|
|
252
|
+
swapRoutes: [
|
|
253
|
+
// WETH
|
|
254
|
+
{
|
|
255
|
+
inputToken: "0x980B62Da83eFf3D4576C647993b0c1D7faf17c73".toLowerCase(),
|
|
256
|
+
outputToken: "0xfff9976782d46cc05630d1f6ebab18b2324d6b14".toLowerCase(),
|
|
257
|
+
swapFee: 0,
|
|
258
|
+
},
|
|
259
|
+
// USDC
|
|
260
|
+
{
|
|
261
|
+
inputToken: "0x75faf114eafb1BDbe2F0316DF893fd58CE46AA4d".toLowerCase(),
|
|
262
|
+
outputToken: "0x1c7d4b196cb0c7b01d743fbc6116a902379c7238".toLowerCase(),
|
|
263
|
+
swapFee: 500,
|
|
264
|
+
},
|
|
265
|
+
],
|
|
266
|
+
},
|
|
267
|
+
},
|
|
268
|
+
},
|
|
269
|
+
},
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
export function defaultPathFilter(envName: string): (_: Path) => boolean {
|
|
273
|
+
switch (envName) {
|
|
274
|
+
case "westend_sepolia": {
|
|
275
|
+
return (path: Path) => {
|
|
276
|
+
// Frequency
|
|
277
|
+
if (path.asset === "0x72c610e05eaafcdf1fa7a2da15374ee90edb1620") {
|
|
278
|
+
return false
|
|
279
|
+
}
|
|
280
|
+
// Disable para to para transfers
|
|
281
|
+
if (path.source.kind === "polkadot" && path.destination.kind === "polkadot") {
|
|
282
|
+
return false
|
|
283
|
+
}
|
|
284
|
+
return true
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
case "paseo_sepolia":
|
|
288
|
+
return (path: Path) => {
|
|
289
|
+
// Disallow MUSE to any location but 3369
|
|
290
|
+
if (
|
|
291
|
+
path.asset === "0xb34a6924a02100ba6ef12af1c798285e8f7a16ee" &&
|
|
292
|
+
((path.destination.kind === "polkadot" &&
|
|
293
|
+
path.destination.id !== 3369 &&
|
|
294
|
+
path.source.kind === "ethereum") ||
|
|
295
|
+
(path.source.id !== 3369 && path.source.kind === "polkadot"))
|
|
296
|
+
) {
|
|
297
|
+
return false
|
|
298
|
+
}
|
|
299
|
+
// Disable para to para transfers
|
|
300
|
+
if (path.source.kind === "polkadot" && path.destination.kind === "polkadot") {
|
|
301
|
+
return false
|
|
302
|
+
}
|
|
303
|
+
return true
|
|
304
|
+
}
|
|
305
|
+
case "polkadot_mainnet":
|
|
306
|
+
return (path: Path) => {
|
|
307
|
+
// Disallow MYTH to any location but 3369
|
|
308
|
+
if (
|
|
309
|
+
path.asset === "0xba41ddf06b7ffd89d1267b5a93bfef2424eb2003" &&
|
|
310
|
+
((path.destination.kind === "polkadot" &&
|
|
311
|
+
path.destination.id !== 3369 &&
|
|
312
|
+
path.source.kind === "ethereum") ||
|
|
313
|
+
(path.source.id !== 3369 && path.source.kind === "polkadot"))
|
|
314
|
+
) {
|
|
315
|
+
return false
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// Allow TRAC to go to Hydration (2034) and Neuroweb (2043) only
|
|
319
|
+
if (
|
|
320
|
+
path.asset === "0xaa7a9ca87d3694b5755f213b5d04094b8d0f0a6f" &&
|
|
321
|
+
((path.destination.kind === "polkadot" &&
|
|
322
|
+
path.destination.id !== 2034 &&
|
|
323
|
+
path.destination.id !== 2043 &&
|
|
324
|
+
path.source.kind === "ethereum") ||
|
|
325
|
+
(path.source.id !== 2034 &&
|
|
326
|
+
path.source.id !== 2043 &&
|
|
327
|
+
path.source.kind === "polkadot"))
|
|
328
|
+
) {
|
|
329
|
+
return false
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
// Disable stable coins in the UI from Ethereum to Polkadot
|
|
333
|
+
if (
|
|
334
|
+
(path.asset === "0x9d39a5de30e57443bff2a8307a4256c8797a3497" || // Staked USDe
|
|
335
|
+
path.asset === "0xa3931d71877c0e7a3148cb7eb4463524fec27fbd" || // Savings USD
|
|
336
|
+
path.asset === "0x6b175474e89094c44da98b954eedeac495271d0f") && // DAI
|
|
337
|
+
path.destination.kind === "polkadot" &&
|
|
338
|
+
path.destination.id === 2034 // Hydration
|
|
339
|
+
) {
|
|
340
|
+
return false
|
|
341
|
+
}
|
|
342
|
+
// Disable para to para transfers except for hydration
|
|
343
|
+
if (
|
|
344
|
+
path.source.kind === "polkadot" &&
|
|
345
|
+
path.destination.kind === "polkadot" &&
|
|
346
|
+
!(
|
|
347
|
+
(path.source.id === 2034 && path.destination.id == 1000) ||
|
|
348
|
+
(path.source.id === 1000 && path.destination.id === 2034)
|
|
349
|
+
)
|
|
350
|
+
) {
|
|
351
|
+
return false
|
|
352
|
+
}
|
|
353
|
+
return true
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
default:
|
|
357
|
+
return (_: Path) => true
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
function buildTransferLocations(
|
|
362
|
+
registry: AssetRegistry,
|
|
363
|
+
environment: Environment,
|
|
364
|
+
filter?: (path: Path) => boolean,
|
|
365
|
+
): TransferRoute[] {
|
|
366
|
+
const ethChain = registry.ethereumChains[`ethereum_${registry.ethChainId}`]
|
|
367
|
+
const parachains = Object.values(registry.parachains).filter(
|
|
368
|
+
(p) => !(p.kind === "polkadot" && p.id === registry.bridgeHubParaId),
|
|
369
|
+
)
|
|
370
|
+
|
|
371
|
+
const pathFilter = filter ?? defaultPathFilter(registry.environment)
|
|
372
|
+
|
|
373
|
+
const locations: Path[] = []
|
|
374
|
+
|
|
375
|
+
const ethAssets = Object.keys(ethChain.assets)
|
|
376
|
+
// Bridged paths
|
|
377
|
+
for (const parachain of parachains) {
|
|
378
|
+
const destinationAssets = Object.keys(parachain.assets)
|
|
379
|
+
const commonAssets = new Set(
|
|
380
|
+
ethAssets.filter((sa) => destinationAssets.find((da) => da === sa)),
|
|
381
|
+
)
|
|
382
|
+
for (const asset of commonAssets) {
|
|
383
|
+
const p1: Path = {
|
|
384
|
+
source: { kind: ethChain.kind, id: ethChain.id },
|
|
385
|
+
destination: { kind: parachain.kind, id: parachain.id },
|
|
386
|
+
asset,
|
|
387
|
+
}
|
|
388
|
+
if (pathFilter(p1)) {
|
|
389
|
+
locations.push(p1)
|
|
390
|
+
}
|
|
391
|
+
const p2: Path = {
|
|
392
|
+
source: p1.destination,
|
|
393
|
+
destination: p1.source,
|
|
394
|
+
asset,
|
|
395
|
+
}
|
|
396
|
+
if (pathFilter(p2)) {
|
|
397
|
+
locations.push(p2)
|
|
398
|
+
}
|
|
399
|
+
if (
|
|
400
|
+
parachain.info.evmChainId &&
|
|
401
|
+
registry.ethereumChains[`ethereum_${parachain.info.evmChainId}`]
|
|
402
|
+
) {
|
|
403
|
+
const p3: Path = {
|
|
404
|
+
source: {
|
|
405
|
+
kind: "ethereum",
|
|
406
|
+
id: parachain.info.evmChainId,
|
|
407
|
+
},
|
|
408
|
+
destination: p1.source, // Ethereum
|
|
409
|
+
asset,
|
|
410
|
+
}
|
|
411
|
+
if (pathFilter(p3)) {
|
|
412
|
+
locations.push(p3)
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
// Local paths
|
|
419
|
+
const assetHub = registry.parachains[`polkadot_${registry.assetHubParaId}`]
|
|
420
|
+
for (const parachain of parachains) {
|
|
421
|
+
if (parachain.kind === assetHub.kind && parachain.id === assetHub.id) continue
|
|
422
|
+
const assetHubAssets = Object.keys(assetHub.assets)
|
|
423
|
+
const destinationAssets = Object.keys(parachain.assets)
|
|
424
|
+
|
|
425
|
+
// The asset exists on ethereum, parachain and asset hub
|
|
426
|
+
const commonAssets = new Set(
|
|
427
|
+
ethAssets.filter(
|
|
428
|
+
(sa) =>
|
|
429
|
+
assetHubAssets.find((da) => da === sa) &&
|
|
430
|
+
destinationAssets.find((da) => da === sa),
|
|
431
|
+
),
|
|
432
|
+
)
|
|
433
|
+
for (const asset of commonAssets) {
|
|
434
|
+
const p1: Path = {
|
|
435
|
+
source: { kind: assetHub.kind, id: assetHub.id },
|
|
436
|
+
destination: { kind: parachain.kind, id: parachain.id },
|
|
437
|
+
asset,
|
|
438
|
+
}
|
|
439
|
+
if (pathFilter(p1)) {
|
|
440
|
+
locations.push(p1)
|
|
441
|
+
}
|
|
442
|
+
const p2: Path = {
|
|
443
|
+
source: p1.destination, // Parachain
|
|
444
|
+
destination: p1.source, // Asset Hub
|
|
445
|
+
asset,
|
|
446
|
+
}
|
|
447
|
+
if (pathFilter(p2)) {
|
|
448
|
+
locations.push(p2)
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
// L2 paths
|
|
454
|
+
if (environment.l2Bridge) {
|
|
455
|
+
// Do asset hub only, in future we can loop through all v2 enabled parachains.
|
|
456
|
+
for (const l2ChainKey of Object.keys(environment.l2Bridge.l2Chains)) {
|
|
457
|
+
const l2ChainId = Number(l2ChainKey)
|
|
458
|
+
const l2Chain = environment.l2Bridge.l2Chains[l2ChainId]
|
|
459
|
+
const ethChain = registry.ethereumChains[`ethereum_l2_${l2ChainId}`]
|
|
460
|
+
if (!ethChain || !l2Chain) {
|
|
461
|
+
console.warn(`Could not find ethereum l2 chain ${l2ChainId}. Skipping...`)
|
|
462
|
+
continue
|
|
463
|
+
}
|
|
464
|
+
const assetHubAssets = Object.keys(assetHub.assets)
|
|
465
|
+
const destinationAssets = Object.values(ethChain.assets)
|
|
466
|
+
.map((a) => a.swapTokenAddress?.toLowerCase())
|
|
467
|
+
.filter((a) => a !== undefined)
|
|
468
|
+
|
|
469
|
+
// The asset exists on ethereum, parachain and asset hub
|
|
470
|
+
const commonAssets = new Set(
|
|
471
|
+
ethAssets.filter(
|
|
472
|
+
(sa) =>
|
|
473
|
+
assetHubAssets.find((da) => da === sa) &&
|
|
474
|
+
destinationAssets.find((da) => da === sa),
|
|
475
|
+
),
|
|
476
|
+
)
|
|
477
|
+
for (const asset of commonAssets) {
|
|
478
|
+
const p1: Path = {
|
|
479
|
+
source: { kind: assetHub.kind, id: assetHub.id },
|
|
480
|
+
destination: { kind: ethChain.kind, id: ethChain.id },
|
|
481
|
+
asset,
|
|
482
|
+
}
|
|
483
|
+
if (pathFilter(p1)) {
|
|
484
|
+
locations.push(p1)
|
|
485
|
+
}
|
|
486
|
+
const p2: Path = {
|
|
487
|
+
source: p1.destination, // L2 Chain
|
|
488
|
+
destination: p1.source, // Asset Hub
|
|
489
|
+
asset,
|
|
490
|
+
}
|
|
491
|
+
if (pathFilter(p2)) {
|
|
492
|
+
locations.push(p2)
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
const results: TransferRoute[] = []
|
|
498
|
+
for (const location of locations) {
|
|
499
|
+
let source = results.find(
|
|
500
|
+
(s) =>
|
|
501
|
+
s.from.kind === location.source.kind &&
|
|
502
|
+
s.from.id === location.source.id &&
|
|
503
|
+
s.to.kind === location.destination.kind &&
|
|
504
|
+
s.to.id === location.destination.id,
|
|
505
|
+
)
|
|
506
|
+
|
|
507
|
+
if (!source) {
|
|
508
|
+
source = {
|
|
509
|
+
from: location.source,
|
|
510
|
+
to: location.destination,
|
|
511
|
+
assets: [],
|
|
512
|
+
}
|
|
513
|
+
results.push(source)
|
|
514
|
+
}
|
|
515
|
+
source.assets = source.assets.concat(location.asset)
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
// Combine all paths into routes
|
|
520
|
+
const results: TransferRoute[] = []
|
|
521
|
+
for (const location of locations) {
|
|
522
|
+
let source = results.find(
|
|
523
|
+
(s) =>
|
|
524
|
+
s.from.kind === location.source.kind &&
|
|
525
|
+
s.from.id === location.source.id &&
|
|
526
|
+
s.to.kind === location.destination.kind &&
|
|
527
|
+
s.to.id === location.destination.id,
|
|
528
|
+
)
|
|
529
|
+
|
|
530
|
+
if (!source) {
|
|
531
|
+
source = {
|
|
532
|
+
from: location.source,
|
|
533
|
+
to: location.destination,
|
|
534
|
+
assets: [],
|
|
535
|
+
}
|
|
536
|
+
results.push(source)
|
|
537
|
+
}
|
|
538
|
+
source.assets = source.assets.concat(location.asset)
|
|
539
|
+
}
|
|
540
|
+
return results
|
|
541
|
+
}
|
|
542
|
+
|
|
28
543
|
async function buildRegistry(environment: Environment): Promise<AssetRegistry> {
|
|
29
544
|
const {
|
|
30
545
|
relaychainUrl,
|
|
@@ -139,6 +654,7 @@ async function buildRegistry(environment: Environment): Promise<AssetRegistry> {
|
|
|
139
654
|
const para = await indexParachain(
|
|
140
655
|
accessor,
|
|
141
656
|
providers[assetHubParaId.toString()].accessor,
|
|
657
|
+
"polkadot",
|
|
142
658
|
ethChainId,
|
|
143
659
|
parachainId,
|
|
144
660
|
assetHubParaId,
|
|
@@ -149,7 +665,7 @@ async function buildRegistry(environment: Environment): Promise<AssetRegistry> {
|
|
|
149
665
|
return { parachainId, para }
|
|
150
666
|
}),
|
|
151
667
|
)) {
|
|
152
|
-
paras[parachainId
|
|
668
|
+
paras[`polkadot_${parachainId}`] = para
|
|
153
669
|
}
|
|
154
670
|
|
|
155
671
|
// Index Ethereum chain
|
|
@@ -170,7 +686,7 @@ async function buildRegistry(environment: Environment): Promise<AssetRegistry> {
|
|
|
170
686
|
)
|
|
171
687
|
}),
|
|
172
688
|
)) {
|
|
173
|
-
ethChains[ethChainInfo.
|
|
689
|
+
ethChains[ethChainInfo.key] = ethChainInfo
|
|
174
690
|
}
|
|
175
691
|
|
|
176
692
|
let kusamaConfig: KusamaConfig | undefined
|
|
@@ -187,6 +703,7 @@ async function buildRegistry(environment: Environment): Promise<AssetRegistry> {
|
|
|
187
703
|
const para = await indexParachain(
|
|
188
704
|
accessor,
|
|
189
705
|
providers[assetHubParaId].accessor,
|
|
706
|
+
"kusama",
|
|
190
707
|
ethChainId,
|
|
191
708
|
accessor.parachainId,
|
|
192
709
|
assetHubParaId,
|
|
@@ -195,7 +712,7 @@ async function buildRegistry(environment: Environment): Promise<AssetRegistry> {
|
|
|
195
712
|
)
|
|
196
713
|
|
|
197
714
|
const kusamaParas: ParachainMap = {}
|
|
198
|
-
kusamaParas[para.
|
|
715
|
+
kusamaParas[para.key] = para
|
|
199
716
|
|
|
200
717
|
kusamaConfig = {
|
|
201
718
|
parachains: kusamaParas,
|
|
@@ -304,12 +821,13 @@ async function checkSnowbridgeV2Support(
|
|
|
304
821
|
async function indexParachain(
|
|
305
822
|
parachain: ParaImpl.ParachainBase,
|
|
306
823
|
assetHub: ParaImpl.ParachainBase,
|
|
824
|
+
kind: ParachainKind,
|
|
307
825
|
ethChainId: number,
|
|
308
826
|
parachainId: number,
|
|
309
827
|
assetHubParaId: number,
|
|
310
828
|
pnaAssets: PNAMap,
|
|
311
829
|
assetOverrides: AssetOverrideMap,
|
|
312
|
-
v2_parachains?: number[],
|
|
830
|
+
v2_parachains?: readonly number[],
|
|
313
831
|
): Promise<Parachain> {
|
|
314
832
|
const info = await parachain.chainProperties()
|
|
315
833
|
|
|
@@ -360,6 +878,7 @@ async function indexParachain(
|
|
|
360
878
|
info.accountType === "AccountId32"
|
|
361
879
|
? "0x0000000000000000000000000000000000000000000000000000000000000000"
|
|
362
880
|
: "0x0000000000000000000000000000000000000000",
|
|
881
|
+
false,
|
|
363
882
|
)
|
|
364
883
|
|
|
365
884
|
let estimatedExecutionFeeDOT = 0n
|
|
@@ -368,7 +887,7 @@ async function indexParachain(
|
|
|
368
887
|
const destinationXcm = xcmBuilder.buildParachainERC20ReceivedXcmOnDestination(
|
|
369
888
|
parachain.provider.registry,
|
|
370
889
|
ethChainId,
|
|
371
|
-
|
|
890
|
+
assetsV2.ETHER_TOKEN_ADDRESS,
|
|
372
891
|
340282366920938463463374607431768211455n,
|
|
373
892
|
340282366920938463463374607431768211455n,
|
|
374
893
|
info.accountType === "AccountId32"
|
|
@@ -386,7 +905,9 @@ async function indexParachain(
|
|
|
386
905
|
)
|
|
387
906
|
}
|
|
388
907
|
return {
|
|
389
|
-
parachainId,
|
|
908
|
+
id: parachainId,
|
|
909
|
+
kind,
|
|
910
|
+
key: `${kind}_${parachainId}`,
|
|
390
911
|
features: {
|
|
391
912
|
hasPalletXcm,
|
|
392
913
|
hasDryRunApi,
|
|
@@ -419,10 +940,10 @@ async function indexEthChain(
|
|
|
419
940
|
metadataOverrides: ERC20MetadataOverrideMap,
|
|
420
941
|
l2Chains: { [l2ChainId: number]: L2ForwardMetadata },
|
|
421
942
|
): Promise<EthereumChain> {
|
|
422
|
-
const
|
|
943
|
+
const name = networkName !== "unknown" ? networkName : undefined
|
|
423
944
|
if (networkChainId == ethChainId) {
|
|
424
945
|
// Asset Hub and get meta data
|
|
425
|
-
const assetHub = parachains[assetHubParaId
|
|
946
|
+
const assetHub = parachains[`polkadot_${assetHubParaId}`]
|
|
426
947
|
const gateway = IGateway__factory.connect(gatewayAddress, provider)
|
|
427
948
|
|
|
428
949
|
const assets: ERC20MetadataMap = {}
|
|
@@ -475,38 +996,42 @@ async function indexEthChain(
|
|
|
475
996
|
)
|
|
476
997
|
}
|
|
477
998
|
return {
|
|
478
|
-
|
|
999
|
+
kind: "ethereum",
|
|
1000
|
+
id: networkChainId,
|
|
1001
|
+
name,
|
|
479
1002
|
assets,
|
|
480
|
-
|
|
1003
|
+
key: `ethereum_${networkChainId}`,
|
|
481
1004
|
baseDeliveryGas: 120_000n,
|
|
482
1005
|
}
|
|
483
1006
|
} else if (networkChainId in l2Chains) {
|
|
484
1007
|
const assets: ERC20MetadataMap = {}
|
|
485
1008
|
for (const route of l2Chains[networkChainId].swapRoutes) {
|
|
486
1009
|
let asset = await assetErc20Metadata(provider, route.inputToken)
|
|
487
|
-
assets[route.inputToken] = {
|
|
1010
|
+
assets[route.inputToken.toLowerCase()] = {
|
|
488
1011
|
...asset,
|
|
489
|
-
swapTokenAddress: route.outputToken,
|
|
1012
|
+
swapTokenAddress: route.outputToken.toLowerCase(),
|
|
490
1013
|
swapFee: route.swapFee,
|
|
491
1014
|
}
|
|
492
1015
|
}
|
|
493
|
-
assets[
|
|
494
|
-
token:
|
|
1016
|
+
assets[assetsV2.ETHER_TOKEN_ADDRESS] = {
|
|
1017
|
+
token: assetsV2.ETHER_TOKEN_ADDRESS,
|
|
495
1018
|
name: "Ether",
|
|
496
1019
|
symbol: "Ether",
|
|
497
1020
|
decimals: 18,
|
|
498
|
-
swapTokenAddress:
|
|
1021
|
+
swapTokenAddress: assetsV2.ETHER_TOKEN_ADDRESS,
|
|
499
1022
|
swapFee: 0,
|
|
500
1023
|
}
|
|
501
1024
|
return {
|
|
502
|
-
|
|
1025
|
+
kind: "ethereum_l2",
|
|
1026
|
+
id: networkChainId,
|
|
1027
|
+
name,
|
|
503
1028
|
assets,
|
|
504
|
-
|
|
1029
|
+
key: `ethereum_l2_${networkChainId}`,
|
|
505
1030
|
}
|
|
506
1031
|
} else {
|
|
507
1032
|
let evmParachainChain: Parachain | undefined
|
|
508
1033
|
for (const paraId in parachains) {
|
|
509
|
-
const parachain = parachains[paraId]
|
|
1034
|
+
const parachain = parachains[paraId as ChainKey<"polkadot">]
|
|
510
1035
|
if (parachain.info.evmChainId === networkChainId) {
|
|
511
1036
|
evmParachainChain = parachain
|
|
512
1037
|
break
|
|
@@ -526,7 +1051,7 @@ async function indexEthChain(
|
|
|
526
1051
|
xcTokenMap[token] = xc20
|
|
527
1052
|
assets[xc20] = asset
|
|
528
1053
|
}
|
|
529
|
-
const paraId = evmParachainChain.
|
|
1054
|
+
const paraId = evmParachainChain.id.toString()
|
|
530
1055
|
if (!(paraId in precompiles)) {
|
|
531
1056
|
throw Error(
|
|
532
1057
|
`No precompile configured for parachain ${paraId} (ethereum chain ${networkChainId}).`,
|
|
@@ -548,13 +1073,15 @@ async function indexEthChain(
|
|
|
548
1073
|
assets[evmParachainChain.xcDOT] = xc20DOTAsset
|
|
549
1074
|
|
|
550
1075
|
return {
|
|
551
|
-
|
|
552
|
-
|
|
1076
|
+
kind: "ethereum",
|
|
1077
|
+
id: networkChainId,
|
|
1078
|
+
key: `ethereum_${networkChainId}`,
|
|
1079
|
+
name,
|
|
1080
|
+
evmParachainId: evmParachainChain.id,
|
|
553
1081
|
assets,
|
|
554
1082
|
precompile,
|
|
555
1083
|
xcDOT: evmParachainChain.xcDOT,
|
|
556
1084
|
xcTokenMap,
|
|
557
|
-
id: id ?? `evm_${evmParachainChain.info.specName}`,
|
|
558
1085
|
}
|
|
559
1086
|
}
|
|
560
1087
|
}
|
|
@@ -613,7 +1140,7 @@ async function assetErc20Metadata(
|
|
|
613
1140
|
erc20Metadata.decimals(),
|
|
614
1141
|
])
|
|
615
1142
|
return {
|
|
616
|
-
token,
|
|
1143
|
+
token: token.toLowerCase(),
|
|
617
1144
|
name: String(name),
|
|
618
1145
|
symbol: String(symbol),
|
|
619
1146
|
decimals: Number(decimals),
|
|
@@ -652,18 +1179,63 @@ async function getRegisteredPnas(
|
|
|
652
1179
|
if (process.env.NODE_ENV !== undefined) {
|
|
653
1180
|
env = process.env.NODE_ENV
|
|
654
1181
|
}
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
1182
|
+
if (!(env in SNOWBRIDGE_ENV)) {
|
|
1183
|
+
throw Error(`Unknown environment ${env}.`)
|
|
1184
|
+
}
|
|
1185
|
+
const environment = SNOWBRIDGE_ENV[env]
|
|
1186
|
+
const registry = await buildRegistry(environment)
|
|
1187
|
+
const routes = buildTransferLocations(registry, environment)
|
|
1188
|
+
const bridge: BridgeInfo = { environment, routes, registry }
|
|
1189
|
+
const json = generateTsObject(bridge, 4)
|
|
1190
|
+
const fileContents = `const registry = ${json} as const\nexport default registry\n`
|
|
1191
|
+
const filepath = `src/${env}_bridge_info.g.ts`
|
|
1192
|
+
await writeFile(filepath, fileContents)
|
|
1193
|
+
})()
|
|
1194
|
+
|
|
1195
|
+
function generateTsObject(value: unknown, indentSize = 4): string {
|
|
1196
|
+
const indentUnit = " ".repeat(indentSize)
|
|
1197
|
+
const serialize = (val: unknown, depth: number): string | undefined => {
|
|
1198
|
+
if (val === null) return "null"
|
|
1199
|
+
if (val === undefined) return undefined
|
|
1200
|
+
if (typeof val === "function" || typeof val === "symbol") return undefined
|
|
1201
|
+
if (typeof val === "bigint") return `${val}n`
|
|
1202
|
+
if (typeof val === "string") return JSON.stringify(val)
|
|
1203
|
+
if (typeof val === "number" || typeof val === "boolean") return String(val)
|
|
1204
|
+
if (Array.isArray(val)) {
|
|
1205
|
+
if (val.length === 0) return "[]"
|
|
1206
|
+
const indent = indentUnit.repeat(depth + 1)
|
|
1207
|
+
const closingIndent = indentUnit.repeat(depth)
|
|
1208
|
+
const items = val
|
|
1209
|
+
.map((item) => {
|
|
1210
|
+
const serialized = serialize(item, depth + 1)
|
|
1211
|
+
return `${indent}${serialized ?? "null"}`
|
|
1212
|
+
})
|
|
1213
|
+
.join(",\n")
|
|
1214
|
+
return `[\n${items}\n${closingIndent}]`
|
|
1215
|
+
}
|
|
1216
|
+
if (typeof val === "object") {
|
|
1217
|
+
const obj = val as Record<string, unknown>
|
|
1218
|
+
const keys = Object.keys(obj)
|
|
1219
|
+
const indent = indentUnit.repeat(depth + 1)
|
|
1220
|
+
const closingIndent = indentUnit.repeat(depth)
|
|
1221
|
+
const items: string[] = []
|
|
1222
|
+
for (const key of keys) {
|
|
1223
|
+
const serialized = serialize(obj[key], depth + 1)
|
|
1224
|
+
if (serialized === undefined) continue
|
|
1225
|
+
const keyLiteral = /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(key)
|
|
1226
|
+
? key
|
|
1227
|
+
: JSON.stringify(key)
|
|
1228
|
+
items.push(`${indent}${keyLiteral}: ${serialized},`)
|
|
661
1229
|
}
|
|
662
|
-
return
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
1230
|
+
if (items.length === 0) return "{}"
|
|
1231
|
+
return `{\n${items.join("\n")}\n${closingIndent}}`
|
|
1232
|
+
}
|
|
1233
|
+
throw new Error(`Unsupported type in registry output: ${typeof val}`)
|
|
1234
|
+
}
|
|
666
1235
|
|
|
667
|
-
const
|
|
668
|
-
|
|
669
|
-
|
|
1236
|
+
const serialized = serialize(value, 0)
|
|
1237
|
+
if (serialized === undefined) {
|
|
1238
|
+
throw new Error("Registry output is not serializable")
|
|
1239
|
+
}
|
|
1240
|
+
return serialized
|
|
1241
|
+
}
|