@gibs/bridge-sdk 1.9.1 → 1.12.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/package.json +12 -5
- package/src/abis.ts +3 -70
- package/src/chain-info.test.ts +968 -0
- package/src/chain-info.ts +161 -127
- package/src/chains.test.ts +123 -0
- package/src/chains.ts +5 -5
- package/src/config.test.ts +679 -0
- package/src/config.ts +138 -118
- package/src/fee-type.test.ts +45 -0
- package/src/fee-type.ts +2 -2
- package/src/image-links.test.ts +160 -0
- package/src/image-links.ts +20 -16
- package/src/index.ts +8 -8
- package/src/settings.test.ts +2754 -0
- package/src/settings.ts +356 -334
- package/src/types.ts +25 -25
- package/tsconfig.json +2 -1
- package/vitest.config.ts +13 -0
- package/dist/src/abis.d.ts +0 -384
- package/dist/src/abis.js +0 -68
- package/dist/src/chain-info.d.ts +0 -130
- package/dist/src/chain-info.js +0 -350
- package/dist/src/chains.d.ts +0 -6
- package/dist/src/chains.js +0 -86
- package/dist/src/config.d.ts +0 -136
- package/dist/src/config.js +0 -386
- package/dist/src/fee-type.d.ts +0 -10
- package/dist/src/fee-type.js +0 -9
- package/dist/src/image-links.d.ts +0 -41
- package/dist/src/image-links.js +0 -45
- package/dist/src/index.d.ts +0 -8
- package/dist/src/index.js +0 -8
- package/dist/src/settings.d.ts +0 -341
- package/dist/src/settings.js +0 -614
- package/dist/src/types.d.ts +0 -44
- package/dist/src/types.js +0 -1
- package/dist/tsconfig.tsbuildinfo +0 -1
package/src/chain-info.ts
CHANGED
|
@@ -1,24 +1,38 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
import { multicallRead } from '@gibs/common/multicall';
|
|
2
|
+
import _ from 'lodash';
|
|
3
|
+
import {
|
|
4
|
+
encodeFunctionData,
|
|
5
|
+
getContract,
|
|
6
|
+
type Hex,
|
|
7
|
+
multicall3Abi,
|
|
8
|
+
type PublicClient,
|
|
9
|
+
zeroAddress,
|
|
10
|
+
} from 'viem';
|
|
11
|
+
import * as abis from './abis.js';
|
|
12
|
+
import { chainsMetadata } from './chains.js';
|
|
13
|
+
import {
|
|
14
|
+
type Chains,
|
|
15
|
+
nativeAssetOut,
|
|
16
|
+
type Pathway,
|
|
17
|
+
pathway,
|
|
18
|
+
toChain,
|
|
19
|
+
uniV2Routers,
|
|
20
|
+
} from './config.js';
|
|
21
|
+
import type { BridgeKey, Token } from './types.js';
|
|
8
22
|
|
|
9
23
|
export type TokenBridgeInfo = {
|
|
10
|
-
originationChainId: Chains
|
|
11
|
-
assetInAddress: Hex
|
|
12
|
-
assetOutAddress: Hex | null
|
|
24
|
+
originationChainId: Chains;
|
|
25
|
+
assetInAddress: Hex;
|
|
26
|
+
assetOutAddress: Hex | null;
|
|
13
27
|
toForeign?: {
|
|
14
|
-
home: Hex
|
|
15
|
-
foreign: Hex | null
|
|
16
|
-
}
|
|
28
|
+
home: Hex;
|
|
29
|
+
foreign: Hex | null;
|
|
30
|
+
};
|
|
17
31
|
toHome?: {
|
|
18
|
-
home: Hex | null
|
|
19
|
-
foreign: Hex
|
|
20
|
-
}
|
|
21
|
-
}
|
|
32
|
+
home: Hex | null;
|
|
33
|
+
foreign: Hex;
|
|
34
|
+
};
|
|
35
|
+
};
|
|
22
36
|
|
|
23
37
|
/**
|
|
24
38
|
* Returns the bridged token address and native token address
|
|
@@ -29,7 +43,17 @@ export type TokenBridgeInfo = {
|
|
|
29
43
|
* @returns the bridged token address and native token address
|
|
30
44
|
*/
|
|
31
45
|
export const links = _.memoize(
|
|
32
|
-
async ({
|
|
46
|
+
async ({
|
|
47
|
+
chainId,
|
|
48
|
+
target,
|
|
49
|
+
address,
|
|
50
|
+
client,
|
|
51
|
+
}: {
|
|
52
|
+
chainId: number;
|
|
53
|
+
target: Hex;
|
|
54
|
+
address: Hex;
|
|
55
|
+
client: PublicClient;
|
|
56
|
+
}) => {
|
|
33
57
|
return multicallRead<[Hex, Hex]>({
|
|
34
58
|
client,
|
|
35
59
|
chain: chainsMetadata[toChain(chainId)],
|
|
@@ -39,10 +63,10 @@ export const links = _.memoize(
|
|
|
39
63
|
{ functionName: 'bridgedTokenAddress', args: [address] },
|
|
40
64
|
{ functionName: 'nativeTokenAddress', args: [address] },
|
|
41
65
|
],
|
|
42
|
-
})
|
|
66
|
+
});
|
|
43
67
|
},
|
|
44
68
|
({ chainId, target, address }) => `${chainId}-${target}-${address}`.toLowerCase(),
|
|
45
|
-
)
|
|
69
|
+
);
|
|
46
70
|
|
|
47
71
|
/**
|
|
48
72
|
* Returns the token bridge info for the given bridge key, asset in, is prod, from chain client, and to chain client
|
|
@@ -60,20 +84,20 @@ export const tokenBridgeInfo = async ({
|
|
|
60
84
|
fromChainClient,
|
|
61
85
|
toChainClient,
|
|
62
86
|
}: {
|
|
63
|
-
bridgeKey: BridgeKey
|
|
64
|
-
assetIn: Token | null
|
|
65
|
-
isProd: boolean
|
|
66
|
-
fromChainClient: PublicClient
|
|
67
|
-
toChainClient: PublicClient
|
|
87
|
+
bridgeKey: BridgeKey;
|
|
88
|
+
assetIn: Token | null;
|
|
89
|
+
isProd: boolean;
|
|
90
|
+
fromChainClient: PublicClient;
|
|
91
|
+
toChainClient: PublicClient;
|
|
68
92
|
}): Promise<null | TokenBridgeInfo> => {
|
|
69
|
-
const bridgePathway = pathway(bridgeKey, isProd, assetIn?.address as Hex | null)
|
|
93
|
+
const bridgePathway = pathway(bridgeKey, isProd, assetIn?.address as Hex | null);
|
|
70
94
|
if (!assetIn || !bridgePathway) {
|
|
71
|
-
console.log('missing asset in or bridge pathway')
|
|
72
|
-
return null
|
|
95
|
+
console.log('missing asset in or bridge pathway');
|
|
96
|
+
return null;
|
|
73
97
|
}
|
|
74
|
-
const [, fromChain, toChain] = bridgeKey
|
|
98
|
+
const [, fromChain, toChain] = bridgeKey;
|
|
75
99
|
const assetInAddress =
|
|
76
|
-
assetIn.address === zeroAddress ? nativeAssetOut[fromChain] : assetIn.address
|
|
100
|
+
assetIn.address === zeroAddress ? nativeAssetOut[fromChain] : assetIn.address;
|
|
77
101
|
const [toMappings, fromMappings] = await Promise.all([
|
|
78
102
|
links({
|
|
79
103
|
chainId: Number(toChain),
|
|
@@ -87,8 +111,8 @@ export const tokenBridgeInfo = async ({
|
|
|
87
111
|
address: assetInAddress as Hex,
|
|
88
112
|
client: fromChainClient,
|
|
89
113
|
}),
|
|
90
|
-
])
|
|
91
|
-
const [toBridged, toNative] = toMappings
|
|
114
|
+
]);
|
|
115
|
+
const [toBridged, toNative] = toMappings;
|
|
92
116
|
if (toBridged !== zeroAddress) {
|
|
93
117
|
return {
|
|
94
118
|
originationChainId: fromChain,
|
|
@@ -98,7 +122,7 @@ export const tokenBridgeInfo = async ({
|
|
|
98
122
|
home: toBridged,
|
|
99
123
|
foreign: assetInAddress as Hex,
|
|
100
124
|
},
|
|
101
|
-
}
|
|
125
|
+
};
|
|
102
126
|
}
|
|
103
127
|
if (toNative !== zeroAddress) {
|
|
104
128
|
return {
|
|
@@ -109,9 +133,9 @@ export const tokenBridgeInfo = async ({
|
|
|
109
133
|
home: toNative,
|
|
110
134
|
foreign: assetInAddress as Hex,
|
|
111
135
|
},
|
|
112
|
-
}
|
|
136
|
+
};
|
|
113
137
|
}
|
|
114
|
-
const [fromBridged, fromNative] = fromMappings
|
|
138
|
+
const [fromBridged, fromNative] = fromMappings;
|
|
115
139
|
if (fromNative !== zeroAddress) {
|
|
116
140
|
return {
|
|
117
141
|
originationChainId: toChain,
|
|
@@ -121,7 +145,7 @@ export const tokenBridgeInfo = async ({
|
|
|
121
145
|
home: assetInAddress as Hex,
|
|
122
146
|
foreign: fromNative,
|
|
123
147
|
},
|
|
124
|
-
}
|
|
148
|
+
};
|
|
125
149
|
}
|
|
126
150
|
if (fromBridged !== zeroAddress) {
|
|
127
151
|
return {
|
|
@@ -132,7 +156,7 @@ export const tokenBridgeInfo = async ({
|
|
|
132
156
|
foreign: fromBridged,
|
|
133
157
|
home: assetInAddress as Hex,
|
|
134
158
|
},
|
|
135
|
-
}
|
|
159
|
+
};
|
|
136
160
|
}
|
|
137
161
|
// the token has not been bridged yet
|
|
138
162
|
return {
|
|
@@ -141,21 +165,21 @@ export const tokenBridgeInfo = async ({
|
|
|
141
165
|
assetOutAddress: null,
|
|
142
166
|
...(bridgePathway.toHome
|
|
143
167
|
? {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
168
|
+
toHome: {
|
|
169
|
+
foreign: assetInAddress as Hex,
|
|
170
|
+
home: null,
|
|
171
|
+
},
|
|
172
|
+
}
|
|
149
173
|
: {
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
}
|
|
156
|
-
}
|
|
174
|
+
toForeign: {
|
|
175
|
+
foreign: null,
|
|
176
|
+
home: assetInAddress as Hex,
|
|
177
|
+
},
|
|
178
|
+
}),
|
|
179
|
+
};
|
|
180
|
+
};
|
|
157
181
|
/** The result of reading the amount out from a router */
|
|
158
|
-
export type FetchResult = bigint[] | Hex
|
|
182
|
+
export type FetchResult = bigint[] | Hex;
|
|
159
183
|
/**
|
|
160
184
|
* Check the prices that each router offers for the given paths
|
|
161
185
|
* @param assetInAddress the address of the asset going into the bridge
|
|
@@ -173,11 +197,11 @@ const readAmountOut = ({
|
|
|
173
197
|
client,
|
|
174
198
|
uniV2Router,
|
|
175
199
|
}: {
|
|
176
|
-
amountIn: bigint
|
|
177
|
-
chain: Chains
|
|
178
|
-
paths: Hex[][]
|
|
179
|
-
client: PublicClient
|
|
180
|
-
uniV2Router?: Hex
|
|
200
|
+
amountIn: bigint;
|
|
201
|
+
chain: Chains;
|
|
202
|
+
paths: Hex[][];
|
|
203
|
+
client: PublicClient;
|
|
204
|
+
uniV2Router?: Hex;
|
|
181
205
|
}): Promise<FetchResult[]> => {
|
|
182
206
|
return multicallRead<FetchResult[]>({
|
|
183
207
|
chain: chainsMetadata[chain],
|
|
@@ -192,8 +216,8 @@ const readAmountOut = ({
|
|
|
192
216
|
target,
|
|
193
217
|
})),
|
|
194
218
|
),
|
|
195
|
-
})
|
|
196
|
-
}
|
|
219
|
+
});
|
|
220
|
+
};
|
|
197
221
|
|
|
198
222
|
/**
|
|
199
223
|
* Fetch the price corrective for the given bridge key, asset out, measurement token, from chain client, to chain client, asset link, amount in, and is prod
|
|
@@ -217,15 +241,15 @@ export const fetchPriceCorrective = ({
|
|
|
217
241
|
amountIn,
|
|
218
242
|
isProd,
|
|
219
243
|
}: {
|
|
220
|
-
bridgeKey: BridgeKey
|
|
221
|
-
bridgeKeyPartner: BridgeKey
|
|
222
|
-
measurementToken: Hex
|
|
223
|
-
assetOut: Token
|
|
224
|
-
fromChainClient: PublicClient
|
|
225
|
-
toChainClient: PublicClient
|
|
226
|
-
assetLink: TokenBridgeInfo
|
|
227
|
-
amountIn: bigint
|
|
228
|
-
isProd: boolean
|
|
244
|
+
bridgeKey: BridgeKey;
|
|
245
|
+
bridgeKeyPartner: BridgeKey;
|
|
246
|
+
measurementToken: Hex;
|
|
247
|
+
assetOut: Token;
|
|
248
|
+
fromChainClient: PublicClient;
|
|
249
|
+
toChainClient: PublicClient;
|
|
250
|
+
assetLink: TokenBridgeInfo;
|
|
251
|
+
amountIn: bigint;
|
|
252
|
+
isProd: boolean;
|
|
229
253
|
}) => {
|
|
230
254
|
return {
|
|
231
255
|
getPaymentToken: async () => {
|
|
@@ -241,7 +265,7 @@ export const fetchPriceCorrective = ({
|
|
|
241
265
|
// tokens going the opposite direction to the provided bridge key
|
|
242
266
|
fromChainClient: toChainClient,
|
|
243
267
|
toChainClient: fromChainClient,
|
|
244
|
-
})
|
|
268
|
+
});
|
|
245
269
|
},
|
|
246
270
|
getSwapResults: async ({
|
|
247
271
|
paymentTokenResult,
|
|
@@ -249,10 +273,10 @@ export const fetchPriceCorrective = ({
|
|
|
249
273
|
uniV2Router,
|
|
250
274
|
client,
|
|
251
275
|
}: {
|
|
252
|
-
paymentTokenResult: TokenBridgeInfo
|
|
253
|
-
chain: Chains
|
|
254
|
-
client: PublicClient
|
|
255
|
-
uniV2Router?: Hex
|
|
276
|
+
paymentTokenResult: TokenBridgeInfo;
|
|
277
|
+
chain: Chains;
|
|
278
|
+
client: PublicClient;
|
|
279
|
+
uniV2Router?: Hex;
|
|
256
280
|
}) => {
|
|
257
281
|
return await Promise.all([
|
|
258
282
|
readAmountOut({
|
|
@@ -276,47 +300,47 @@ export const fetchPriceCorrective = ({
|
|
|
276
300
|
// only the direct route is available.
|
|
277
301
|
// might be able to create a whitelist for this at some point
|
|
278
302
|
}),
|
|
279
|
-
])
|
|
303
|
+
]);
|
|
280
304
|
},
|
|
281
305
|
reduceResults: ({
|
|
282
306
|
results,
|
|
283
307
|
oneToken,
|
|
284
308
|
}: {
|
|
285
|
-
results: [FetchResult[], ...[FetchResult[]]]
|
|
286
|
-
oneToken: bigint
|
|
309
|
+
results: [FetchResult[], ...[FetchResult[]]];
|
|
310
|
+
oneToken: bigint;
|
|
287
311
|
}) => {
|
|
288
312
|
const outputFromRouter = (result: FetchResult) => {
|
|
289
313
|
if (_.isString(result)) {
|
|
290
314
|
// the router failed to return a result
|
|
291
|
-
return 0n
|
|
315
|
+
return 0n;
|
|
292
316
|
}
|
|
293
317
|
if (!result.length) {
|
|
294
318
|
// the router returned an empty result
|
|
295
|
-
return 0n
|
|
319
|
+
return 0n;
|
|
296
320
|
}
|
|
297
321
|
// the last element is the amount of the output token
|
|
298
|
-
const last = result[result.length - 1]
|
|
299
|
-
return (last * oneToken) / amountIn
|
|
300
|
-
}
|
|
322
|
+
const last = result[result.length - 1]!;
|
|
323
|
+
return (last * oneToken) / amountIn;
|
|
324
|
+
};
|
|
301
325
|
const max = (amountsOut: (bigint | undefined)[]) => {
|
|
302
|
-
return _.compact(amountsOut).reduce((max, current) => (max < current ? current : max), 0n)
|
|
303
|
-
}
|
|
326
|
+
return _.compact(amountsOut).reduce((max, current) => (max < current ? current : max), 0n);
|
|
327
|
+
};
|
|
304
328
|
// could do with a refactor to unify the results
|
|
305
|
-
const [outputs, inputs] = results
|
|
306
|
-
const outputAmounts = outputs.map(outputFromRouter)
|
|
307
|
-
const inputAmounts = inputs.map(outputFromRouter)
|
|
308
|
-
const outputToken = max(outputAmounts)
|
|
309
|
-
const inputToken = max(inputAmounts)
|
|
329
|
+
const [outputs, inputs] = results;
|
|
330
|
+
const outputAmounts = outputs.map(outputFromRouter);
|
|
331
|
+
const inputAmounts = inputs.map(outputFromRouter);
|
|
332
|
+
const outputToken = max(outputAmounts);
|
|
333
|
+
const inputToken = max(inputAmounts);
|
|
310
334
|
const result =
|
|
311
335
|
outputToken && outputToken > 0n
|
|
312
336
|
? inputToken && inputToken > outputToken && inputToken / outputToken === 1n
|
|
313
337
|
? inputToken
|
|
314
338
|
: outputToken
|
|
315
|
-
: inputToken
|
|
316
|
-
return result
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
}
|
|
339
|
+
: inputToken;
|
|
340
|
+
return result;
|
|
341
|
+
},
|
|
342
|
+
};
|
|
343
|
+
};
|
|
320
344
|
|
|
321
345
|
/**
|
|
322
346
|
* Fetch the minimum bridge amount in for the given asset in, pathway, from public client, and to public client
|
|
@@ -332,51 +356,58 @@ export const minBridgeAmountIn = async ({
|
|
|
332
356
|
fromPublicClient,
|
|
333
357
|
toPublicClient,
|
|
334
358
|
}: {
|
|
335
|
-
assetIn: Token
|
|
336
|
-
pathway: Pathway
|
|
337
|
-
fromPublicClient: PublicClient
|
|
338
|
-
toPublicClient: PublicClient
|
|
359
|
+
assetIn: Token;
|
|
360
|
+
pathway: Pathway;
|
|
361
|
+
fromPublicClient: PublicClient;
|
|
362
|
+
toPublicClient: PublicClient;
|
|
339
363
|
}) => {
|
|
340
|
-
const publicClient = pathway?.feeManager === 'from' ? fromPublicClient : toPublicClient
|
|
364
|
+
const publicClient = pathway?.feeManager === 'from' ? fromPublicClient : toPublicClient;
|
|
341
365
|
return publicClient.readContract({
|
|
342
366
|
abi: abis.inputBridge,
|
|
343
367
|
functionName: 'minPerTx',
|
|
344
368
|
args: [assetIn.address as Hex],
|
|
345
369
|
address: pathway[pathway.feeManager],
|
|
346
|
-
})
|
|
347
|
-
}
|
|
370
|
+
});
|
|
371
|
+
};
|
|
348
372
|
/** get the symbol of the native asset, unwrap it if it needs to be */
|
|
349
|
-
export const nativeSymbol = (
|
|
350
|
-
|
|
351
|
-
|
|
373
|
+
export const nativeSymbol = (
|
|
374
|
+
asset: { address: string; symbol: string; chainId: number } | null,
|
|
375
|
+
unwrap = false,
|
|
376
|
+
) => {
|
|
377
|
+
return asset
|
|
378
|
+
? unwrap && asset.address === nativeAssetOut[toChain(asset.chainId)]
|
|
379
|
+
? asset.symbol.slice(1)
|
|
380
|
+
: asset.symbol
|
|
381
|
+
: '';
|
|
382
|
+
};
|
|
352
383
|
|
|
353
384
|
/** The input for loading the bridge fees */
|
|
354
385
|
export type InputLoadFeeFor = {
|
|
355
|
-
pathway: Pathway
|
|
356
|
-
fromChainClient: PublicClient
|
|
357
|
-
toChainClient: PublicClient
|
|
358
|
-
}
|
|
386
|
+
pathway: Pathway;
|
|
387
|
+
fromChainClient: PublicClient;
|
|
388
|
+
toChainClient: PublicClient;
|
|
389
|
+
};
|
|
359
390
|
|
|
360
391
|
/** The fee configuration for a given pathway */
|
|
361
392
|
export type PathwayExtendableConfig = {
|
|
362
|
-
feeManager: Hex
|
|
363
|
-
feeH2F: bigint
|
|
364
|
-
feeF2H: bigint
|
|
365
|
-
}
|
|
393
|
+
feeManager: Hex;
|
|
394
|
+
feeH2F: bigint;
|
|
395
|
+
feeF2H: bigint;
|
|
396
|
+
};
|
|
366
397
|
/**
|
|
367
398
|
* Returns the chain multicall for the given client
|
|
368
399
|
* @param client - the client
|
|
369
400
|
* @returns the chain multicall
|
|
370
401
|
*/
|
|
371
402
|
export const chainMulticall = (client: PublicClient) => {
|
|
372
|
-
const chainId = client.chain!.id
|
|
373
|
-
const metadata = chainsMetadata[toChain(chainId)]
|
|
403
|
+
const chainId = client.chain!.id;
|
|
404
|
+
const metadata = chainsMetadata[toChain(chainId)];
|
|
374
405
|
return getContract({
|
|
375
406
|
abi: multicall3Abi,
|
|
376
407
|
client: client as any,
|
|
377
408
|
address: metadata.contracts!.multicall3!.address,
|
|
378
|
-
}) as any
|
|
379
|
-
}
|
|
409
|
+
}) as any;
|
|
410
|
+
};
|
|
380
411
|
/**
|
|
381
412
|
* Load the bridge fees for the given pathway, from chain client, and to chain client
|
|
382
413
|
* @param pathway - the pathway
|
|
@@ -384,10 +415,13 @@ export const chainMulticall = (client: PublicClient) => {
|
|
|
384
415
|
* @param toChainClient - the to chain client
|
|
385
416
|
* @returns the bridge fees
|
|
386
417
|
*/
|
|
387
|
-
export const loadBridgeFees = async ({
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
418
|
+
export const loadBridgeFees = async ({
|
|
419
|
+
pathway,
|
|
420
|
+
fromChainClient,
|
|
421
|
+
toChainClient,
|
|
422
|
+
}: InputLoadFeeFor) => {
|
|
423
|
+
const multicall =
|
|
424
|
+
pathway.feeManager === 'from' ? chainMulticall(fromChainClient) : chainMulticall(toChainClient);
|
|
391
425
|
|
|
392
426
|
const [feeManagerResponse] = await multicall.read.aggregate3([
|
|
393
427
|
[
|
|
@@ -400,19 +434,19 @@ export const loadBridgeFees = async ({ pathway, fromChainClient, toChainClient }
|
|
|
400
434
|
}),
|
|
401
435
|
},
|
|
402
436
|
],
|
|
403
|
-
])
|
|
404
|
-
const { success, returnData } = feeManagerResponse
|
|
437
|
+
]);
|
|
438
|
+
const { success, returnData } = feeManagerResponse;
|
|
405
439
|
if (!success) {
|
|
406
|
-
throw new Error('unable to load feeManager')
|
|
440
|
+
throw new Error('unable to load feeManager');
|
|
407
441
|
}
|
|
408
442
|
if (returnData === '0x') {
|
|
409
|
-
throw new Error('unable to read feeManager')
|
|
443
|
+
throw new Error('unable to read feeManager');
|
|
410
444
|
}
|
|
411
445
|
const feeManager = (
|
|
412
446
|
returnData.startsWith('0x000000000000000000000000')
|
|
413
447
|
? `0x${returnData.slice(26)}`
|
|
414
448
|
: `0x${returnData.slice(-40)}`
|
|
415
|
-
) as Hex
|
|
449
|
+
) as Hex;
|
|
416
450
|
const [keyH2F, keyF2H] = await multicall.read.aggregate3([
|
|
417
451
|
[
|
|
418
452
|
{
|
|
@@ -432,7 +466,7 @@ export const loadBridgeFees = async ({ pathway, fromChainClient, toChainClient }
|
|
|
432
466
|
}),
|
|
433
467
|
},
|
|
434
468
|
],
|
|
435
|
-
])
|
|
469
|
+
]);
|
|
436
470
|
const [feeH2F, feeF2H] = await multicall.read.aggregate3([
|
|
437
471
|
[
|
|
438
472
|
{
|
|
@@ -454,11 +488,11 @@ export const loadBridgeFees = async ({ pathway, fromChainClient, toChainClient }
|
|
|
454
488
|
}),
|
|
455
489
|
},
|
|
456
490
|
],
|
|
457
|
-
])
|
|
491
|
+
]);
|
|
458
492
|
const setting = {
|
|
459
493
|
feeManager,
|
|
460
494
|
feeH2F: BigInt(feeH2F.returnData),
|
|
461
495
|
feeF2H: BigInt(feeF2H.returnData),
|
|
462
|
-
} as PathwayExtendableConfig
|
|
463
|
-
return setting
|
|
464
|
-
}
|
|
496
|
+
} as PathwayExtendableConfig;
|
|
497
|
+
return setting;
|
|
498
|
+
};
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { chainsMetadata } from './chains';
|
|
3
|
+
import { Chains } from './config';
|
|
4
|
+
|
|
5
|
+
describe('chains', () => {
|
|
6
|
+
describe('chainsMetadata', () => {
|
|
7
|
+
it('should have metadata for all main chains', () => {
|
|
8
|
+
expect(chainsMetadata[Chains.PLS]).toBeDefined();
|
|
9
|
+
expect(chainsMetadata[Chains.ETH]).toBeDefined();
|
|
10
|
+
expect(chainsMetadata[Chains.BNB]).toBeDefined();
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it('should have metadata for testnet chains', () => {
|
|
14
|
+
expect(chainsMetadata[Chains.SEP]).toBeDefined();
|
|
15
|
+
expect(chainsMetadata[Chains.V4PLS]).toBeDefined();
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it('should have required fields for each chain', () => {
|
|
19
|
+
Object.entries(chainsMetadata).forEach(([chainKey, metadata]) => {
|
|
20
|
+
expect(metadata).toHaveProperty('chainId');
|
|
21
|
+
expect(metadata).toHaveProperty('name');
|
|
22
|
+
expect(metadata).toHaveProperty('logoURI');
|
|
23
|
+
expect(metadata).toHaveProperty('alt');
|
|
24
|
+
expect(metadata).toHaveProperty('rpcUrls');
|
|
25
|
+
expect(metadata.rpcUrls).toHaveProperty('default');
|
|
26
|
+
expect(metadata.rpcUrls.default).toHaveProperty('http');
|
|
27
|
+
expect(Array.isArray(metadata.rpcUrls.default.http)).toBe(true);
|
|
28
|
+
expect(metadata.rpcUrls.default.http.length).toBeGreaterThan(0);
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('should have valid RPC URLs for each chain', () => {
|
|
33
|
+
Object.values(chainsMetadata).forEach((metadata) => {
|
|
34
|
+
metadata.rpcUrls.default.http.forEach((url) => {
|
|
35
|
+
expect(url).toMatch(/^https?:\/\//);
|
|
36
|
+
expect(url).not.toContain(' ');
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('should have valid logoURIs', () => {
|
|
42
|
+
Object.values(chainsMetadata).forEach((metadata) => {
|
|
43
|
+
expect(metadata.logoURI).toMatch(/^https?:\/\//);
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('should have alt text for accessibility', () => {
|
|
48
|
+
Object.values(chainsMetadata).forEach((metadata) => {
|
|
49
|
+
expect(typeof metadata.alt).toBe('string');
|
|
50
|
+
expect(metadata.alt.length).toBeGreaterThan(0);
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it('should have matching chainId in metadata', () => {
|
|
55
|
+
Object.entries(chainsMetadata).forEach(([chainKey, metadata]) => {
|
|
56
|
+
expect(metadata.chainId).toBe(chainKey);
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('should have ENS contracts for Pulsechain chains', () => {
|
|
61
|
+
// Mainnet PLS should have ENS
|
|
62
|
+
expect(chainsMetadata[Chains.PLS].contracts?.ensRegistry).toBeDefined();
|
|
63
|
+
expect(chainsMetadata[Chains.PLS].contracts?.ensUniversalResolver).toBeDefined();
|
|
64
|
+
expect(chainsMetadata[Chains.PLS].contracts?.ensRegistry?.address).toMatch(
|
|
65
|
+
/^0x[a-fA-F0-9]{40}$/,
|
|
66
|
+
);
|
|
67
|
+
expect(chainsMetadata[Chains.PLS].contracts?.ensUniversalResolver?.address).toMatch(
|
|
68
|
+
/^0x[a-fA-F0-9]{40}$/,
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
// Testnet V4PLS should have ENS
|
|
72
|
+
expect(chainsMetadata[Chains.V4PLS].contracts?.ensRegistry).toBeDefined();
|
|
73
|
+
expect(chainsMetadata[Chains.V4PLS].contracts?.ensUniversalResolver).toBeDefined();
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it('should have multicall3 contracts for all chains', () => {
|
|
77
|
+
Object.values(chainsMetadata).forEach((metadata) => {
|
|
78
|
+
expect(metadata.contracts?.multicall3).toBeDefined();
|
|
79
|
+
expect(metadata.contracts?.multicall3?.address).toMatch(/^0x[a-fA-F0-9]{40}$/);
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it('should have unique RPC URLs per chain', () => {
|
|
84
|
+
const rpcUrls = Object.values(chainsMetadata).map((m) => m.rpcUrls.default.http[0]);
|
|
85
|
+
const uniqueUrls = new Set(rpcUrls);
|
|
86
|
+
expect(uniqueUrls.size).toBe(rpcUrls.length);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
describe('specific chain validation', () => {
|
|
90
|
+
it('should have correct Pulsechain mainnet config', () => {
|
|
91
|
+
const pls = chainsMetadata[Chains.PLS];
|
|
92
|
+
expect(pls.name).toContain('Pulse');
|
|
93
|
+
expect(pls.chainId).toBe(Chains.PLS);
|
|
94
|
+
expect(pls.rpcUrls.default.http[0]).toContain('pulsechain');
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it('should have correct Ethereum mainnet config', () => {
|
|
98
|
+
const eth = chainsMetadata[Chains.ETH];
|
|
99
|
+
expect(eth.name).toContain('Ethereum');
|
|
100
|
+
expect(eth.chainId).toBe(Chains.ETH);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it('should have correct BSC config', () => {
|
|
104
|
+
const bnb = chainsMetadata[Chains.BNB];
|
|
105
|
+
expect(bnb.name).toContain('Binance');
|
|
106
|
+
expect(bnb.chainId).toBe(Chains.BNB);
|
|
107
|
+
expect(bnb.rpcUrls.default.http[0]).toContain('bsc');
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it('should have correct Sepolia testnet config', () => {
|
|
111
|
+
const sep = chainsMetadata[Chains.SEP];
|
|
112
|
+
expect(sep.name).toBe('Sepolia');
|
|
113
|
+
expect(sep.chainId).toBe(Chains.SEP);
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it('should have correct Pulsechain V4 testnet config', () => {
|
|
117
|
+
const v4pls = chainsMetadata[Chains.V4PLS];
|
|
118
|
+
expect(v4pls.name).toContain('Pulsechain V4');
|
|
119
|
+
expect(v4pls.chainId).toBe(Chains.V4PLS);
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
});
|
package/src/chains.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
3
|
-
import type { ChainsMetadata } from '@gibs/bridge-sdk/types'
|
|
4
|
-
import
|
|
1
|
+
import { Chains } from '@gibs/bridge-sdk/config';
|
|
2
|
+
import * as imageLinks from '@gibs/bridge-sdk/image-links';
|
|
3
|
+
import type { ChainsMetadata } from '@gibs/bridge-sdk/types';
|
|
4
|
+
import { bsc, mainnet, pulsechain, pulsechainV4, sepolia } from '@reown/appkit/networks';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* all of the chains that are enabled in this dapp
|
|
@@ -85,4 +85,4 @@ export const chainsMetadata = {
|
|
|
85
85
|
},
|
|
86
86
|
},
|
|
87
87
|
},
|
|
88
|
-
} as ChainsMetadata
|
|
88
|
+
} as ChainsMetadata;
|