@hyperbridge/sdk 1.2.2 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser/index.d.ts +591 -8
- package/dist/browser/index.js +2039 -2007
- package/dist/browser/index.js.map +1 -1
- package/dist/node/index.d.ts +591 -8
- package/dist/node/index.js +2039 -2007
- package/dist/node/index.js.map +1 -1
- package/package.json +2 -2
package/dist/node/index.js
CHANGED
|
@@ -3,15 +3,15 @@ import { join } from 'path';
|
|
|
3
3
|
import { TextDecoder as TextDecoder$1, TextEncoder as TextEncoder$1 } from 'util';
|
|
4
4
|
import { createConsola, LogLevels } from 'consola';
|
|
5
5
|
import { flatten, zip, capitalize, maxBy, isNil } from 'lodash-es';
|
|
6
|
-
import {
|
|
6
|
+
import { hexToBytes, encodePacked, toHex, keccak256, encodeAbiParameters, bytesToHex, concatHex, createPublicClient, http, encodeFunctionData, erc20Abi, bytesToBigInt, pad, toBytes, maxUint256, parseUnits } from 'viem';
|
|
7
7
|
import mergeRace from '@async-generator/merge-race';
|
|
8
|
+
import { hasWindow, isNode, env } from 'std-env';
|
|
9
|
+
import { Vector, u8, Struct, Tuple, Enum, _void, u64, u32, Option, bool, u128 } from 'scale-ts';
|
|
8
10
|
import { gnosisChiado, gnosis, bscTestnet, bsc, soneium, baseSepolia, base, optimismSepolia, optimism, arbitrumSepolia, arbitrum, mainnet, sepolia } from 'viem/chains';
|
|
9
11
|
import { match } from 'ts-pattern';
|
|
10
12
|
import { WsProvider, ApiPromise } from '@polkadot/api';
|
|
11
13
|
import { RpcWebSocketClient } from 'rpc-websocket-client';
|
|
12
|
-
import { Vector, u8, Struct, Tuple, Enum, _void, u64, u32, Option, bool, u128 } from 'scale-ts';
|
|
13
14
|
import { keccakAsU8a, decodeAddress, xxhashAsU8a } from '@polkadot/util-crypto';
|
|
14
|
-
import { hasWindow, isNode, env } from 'std-env';
|
|
15
15
|
import { GraphQLClient } from 'graphql-request';
|
|
16
16
|
import { u8aToHex } from '@polkadot/util';
|
|
17
17
|
|
|
@@ -230,234 +230,6 @@ var init_node = __esm({
|
|
|
230
230
|
}
|
|
231
231
|
});
|
|
232
232
|
|
|
233
|
-
// src/queries.ts
|
|
234
|
-
var POST_REQUEST_STATUS = `
|
|
235
|
-
query RequestStatusM($hash: String!) {
|
|
236
|
-
requests(
|
|
237
|
-
filter: { commitment: { equalTo: $hash } }
|
|
238
|
-
) {
|
|
239
|
-
nodes {
|
|
240
|
-
commitment
|
|
241
|
-
timeoutTimestamp
|
|
242
|
-
source
|
|
243
|
-
dest
|
|
244
|
-
to
|
|
245
|
-
from
|
|
246
|
-
nonce
|
|
247
|
-
body
|
|
248
|
-
statusMetadata {
|
|
249
|
-
nodes {
|
|
250
|
-
blockHash
|
|
251
|
-
blockNumber
|
|
252
|
-
timestamp
|
|
253
|
-
chain
|
|
254
|
-
status
|
|
255
|
-
transactionHash
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
`;
|
|
262
|
-
var GET_REQUEST_STATUS = `
|
|
263
|
-
query GetRequestDetails($commitment: String!) {
|
|
264
|
-
getRequests(
|
|
265
|
-
filter: { commitment: { equalTo: $commitment } }
|
|
266
|
-
) {
|
|
267
|
-
nodes {
|
|
268
|
-
id
|
|
269
|
-
source
|
|
270
|
-
dest
|
|
271
|
-
from
|
|
272
|
-
keys
|
|
273
|
-
nonce
|
|
274
|
-
height
|
|
275
|
-
context
|
|
276
|
-
timeoutTimestamp
|
|
277
|
-
fee
|
|
278
|
-
blockNumber
|
|
279
|
-
blockHash
|
|
280
|
-
transactionHash
|
|
281
|
-
blockTimestamp
|
|
282
|
-
status
|
|
283
|
-
chain
|
|
284
|
-
commitment
|
|
285
|
-
statusMetadata {
|
|
286
|
-
nodes {
|
|
287
|
-
status
|
|
288
|
-
chain
|
|
289
|
-
timestamp
|
|
290
|
-
blockNumber
|
|
291
|
-
blockHash
|
|
292
|
-
transactionHash
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
}`;
|
|
298
|
-
var STATE_MACHINE_UPDATES_BY_HEIGHT = `
|
|
299
|
-
query StateMachineUpdatesByHeight($statemachineId: String!, $height: Int!, $chain: String!) {
|
|
300
|
-
stateMachineUpdateEvents(
|
|
301
|
-
filter: {
|
|
302
|
-
and: [
|
|
303
|
-
{ stateMachineId: { equalTo: $statemachineId } }
|
|
304
|
-
{ height: { greaterThanOrEqualTo: $height } }
|
|
305
|
-
{ chain: { equalTo: $chain } }
|
|
306
|
-
]
|
|
307
|
-
}
|
|
308
|
-
orderBy: HEIGHT_ASC
|
|
309
|
-
first: 1
|
|
310
|
-
) {
|
|
311
|
-
nodes {
|
|
312
|
-
height
|
|
313
|
-
stateMachineId
|
|
314
|
-
chain
|
|
315
|
-
blockHash
|
|
316
|
-
blockNumber
|
|
317
|
-
transactionHash
|
|
318
|
-
createdAt
|
|
319
|
-
}
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
`;
|
|
323
|
-
var STATE_MACHINE_UPDATES_BY_TIMESTAMP = `
|
|
324
|
-
query StateMachineUpdatesByTimestamp($statemachineId: String!, $commitmentTimestamp: BigFloat!, $chain: String!) {
|
|
325
|
-
stateMachineUpdateEvents(
|
|
326
|
-
filter: {
|
|
327
|
-
and: [
|
|
328
|
-
{ stateMachineId: { equalTo: $statemachineId } }
|
|
329
|
-
{ commitmentTimestamp: { greaterThanOrEqualTo: $commitmentTimestamp } }
|
|
330
|
-
{ chain: { equalTo: $chain } }
|
|
331
|
-
]
|
|
332
|
-
}
|
|
333
|
-
orderBy: COMMITMENT_TIMESTAMP_DESC
|
|
334
|
-
first: 1
|
|
335
|
-
) {
|
|
336
|
-
nodes {
|
|
337
|
-
height
|
|
338
|
-
stateMachineId
|
|
339
|
-
chain
|
|
340
|
-
blockHash
|
|
341
|
-
blockNumber
|
|
342
|
-
transactionHash
|
|
343
|
-
commitmentTimestamp
|
|
344
|
-
createdAt
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
`;
|
|
349
|
-
var ASSET_TELEPORTED_BY_PARAMS = `
|
|
350
|
-
query AssetTeleportedByParams($from: String!, $to: String!, $dest: String!, $blockNumber: Int!) {
|
|
351
|
-
assetTeleporteds(
|
|
352
|
-
filter: {
|
|
353
|
-
and: [
|
|
354
|
-
{ from: { equalTo: $from } }
|
|
355
|
-
{ to: { equalTo: $to } }
|
|
356
|
-
{ dest: { includes: $dest } }
|
|
357
|
-
{ blockNumber: { greaterThanOrEqualTo: $blockNumber } }
|
|
358
|
-
]
|
|
359
|
-
}
|
|
360
|
-
orderBy: CREATED_AT_DESC
|
|
361
|
-
first: 1
|
|
362
|
-
) {
|
|
363
|
-
nodes {
|
|
364
|
-
id
|
|
365
|
-
from
|
|
366
|
-
to
|
|
367
|
-
amount
|
|
368
|
-
dest
|
|
369
|
-
commitment
|
|
370
|
-
createdAt
|
|
371
|
-
blockNumber
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
`;
|
|
376
|
-
var GET_RESPONSE_BY_REQUEST_ID = `
|
|
377
|
-
query GetResponseByRequestId($requestId: String!) {
|
|
378
|
-
getResponses(filter: {requestId: {equalTo: $requestId}}) {
|
|
379
|
-
nodes {
|
|
380
|
-
id
|
|
381
|
-
commitment
|
|
382
|
-
responseMessage
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
`;
|
|
387
|
-
var ORDER_STATUS = `
|
|
388
|
-
query OrderStatus($commitment: String!) {
|
|
389
|
-
orderPlaceds(
|
|
390
|
-
filter: { commitment: { equalTo: $commitment } }
|
|
391
|
-
) {
|
|
392
|
-
nodes {
|
|
393
|
-
id
|
|
394
|
-
user
|
|
395
|
-
sourceChain
|
|
396
|
-
destChain
|
|
397
|
-
commitment
|
|
398
|
-
deadline
|
|
399
|
-
nonce
|
|
400
|
-
fees
|
|
401
|
-
inputTokens
|
|
402
|
-
inputAmounts
|
|
403
|
-
inputValuesUSD
|
|
404
|
-
inputUSD
|
|
405
|
-
outputTokens
|
|
406
|
-
outputAmounts
|
|
407
|
-
outputBeneficiaries
|
|
408
|
-
calldata
|
|
409
|
-
status
|
|
410
|
-
createdAt
|
|
411
|
-
blockNumber
|
|
412
|
-
blockTimestamp
|
|
413
|
-
transactionHash
|
|
414
|
-
statusMetadata {
|
|
415
|
-
nodes {
|
|
416
|
-
status
|
|
417
|
-
chain
|
|
418
|
-
timestamp
|
|
419
|
-
blockNumber
|
|
420
|
-
transactionHash
|
|
421
|
-
filler
|
|
422
|
-
}
|
|
423
|
-
}
|
|
424
|
-
}
|
|
425
|
-
}
|
|
426
|
-
}`;
|
|
427
|
-
var TOKEN_GATEWAY_ASSET_TELEPORTED_STATUS = `
|
|
428
|
-
query TokenGatewayAssetTeleportedStatus($commitment: String!) {
|
|
429
|
-
tokenGatewayAssetTeleporteds(
|
|
430
|
-
filter: { commitment: { equalTo: $commitment } }
|
|
431
|
-
) {
|
|
432
|
-
nodes {
|
|
433
|
-
id
|
|
434
|
-
from
|
|
435
|
-
to
|
|
436
|
-
sourceChain
|
|
437
|
-
destChain
|
|
438
|
-
commitment
|
|
439
|
-
amount
|
|
440
|
-
usdValue
|
|
441
|
-
assetId
|
|
442
|
-
redeem
|
|
443
|
-
status
|
|
444
|
-
createdAt
|
|
445
|
-
blockNumber
|
|
446
|
-
blockTimestamp
|
|
447
|
-
transactionHash
|
|
448
|
-
statusMetadata {
|
|
449
|
-
nodes {
|
|
450
|
-
status
|
|
451
|
-
chain
|
|
452
|
-
timestamp
|
|
453
|
-
blockNumber
|
|
454
|
-
transactionHash
|
|
455
|
-
}
|
|
456
|
-
}
|
|
457
|
-
}
|
|
458
|
-
}
|
|
459
|
-
}`;
|
|
460
|
-
|
|
461
233
|
// src/types/index.ts
|
|
462
234
|
var RequestStatus = Object.freeze({
|
|
463
235
|
SOURCE: "SOURCE",
|
|
@@ -505,16 +277,6 @@ var RequestKind = /* @__PURE__ */ ((RequestKind2) => {
|
|
|
505
277
|
RequestKind2[RequestKind2["UpdateParams"] = 2] = "UpdateParams";
|
|
506
278
|
return RequestKind2;
|
|
507
279
|
})(RequestKind || {});
|
|
508
|
-
var AbortSignalInternal = class _AbortSignalInternal extends Error {
|
|
509
|
-
constructor(message) {
|
|
510
|
-
super();
|
|
511
|
-
this.name = "AbortSignalInternal";
|
|
512
|
-
this.message = message;
|
|
513
|
-
}
|
|
514
|
-
static isError(error) {
|
|
515
|
-
return error instanceof _AbortSignalInternal;
|
|
516
|
-
}
|
|
517
|
-
};
|
|
518
280
|
|
|
519
281
|
// src/abis/evmHost.ts
|
|
520
282
|
var ABI = [
|
|
@@ -3541,1346 +3303,290 @@ var ABI2 = [
|
|
|
3541
3303
|
}
|
|
3542
3304
|
];
|
|
3543
3305
|
var handler_default = { ABI: ABI2 };
|
|
3544
|
-
|
|
3545
|
-
|
|
3546
|
-
|
|
3547
|
-
|
|
3548
|
-
|
|
3549
|
-
|
|
3550
|
-
|
|
3551
|
-
|
|
3552
|
-
|
|
3553
|
-
|
|
3554
|
-
|
|
3555
|
-
["EVM-10200" /* GNOSIS_CHIADO */]: 10200,
|
|
3556
|
-
["KUSAMA-4009" /* HYPERBRIDGE_GARGANTUA */]: 4009,
|
|
3557
|
-
["EVM-11155111" /* SEPOLIA */]: 11155111,
|
|
3558
|
-
["EVM-1" /* MAINNET */]: 1,
|
|
3559
|
-
["EVM-56" /* BSC_MAINNET */]: 56
|
|
3560
|
-
};
|
|
3561
|
-
var viemChains = {
|
|
3562
|
-
"97": bscTestnet,
|
|
3563
|
-
"10200": gnosisChiado,
|
|
3564
|
-
"11155111": sepolia,
|
|
3565
|
-
"1": mainnet,
|
|
3566
|
-
"56": bsc
|
|
3567
|
-
};
|
|
3568
|
-
var WrappedNativeDecimals = {
|
|
3569
|
-
["EVM-97" /* BSC_CHAPEL */]: 18,
|
|
3570
|
-
["EVM-10200" /* GNOSIS_CHIADO */]: 18,
|
|
3571
|
-
["EVM-11155111" /* SEPOLIA */]: 18,
|
|
3572
|
-
["EVM-1" /* MAINNET */]: 18,
|
|
3573
|
-
["EVM-56" /* BSC_MAINNET */]: 18
|
|
3574
|
-
};
|
|
3575
|
-
var assets = {
|
|
3576
|
-
["EVM-97" /* BSC_CHAPEL */]: {
|
|
3577
|
-
WETH: "0xae13d989dac2f0debff460ac112a837c89baa7cd".toLowerCase(),
|
|
3578
|
-
DAI: "0x1938165569A5463327fb206bE06d8D9253aa06b7".toLowerCase(),
|
|
3579
|
-
USDC: "0xC625ec7D30A4b1AAEfb1304610CdAcD0d606aC92".toLowerCase(),
|
|
3580
|
-
USDT: "0xc043f483373072f7f27420d6e7d7ad269c018e18".toLowerCase()
|
|
3581
|
-
},
|
|
3582
|
-
["EVM-10200" /* GNOSIS_CHIADO */]: {
|
|
3583
|
-
WETH: "0x0000000000000000000000000000000000000000".toLowerCase(),
|
|
3584
|
-
DAI: "0x50B1d3c7c073c9caa1Ef207365A2c9C976bD70b9".toLowerCase(),
|
|
3585
|
-
USDC: "0x0000000000000000000000000000000000000000".toLowerCase(),
|
|
3586
|
-
USDT: "0x0000000000000000000000000000000000000000".toLowerCase()
|
|
3587
|
-
},
|
|
3588
|
-
["EVM-11155111" /* SEPOLIA */]: {
|
|
3589
|
-
WETH: "0x7b79995e5f793A07Bc00c21412e50Ecae098E7f9".toLowerCase(),
|
|
3590
|
-
USDC: "0x0000000000000000000000000000000000000000".toLowerCase(),
|
|
3591
|
-
USDT: "0x0000000000000000000000000000000000000000".toLowerCase(),
|
|
3592
|
-
DAI: "0x0000000000000000000000000000000000000000".toLowerCase()
|
|
3593
|
-
},
|
|
3594
|
-
["EVM-1" /* MAINNET */]: {
|
|
3595
|
-
WETH: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2".toLowerCase(),
|
|
3596
|
-
DAI: "0x6B175474E89094C44Da98b954EedeAC495271d0F".toLowerCase(),
|
|
3597
|
-
USDC: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48".toLowerCase(),
|
|
3598
|
-
USDT: "0xdAC17F958D2ee523a2206206994597C13D831ec7".toLowerCase()
|
|
3599
|
-
},
|
|
3600
|
-
["EVM-56" /* BSC_MAINNET */]: {
|
|
3601
|
-
WETH: "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c".toLowerCase(),
|
|
3602
|
-
DAI: "0x1AF3F329e8BE154074D8769D1FFa4eE058B1DBc3".toLowerCase(),
|
|
3603
|
-
USDC: "0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d".toLowerCase(),
|
|
3604
|
-
USDT: "0x55d398326f99059fF775485246999027B3197955".toLowerCase()
|
|
3306
|
+
function getPeakPosByHeight(height) {
|
|
3307
|
+
return (1n << BigInt(height + 1)) - 2n;
|
|
3308
|
+
}
|
|
3309
|
+
function leftPeakHeightPos(mmrSize) {
|
|
3310
|
+
let height = 1;
|
|
3311
|
+
let prevPos = 0n;
|
|
3312
|
+
let pos = getPeakPosByHeight(height);
|
|
3313
|
+
while (pos < mmrSize) {
|
|
3314
|
+
height += 1;
|
|
3315
|
+
prevPos = pos;
|
|
3316
|
+
pos = getPeakPosByHeight(height);
|
|
3605
3317
|
}
|
|
3606
|
-
|
|
3607
|
-
|
|
3608
|
-
|
|
3609
|
-
|
|
3610
|
-
|
|
3611
|
-
|
|
3612
|
-
|
|
3613
|
-
|
|
3614
|
-
|
|
3615
|
-
|
|
3616
|
-
|
|
3617
|
-
|
|
3618
|
-
["EVM-11155111" /* SEPOLIA */]: "0x2EdB74C269948b60ec1000040E104cef0eABaae8",
|
|
3619
|
-
["EVM-1" /* MAINNET */]: "0x792A6236AF69787C40cF76b69B4c8c7B28c4cA20",
|
|
3620
|
-
["EVM-56" /* BSC_MAINNET */]: "0x24B5d421Ec373FcA57325dd2F0C074009Af021F7"
|
|
3621
|
-
},
|
|
3622
|
-
UniswapRouter02: {
|
|
3623
|
-
["EVM-97" /* BSC_CHAPEL */]: "0x9639379819420704457B07A0C33B678D9E0F8Df0",
|
|
3624
|
-
["EVM-10200" /* GNOSIS_CHIADO */]: "0x0000000000000000000000000000000000000000",
|
|
3625
|
-
["EVM-11155111" /* SEPOLIA */]: "0x0000000000000000000000000000000000000000",
|
|
3626
|
-
["EVM-1" /* MAINNET */]: "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D",
|
|
3627
|
-
["EVM-56" /* BSC_MAINNET */]: "0x0000000000000000000000000000000000000000"
|
|
3628
|
-
},
|
|
3629
|
-
UniswapV2Factory: {
|
|
3630
|
-
["EVM-97" /* BSC_CHAPEL */]: "0x12e036669DA18F4A2777853d6e2136b32AceEC86",
|
|
3631
|
-
["EVM-10200" /* GNOSIS_CHIADO */]: "0x0000000000000000000000000000000000000000",
|
|
3632
|
-
["EVM-11155111" /* SEPOLIA */]: "0x0000000000000000000000000000000000000000",
|
|
3633
|
-
["EVM-1" /* MAINNET */]: "0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f",
|
|
3634
|
-
["EVM-56" /* BSC_MAINNET */]: "0x0000000000000000000000000000000000000000"
|
|
3635
|
-
},
|
|
3636
|
-
BatchExecutor: {
|
|
3637
|
-
["EVM-97" /* BSC_CHAPEL */]: "0x4CC58B5D8FBf838d062E4b21F75C327835B5F0ef",
|
|
3638
|
-
["EVM-1" /* MAINNET */]: "0x0000000000000000000000000000000000000000",
|
|
3639
|
-
["EVM-56" /* BSC_MAINNET */]: "0x0000000000000000000000000000000000000000"
|
|
3640
|
-
},
|
|
3641
|
-
UniversalRouter: {
|
|
3642
|
-
["EVM-97" /* BSC_CHAPEL */]: "0xcc6d5ece3d4a57245bf5a2f64f3ed9179b81f714",
|
|
3643
|
-
["EVM-1" /* MAINNET */]: "0x0000000000000000000000000000000000000000",
|
|
3644
|
-
["EVM-56" /* BSC_MAINNET */]: "0x0000000000000000000000000000000000000000"
|
|
3645
|
-
},
|
|
3646
|
-
UniswapV3Router: {
|
|
3647
|
-
["EVM-97" /* BSC_CHAPEL */]: "0x0000000000000000000000000000000000000000",
|
|
3648
|
-
["EVM-1" /* MAINNET */]: "0x1F98431c8aD98523631AE4a59f267346ea31F984",
|
|
3649
|
-
["EVM-56" /* BSC_MAINNET */]: "0x0000000000000000000000000000000000000000"
|
|
3650
|
-
},
|
|
3651
|
-
UniswapV3Factory: {
|
|
3652
|
-
["EVM-97" /* BSC_CHAPEL */]: "0x0000000000000000000000000000000000000000",
|
|
3653
|
-
["EVM-1" /* MAINNET */]: "0x1F98431c8aD98523631AE4a59f267346ea31F984",
|
|
3654
|
-
["EVM-56" /* BSC_MAINNET */]: "0x0000000000000000000000000000000000000000"
|
|
3655
|
-
},
|
|
3656
|
-
UniswapV3Quoter: {
|
|
3657
|
-
["EVM-97" /* BSC_CHAPEL */]: "0x0000000000000000000000000000000000000000",
|
|
3658
|
-
["EVM-1" /* MAINNET */]: "0x61fFE014bA17989E743c5F6cB21bF9697530B21e",
|
|
3659
|
-
["EVM-56" /* BSC_MAINNET */]: "0x0000000000000000000000000000000000000000"
|
|
3660
|
-
},
|
|
3661
|
-
UniswapV4PoolManager: {
|
|
3662
|
-
["EVM-97" /* BSC_CHAPEL */]: "0x0000000000000000000000000000000000000000",
|
|
3663
|
-
["EVM-1" /* MAINNET */]: "0x0000000000000000000000000000000000000000",
|
|
3664
|
-
["EVM-56" /* BSC_MAINNET */]: "0x0000000000000000000000000000000000000000"
|
|
3665
|
-
},
|
|
3666
|
-
UniswapV4Quoter: {
|
|
3667
|
-
["EVM-97" /* BSC_CHAPEL */]: "0x0000000000000000000000000000000000000000",
|
|
3668
|
-
["EVM-1" /* MAINNET */]: "0x52f0e24d1c21c8a0cb1e5a5dd6198556bd9e1203",
|
|
3669
|
-
["EVM-56" /* BSC_MAINNET */]: "0x0000000000000000000000000000000000000000"
|
|
3670
|
-
},
|
|
3671
|
-
Calldispatcher: {
|
|
3672
|
-
["EVM-11155111" /* SEPOLIA */]: "0xC7f13b6D03A0A7F3239d38897503E90553ABe155"
|
|
3318
|
+
return [height - 1, prevPos];
|
|
3319
|
+
}
|
|
3320
|
+
function getRightPeak(initialHeight, initialPos, mmrSize) {
|
|
3321
|
+
let height = initialHeight;
|
|
3322
|
+
let pos = initialPos;
|
|
3323
|
+
pos += siblingOffset(height);
|
|
3324
|
+
while (pos > mmrSize - 1n) {
|
|
3325
|
+
if (height === 0) {
|
|
3326
|
+
return null;
|
|
3327
|
+
}
|
|
3328
|
+
pos -= parentOffset(height - 1);
|
|
3329
|
+
height -= 1;
|
|
3673
3330
|
}
|
|
3674
|
-
|
|
3675
|
-
|
|
3676
|
-
|
|
3677
|
-
|
|
3678
|
-
[
|
|
3679
|
-
|
|
3680
|
-
|
|
3681
|
-
|
|
3682
|
-
|
|
3683
|
-
|
|
3684
|
-
|
|
3685
|
-
["EVM-10200" /* GNOSIS_CHIADO */]: "GNO0",
|
|
3686
|
-
["KUSAMA-4009" /* HYPERBRIDGE_GARGANTUA */]: "PAS0",
|
|
3687
|
-
["EVM-11155111" /* SEPOLIA */]: "ETH0",
|
|
3688
|
-
["EVM-1" /* MAINNET */]: "ETH0",
|
|
3689
|
-
["EVM-56" /* BSC_MAINNET */]: "BSC0"
|
|
3690
|
-
};
|
|
3691
|
-
|
|
3692
|
-
// src/configs/ChainConfigService.ts
|
|
3693
|
-
var ChainConfigService = class {
|
|
3694
|
-
rpcUrls;
|
|
3695
|
-
constructor(env2 = process.env) {
|
|
3696
|
-
this.rpcUrls = createRpcUrls(env2);
|
|
3331
|
+
return [height, pos];
|
|
3332
|
+
}
|
|
3333
|
+
function getPeaks(mmrSize) {
|
|
3334
|
+
const positions = [];
|
|
3335
|
+
let [height, pos] = leftPeakHeightPos(mmrSize);
|
|
3336
|
+
positions.push(pos);
|
|
3337
|
+
while (height > 0) {
|
|
3338
|
+
const peak = getRightPeak(height, pos, mmrSize);
|
|
3339
|
+
if (!peak) break;
|
|
3340
|
+
[height, pos] = peak;
|
|
3341
|
+
positions.push(pos);
|
|
3697
3342
|
}
|
|
3698
|
-
|
|
3699
|
-
|
|
3700
|
-
|
|
3701
|
-
|
|
3702
|
-
|
|
3703
|
-
|
|
3343
|
+
return positions;
|
|
3344
|
+
}
|
|
3345
|
+
function allOnes(num) {
|
|
3346
|
+
if (num === 0n) return false;
|
|
3347
|
+
return num.toString(2).split("").every((bit) => bit === "1");
|
|
3348
|
+
}
|
|
3349
|
+
function jumpLeft(pos) {
|
|
3350
|
+
const bitLength = pos.toString(2).length;
|
|
3351
|
+
const mostSignificantBits = 1n << BigInt(bitLength - 1);
|
|
3352
|
+
return pos - (mostSignificantBits - 1n);
|
|
3353
|
+
}
|
|
3354
|
+
function posHeightInTree(initialPos) {
|
|
3355
|
+
let pos = initialPos + 1n;
|
|
3356
|
+
while (!allOnes(pos)) {
|
|
3357
|
+
pos = jumpLeft(pos);
|
|
3704
3358
|
}
|
|
3705
|
-
|
|
3706
|
-
|
|
3359
|
+
return pos.toString(2).length - 1;
|
|
3360
|
+
}
|
|
3361
|
+
function parentOffset(height) {
|
|
3362
|
+
return 2n << BigInt(height);
|
|
3363
|
+
}
|
|
3364
|
+
function siblingOffset(height) {
|
|
3365
|
+
return (2n << BigInt(height)) - 1n;
|
|
3366
|
+
}
|
|
3367
|
+
function takeWhileVec(v, p) {
|
|
3368
|
+
const index = v.findIndex((item) => !p(item));
|
|
3369
|
+
if (index === -1) {
|
|
3370
|
+
const result = [...v];
|
|
3371
|
+
v.length = 0;
|
|
3372
|
+
return result;
|
|
3707
3373
|
}
|
|
3708
|
-
|
|
3709
|
-
|
|
3374
|
+
return v.splice(0, index);
|
|
3375
|
+
}
|
|
3376
|
+
function mmrPositionToKIndex(initialLeaves, mmrSize) {
|
|
3377
|
+
const leaves = [...initialLeaves];
|
|
3378
|
+
const peaks = getPeaks(mmrSize);
|
|
3379
|
+
const leavesWithKIndices = [];
|
|
3380
|
+
for (const peak of peaks) {
|
|
3381
|
+
const peakLeaves = takeWhileVec(leaves, (pos) => pos <= peak);
|
|
3382
|
+
if (peakLeaves.length > 0) {
|
|
3383
|
+
for (const pos of peakLeaves) {
|
|
3384
|
+
const height = posHeightInTree(peak);
|
|
3385
|
+
let index = 0n;
|
|
3386
|
+
let parentPos = peak;
|
|
3387
|
+
for (let h = height; h >= 1; h--) {
|
|
3388
|
+
const leftChild = parentPos - parentOffset(h - 1);
|
|
3389
|
+
const rightChild = leftChild + siblingOffset(h - 1);
|
|
3390
|
+
index *= 2n;
|
|
3391
|
+
if (leftChild >= pos) {
|
|
3392
|
+
parentPos = leftChild;
|
|
3393
|
+
} else {
|
|
3394
|
+
parentPos = rightChild;
|
|
3395
|
+
index += 1n;
|
|
3396
|
+
}
|
|
3397
|
+
}
|
|
3398
|
+
leavesWithKIndices.push([pos, index]);
|
|
3399
|
+
}
|
|
3400
|
+
}
|
|
3710
3401
|
}
|
|
3711
|
-
|
|
3712
|
-
|
|
3713
|
-
|
|
3714
|
-
|
|
3715
|
-
|
|
3402
|
+
return leavesWithKIndices;
|
|
3403
|
+
}
|
|
3404
|
+
function calculateMMRSize(numberOfLeaves) {
|
|
3405
|
+
const numberOfPeaks = numberOfLeaves.toString(2).split("1").length - 1;
|
|
3406
|
+
return 2n * numberOfLeaves - BigInt(numberOfPeaks);
|
|
3407
|
+
}
|
|
3408
|
+
async function generateRootWithProof(postRequest, treeSize) {
|
|
3409
|
+
const { generate_root_with_proof: generate_root_with_proof2 } = await load_ckb_mmr();
|
|
3410
|
+
const { commitment: hash, encodePacked: encodePacked2 } = postRequestCommitment(postRequest);
|
|
3411
|
+
const result = JSON.parse(generate_root_with_proof2(hexToBytes(encodePacked2), treeSize));
|
|
3412
|
+
const { root, proof, mmr_size, leaf_positions, keccak_hash_calldata } = result;
|
|
3413
|
+
if (keccak_hash_calldata !== hash) {
|
|
3414
|
+
console.log("keccak_hash", keccak_hash_calldata);
|
|
3415
|
+
console.log("hash", hash);
|
|
3416
|
+
throw new Error("Abi keccak hash mismatch");
|
|
3716
3417
|
}
|
|
3717
|
-
|
|
3718
|
-
|
|
3719
|
-
|
|
3720
|
-
|
|
3721
|
-
|
|
3722
|
-
|
|
3723
|
-
|
|
3724
|
-
|
|
3725
|
-
}
|
|
3726
|
-
|
|
3727
|
-
|
|
3728
|
-
|
|
3729
|
-
|
|
3730
|
-
|
|
3731
|
-
|
|
3732
|
-
getHyperbridgeChainId() {
|
|
3733
|
-
return chainIds["KUSAMA-4009" /* HYPERBRIDGE_GARGANTUA */];
|
|
3734
|
-
}
|
|
3735
|
-
getRpcUrl(chain) {
|
|
3736
|
-
return this.rpcUrls[chain];
|
|
3737
|
-
}
|
|
3738
|
-
getUniswapRouterV2Address(chain) {
|
|
3739
|
-
return addresses.UniswapRouter02[chain];
|
|
3740
|
-
}
|
|
3741
|
-
getUniswapV2FactoryAddress(chain) {
|
|
3742
|
-
return addresses.UniswapV2Factory[chain];
|
|
3743
|
-
}
|
|
3744
|
-
getBatchExecutorAddress(chain) {
|
|
3745
|
-
return addresses.BatchExecutor[chain];
|
|
3746
|
-
}
|
|
3747
|
-
getUniversalRouterAddress(chain) {
|
|
3748
|
-
return addresses.UniversalRouter[chain];
|
|
3749
|
-
}
|
|
3750
|
-
getUniswapV3RouterAddress(chain) {
|
|
3751
|
-
return addresses.UniswapV3Router[chain];
|
|
3752
|
-
}
|
|
3753
|
-
getUniswapV3FactoryAddress(chain) {
|
|
3754
|
-
return addresses.UniswapV3Factory[chain];
|
|
3755
|
-
}
|
|
3756
|
-
getUniswapV3QuoterAddress(chain) {
|
|
3757
|
-
return addresses.UniswapV3Quoter[chain];
|
|
3758
|
-
}
|
|
3759
|
-
getUniswapV4PoolManagerAddress(chain) {
|
|
3760
|
-
return addresses.UniswapV4PoolManager[chain];
|
|
3761
|
-
}
|
|
3762
|
-
getUniswapV4QuoterAddress(chain) {
|
|
3763
|
-
return addresses.UniswapV4Quoter[chain];
|
|
3764
|
-
}
|
|
3765
|
-
};
|
|
3766
|
-
|
|
3767
|
-
// src/chains/evm.ts
|
|
3768
|
-
var chains = {
|
|
3769
|
-
[mainnet.id]: mainnet,
|
|
3770
|
-
[arbitrum.id]: arbitrum,
|
|
3771
|
-
[arbitrumSepolia.id]: arbitrumSepolia,
|
|
3772
|
-
[optimism.id]: optimism,
|
|
3773
|
-
[optimismSepolia.id]: optimismSepolia,
|
|
3774
|
-
[base.id]: base,
|
|
3775
|
-
[baseSepolia.id]: baseSepolia,
|
|
3776
|
-
[soneium.id]: soneium,
|
|
3777
|
-
[bsc.id]: bsc,
|
|
3778
|
-
[bscTestnet.id]: bscTestnet,
|
|
3779
|
-
[gnosis.id]: gnosis,
|
|
3780
|
-
[gnosisChiado.id]: gnosisChiado
|
|
3781
|
-
};
|
|
3782
|
-
var DEFAULT_ADDRESS = "0x0000000000000000000000000000000000000000";
|
|
3783
|
-
var EvmChain = class {
|
|
3784
|
-
constructor(params) {
|
|
3785
|
-
this.params = params;
|
|
3786
|
-
this.publicClient = createPublicClient({
|
|
3787
|
-
// @ts-ignore
|
|
3788
|
-
chain: chains[params.chainId],
|
|
3789
|
-
transport: http(params.url)
|
|
3790
|
-
});
|
|
3791
|
-
this.chainConfigService = new ChainConfigService();
|
|
3792
|
-
}
|
|
3793
|
-
publicClient;
|
|
3794
|
-
chainConfigService;
|
|
3795
|
-
// Expose minimal getters for external helpers/classes
|
|
3796
|
-
get client() {
|
|
3797
|
-
return this.publicClient;
|
|
3798
|
-
}
|
|
3799
|
-
get host() {
|
|
3800
|
-
return this.params.host;
|
|
3418
|
+
const [[, kIndex]] = mmrPositionToKIndex(leaf_positions, BigInt(mmr_size));
|
|
3419
|
+
return {
|
|
3420
|
+
root,
|
|
3421
|
+
proof,
|
|
3422
|
+
index: treeSize - 1n,
|
|
3423
|
+
kIndex,
|
|
3424
|
+
treeSize,
|
|
3425
|
+
mmrSize: mmr_size
|
|
3426
|
+
};
|
|
3427
|
+
}
|
|
3428
|
+
async function load_ckb_mmr() {
|
|
3429
|
+
if (hasWindow) {
|
|
3430
|
+
const wasm2 = await Promise.resolve().then(() => (init_node(), node_exports));
|
|
3431
|
+
await wasm2.default();
|
|
3432
|
+
return wasm2;
|
|
3801
3433
|
}
|
|
3802
|
-
|
|
3803
|
-
|
|
3434
|
+
if (isNode) {
|
|
3435
|
+
const wasm2 = await Promise.resolve().then(() => (init_node(), node_exports));
|
|
3436
|
+
return wasm2;
|
|
3804
3437
|
}
|
|
3438
|
+
throw new Error(`SDK not setup for ${env}`);
|
|
3439
|
+
}
|
|
3440
|
+
async function __test() {
|
|
3441
|
+
const { generate_root_with_proof: generate_root_with_proof2 } = await load_ckb_mmr();
|
|
3442
|
+
return generate_root_with_proof2(new Uint8Array(), 120n);
|
|
3443
|
+
}
|
|
3444
|
+
var H256 = Vector(u8, 32);
|
|
3445
|
+
var EvmStateProof = Struct({
|
|
3805
3446
|
/**
|
|
3806
|
-
*
|
|
3807
|
-
* @param {HexString} commitment - The commitment to derive the key from.
|
|
3808
|
-
* @returns {HexString} The derived key.
|
|
3447
|
+
* Proof of the contract state.
|
|
3809
3448
|
*/
|
|
3810
|
-
|
|
3811
|
-
return deriveMapKey(hexToBytes(commitment), REQUEST_RECEIPTS_SLOT);
|
|
3812
|
-
}
|
|
3449
|
+
contractProof: Vector(Vector(u8)),
|
|
3813
3450
|
/**
|
|
3814
|
-
*
|
|
3815
|
-
* @param {HexString} commitment - The commitment to query.
|
|
3816
|
-
* @returns {Promise<HexString | undefined>} The relayer address responsible for delivering the request.
|
|
3451
|
+
* Proof of the storage state.
|
|
3817
3452
|
*/
|
|
3818
|
-
|
|
3819
|
-
|
|
3820
|
-
|
|
3821
|
-
|
|
3822
|
-
|
|
3823
|
-
|
|
3824
|
-
|
|
3825
|
-
|
|
3826
|
-
|
|
3453
|
+
storageProof: Vector(Tuple(Vector(u8), Vector(Vector(u8))))
|
|
3454
|
+
});
|
|
3455
|
+
var SubstrateHashing = Enum({
|
|
3456
|
+
/* For chains that use keccak as their hashing algo */
|
|
3457
|
+
Keccak: _void,
|
|
3458
|
+
/* For chains that use blake2b as their hashing algo */
|
|
3459
|
+
Blake2: _void
|
|
3460
|
+
});
|
|
3461
|
+
var SubstrateStateMachineProof = Struct({
|
|
3827
3462
|
/**
|
|
3828
|
-
*
|
|
3829
|
-
* @param {IMessage} message - The message to query.
|
|
3830
|
-
* @param {string} counterparty - The counterparty address.
|
|
3831
|
-
* @param {bigint} [at] - The block number to query at.
|
|
3832
|
-
* @returns {Promise<HexString>} The proof.
|
|
3463
|
+
* The hasher used to hash the state machine state.
|
|
3833
3464
|
*/
|
|
3834
|
-
|
|
3835
|
-
const commitmentKeys = "Requests" in message ? message.Requests.map((key) => requestCommitmentKey(key)) : message.Responses.map((key) => responseCommitmentKey(key));
|
|
3836
|
-
const config = {
|
|
3837
|
-
address: this.params.host,
|
|
3838
|
-
storageKeys: commitmentKeys
|
|
3839
|
-
};
|
|
3840
|
-
if (!at) {
|
|
3841
|
-
config.blockTag = "latest";
|
|
3842
|
-
} else {
|
|
3843
|
-
config.blockNumber = at;
|
|
3844
|
-
}
|
|
3845
|
-
const proof = await this.publicClient.getProof(config);
|
|
3846
|
-
const flattenedProof = Array.from(new Set(flatten(proof.storageProof.map((item) => item.proof))));
|
|
3847
|
-
const encoded = EvmStateProof.enc({
|
|
3848
|
-
contractProof: proof.accountProof.map((item) => Array.from(hexToBytes(item))),
|
|
3849
|
-
storageProof: [
|
|
3850
|
-
[Array.from(hexToBytes(this.params.host)), flattenedProof.map((item) => Array.from(hexToBytes(item)))]
|
|
3851
|
-
]
|
|
3852
|
-
});
|
|
3853
|
-
return toHex(encoded);
|
|
3854
|
-
}
|
|
3465
|
+
hasher: SubstrateHashing,
|
|
3855
3466
|
/**
|
|
3856
|
-
*
|
|
3857
|
-
* @param {bigint} at - The block height at which to query the storage proof.
|
|
3858
|
-
* @param {HexString[]} keys - The keys for which to query the storage proof.
|
|
3859
|
-
* @returns {Promise<HexString>} The encoded storage proof.
|
|
3467
|
+
* Proof of the state machine state.
|
|
3860
3468
|
*/
|
|
3861
|
-
|
|
3862
|
-
|
|
3863
|
-
|
|
3864
|
-
|
|
3865
|
-
|
|
3866
|
-
if (!at) {
|
|
3867
|
-
config.blockTag = "latest";
|
|
3868
|
-
} else {
|
|
3869
|
-
config.blockNumber = at;
|
|
3870
|
-
}
|
|
3871
|
-
const proof = await this.publicClient.getProof(config);
|
|
3872
|
-
const flattenedProof = Array.from(new Set(flatten(proof.storageProof.map((item) => item.proof))));
|
|
3873
|
-
const encoded = EvmStateProof.enc({
|
|
3874
|
-
contractProof: proof.accountProof.map((item) => Array.from(hexToBytes(item))),
|
|
3875
|
-
storageProof: [
|
|
3876
|
-
[Array.from(hexToBytes(this.params.host)), flattenedProof.map((item) => Array.from(hexToBytes(item)))]
|
|
3877
|
-
]
|
|
3878
|
-
});
|
|
3879
|
-
return toHex(encoded);
|
|
3880
|
-
}
|
|
3881
|
-
/**
|
|
3882
|
-
* Returns the current timestamp of the chain.
|
|
3883
|
-
* @returns {Promise<bigint>} The current timestamp.
|
|
3469
|
+
storageProof: Vector(Vector(u8))
|
|
3470
|
+
});
|
|
3471
|
+
var SubstrateStateProof = Enum({
|
|
3472
|
+
/*
|
|
3473
|
+
* Uses overlay root for verification
|
|
3884
3474
|
*/
|
|
3885
|
-
|
|
3886
|
-
|
|
3887
|
-
|
|
3888
|
-
abi: evmHost_default.ABI,
|
|
3889
|
-
functionName: "timestamp"
|
|
3890
|
-
});
|
|
3891
|
-
return BigInt(data);
|
|
3892
|
-
}
|
|
3893
|
-
/**
|
|
3894
|
-
* Get the latest state machine height for a given state machine ID.
|
|
3895
|
-
* @param {StateMachineIdParams} stateMachineId - The state machine ID.
|
|
3896
|
-
* @returns {Promise<bigint>} The latest state machine height.
|
|
3475
|
+
OverlayProof: SubstrateStateMachineProof,
|
|
3476
|
+
/*
|
|
3477
|
+
* Uses state root for verification
|
|
3897
3478
|
*/
|
|
3898
|
-
|
|
3899
|
-
|
|
3900
|
-
|
|
3901
|
-
|
|
3902
|
-
|
|
3903
|
-
|
|
3904
|
-
);
|
|
3905
|
-
const data = await this.publicClient.readContract({
|
|
3906
|
-
address: this.params.host,
|
|
3907
|
-
abi: evmHost_default.ABI,
|
|
3908
|
-
functionName: "latestStateMachineHeight",
|
|
3909
|
-
args: [BigInt(id)]
|
|
3910
|
-
});
|
|
3911
|
-
return data;
|
|
3912
|
-
}
|
|
3913
|
-
/**
|
|
3914
|
-
* Get the state machine update time for a given state machine height.
|
|
3915
|
-
* @param {StateMachineHeight} stateMachineHeight - The state machine height.
|
|
3916
|
-
* @returns {Promise<bigint>} The statemachine update time in seconds.
|
|
3479
|
+
StateProof: SubstrateStateMachineProof
|
|
3480
|
+
});
|
|
3481
|
+
var BasicProof = Vector(Vector(u8));
|
|
3482
|
+
var LeafIndexAndPos = Struct({
|
|
3483
|
+
/*
|
|
3484
|
+
* Leaf index
|
|
3917
3485
|
*/
|
|
3918
|
-
|
|
3919
|
-
|
|
3920
|
-
|
|
3921
|
-
if (!id) throw new Error("Expected Polkadot or Kusama State machine id when reading state machine update time");
|
|
3922
|
-
const data = await this.publicClient.readContract({
|
|
3923
|
-
address: this.params.host,
|
|
3924
|
-
abi: evmHost_default.ABI,
|
|
3925
|
-
functionName: "stateMachineCommitmentUpdateTime",
|
|
3926
|
-
args: [{ stateMachineId: BigInt(id), height: stateMachineHeight.height }]
|
|
3927
|
-
});
|
|
3928
|
-
return data;
|
|
3929
|
-
}
|
|
3930
|
-
/**
|
|
3931
|
-
* Get the challenge period for a given state machine id.
|
|
3932
|
-
* @param {StateMachineIdParams} stateMachineId - The state machine ID.
|
|
3933
|
-
* @returns {Promise<bigint>} The challenge period in seconds.
|
|
3486
|
+
leafIndex: u64,
|
|
3487
|
+
/*
|
|
3488
|
+
* Leaf position in the MMR
|
|
3934
3489
|
*/
|
|
3935
|
-
|
|
3936
|
-
|
|
3937
|
-
|
|
3938
|
-
|
|
3939
|
-
|
|
3940
|
-
"Expected Polkadot or Kusama State machine id when reading latest state machine height on evm"
|
|
3941
|
-
);
|
|
3942
|
-
const data = await this.publicClient.readContract({
|
|
3943
|
-
address: this.params.host,
|
|
3944
|
-
abi: evmHost_default.ABI,
|
|
3945
|
-
functionName: "challengePeriod"
|
|
3946
|
-
});
|
|
3947
|
-
return data;
|
|
3948
|
-
}
|
|
3949
|
-
/**
|
|
3950
|
-
* Encodes an ISMP message for the EVM chain.
|
|
3951
|
-
* @param {IIsmpMessage} message The ISMP message to encode.
|
|
3952
|
-
* @returns {HexString} The encoded calldata.
|
|
3490
|
+
pos: u64
|
|
3491
|
+
});
|
|
3492
|
+
var MmrProof = Struct({
|
|
3493
|
+
/*
|
|
3494
|
+
* Proof of the leaf index and position.
|
|
3953
3495
|
*/
|
|
3954
|
-
|
|
3955
|
-
|
|
3956
|
-
|
|
3957
|
-
const requests = zip(request.requests, mmrProof.leafIndexAndPos).map(([req, leafIndexAndPos]) => {
|
|
3958
|
-
if (!req || !leafIndexAndPos) return;
|
|
3959
|
-
const [[, kIndex]] = mmrPositionToKIndex(
|
|
3960
|
-
[leafIndexAndPos?.pos],
|
|
3961
|
-
calculateMMRSize(mmrProof.leafCount)
|
|
3962
|
-
);
|
|
3963
|
-
return {
|
|
3964
|
-
request: {
|
|
3965
|
-
source: toHex(req.source),
|
|
3966
|
-
dest: toHex(req.dest),
|
|
3967
|
-
to: req.to,
|
|
3968
|
-
from: req.from,
|
|
3969
|
-
nonce: req.nonce,
|
|
3970
|
-
timeoutTimestamp: req.timeoutTimestamp,
|
|
3971
|
-
body: req.body
|
|
3972
|
-
},
|
|
3973
|
-
index: leafIndexAndPos?.leafIndex,
|
|
3974
|
-
kIndex
|
|
3975
|
-
};
|
|
3976
|
-
}).filter((item) => !!item);
|
|
3977
|
-
const proof = {
|
|
3978
|
-
height: {
|
|
3979
|
-
stateMachineId: BigInt(Number.parseInt(request.proof.stateMachine.split("-")[1])),
|
|
3980
|
-
height: request.proof.height
|
|
3981
|
-
},
|
|
3982
|
-
multiproof: mmrProof.items.map((item) => bytesToHex(new Uint8Array(item))),
|
|
3983
|
-
leafCount: mmrProof.leafCount
|
|
3984
|
-
};
|
|
3985
|
-
const encoded2 = encodeFunctionData({
|
|
3986
|
-
abi: handler_default.ABI,
|
|
3987
|
-
functionName: "handlePostRequests",
|
|
3988
|
-
args: [
|
|
3989
|
-
this.params.host,
|
|
3990
|
-
{
|
|
3991
|
-
proof,
|
|
3992
|
-
requests
|
|
3993
|
-
}
|
|
3994
|
-
]
|
|
3995
|
-
});
|
|
3996
|
-
return encoded2;
|
|
3997
|
-
}).with({ kind: "TimeoutPostRequest" }, (timeout) => {
|
|
3998
|
-
const proof = SubstrateStateProof.dec(timeout.proof.proof).value.storageProof.map(
|
|
3999
|
-
(item) => toHex(new Uint8Array(item))
|
|
4000
|
-
);
|
|
4001
|
-
const encoded2 = encodeFunctionData({
|
|
4002
|
-
abi: handler_default.ABI,
|
|
4003
|
-
functionName: "handlePostRequestTimeouts",
|
|
4004
|
-
args: [
|
|
4005
|
-
this.params.host,
|
|
4006
|
-
{
|
|
4007
|
-
height: {
|
|
4008
|
-
stateMachineId: BigInt(Number.parseInt(timeout.proof.stateMachine.split("-")[1])),
|
|
4009
|
-
height: timeout.proof.height
|
|
4010
|
-
},
|
|
4011
|
-
timeouts: timeout.requests.map((req) => ({
|
|
4012
|
-
source: toHex(req.source),
|
|
4013
|
-
dest: toHex(req.dest),
|
|
4014
|
-
to: req.to,
|
|
4015
|
-
from: req.from,
|
|
4016
|
-
nonce: req.nonce,
|
|
4017
|
-
timeoutTimestamp: req.timeoutTimestamp,
|
|
4018
|
-
body: req.body
|
|
4019
|
-
})),
|
|
4020
|
-
proof
|
|
4021
|
-
}
|
|
4022
|
-
]
|
|
4023
|
-
});
|
|
4024
|
-
return encoded2;
|
|
4025
|
-
}).with({ kind: "GetResponse" }, (request) => {
|
|
4026
|
-
const mmrProof = MmrProof.dec(request.proof.proof);
|
|
4027
|
-
const responses = zip(request.responses, mmrProof.leafIndexAndPos).map(([req, leafIndexAndPos]) => {
|
|
4028
|
-
if (!req || !leafIndexAndPos) return;
|
|
4029
|
-
const [[, kIndex]] = mmrPositionToKIndex(
|
|
4030
|
-
[leafIndexAndPos?.pos],
|
|
4031
|
-
calculateMMRSize(mmrProof.leafCount)
|
|
4032
|
-
);
|
|
4033
|
-
return {
|
|
4034
|
-
response: {
|
|
4035
|
-
request: {
|
|
4036
|
-
source: toHex(req.get.source),
|
|
4037
|
-
dest: toHex(req.get.dest),
|
|
4038
|
-
from: req.get.from,
|
|
4039
|
-
nonce: req.get.nonce,
|
|
4040
|
-
timeoutTimestamp: req.get.timeoutTimestamp,
|
|
4041
|
-
keys: req.get.keys,
|
|
4042
|
-
context: req.get.context,
|
|
4043
|
-
height: req.get.height
|
|
4044
|
-
},
|
|
4045
|
-
values: req.values
|
|
4046
|
-
},
|
|
4047
|
-
index: leafIndexAndPos?.leafIndex,
|
|
4048
|
-
kIndex
|
|
4049
|
-
};
|
|
4050
|
-
}).filter((item) => !!item);
|
|
4051
|
-
const proof = {
|
|
4052
|
-
height: {
|
|
4053
|
-
stateMachineId: BigInt(Number.parseInt(request.proof.stateMachine.split("-")[1])),
|
|
4054
|
-
height: request.proof.height
|
|
4055
|
-
},
|
|
4056
|
-
multiproof: mmrProof.items.map((item) => bytesToHex(new Uint8Array(item))),
|
|
4057
|
-
leafCount: mmrProof.leafCount
|
|
4058
|
-
};
|
|
4059
|
-
const encoded2 = encodeFunctionData({
|
|
4060
|
-
abi: handler_default.ABI,
|
|
4061
|
-
functionName: "handleGetResponses",
|
|
4062
|
-
args: [
|
|
4063
|
-
this.params.host,
|
|
4064
|
-
{
|
|
4065
|
-
proof,
|
|
4066
|
-
responses
|
|
4067
|
-
}
|
|
4068
|
-
]
|
|
4069
|
-
});
|
|
4070
|
-
return encoded2;
|
|
4071
|
-
}).exhaustive();
|
|
4072
|
-
return encoded;
|
|
4073
|
-
}
|
|
4074
|
-
/**
|
|
4075
|
-
* Calculates the fee required to send a post request to the destination chain.
|
|
4076
|
-
* The fee is calculated based on the per-byte fee for the destination chain
|
|
4077
|
-
* multiplied by the size of the request body.
|
|
4078
|
-
*
|
|
4079
|
-
* @param request - The post request to calculate the fee for
|
|
4080
|
-
* @returns The total fee in wei required to send the post request
|
|
3496
|
+
leafIndexAndPos: Vector(LeafIndexAndPos),
|
|
3497
|
+
/*
|
|
3498
|
+
* Proof of the leaf data.
|
|
4081
3499
|
*/
|
|
4082
|
-
|
|
4083
|
-
|
|
4084
|
-
|
|
4085
|
-
abi: evmHost_default.ABI,
|
|
4086
|
-
functionName: "perByteFee",
|
|
4087
|
-
args: [toHex(request.dest)]
|
|
4088
|
-
});
|
|
4089
|
-
const bodyByteLength = Math.floor((request.body.length - 2) / 2);
|
|
4090
|
-
const length = bodyByteLength < 32 ? 32 : bodyByteLength;
|
|
4091
|
-
return perByteFee * BigInt(length);
|
|
4092
|
-
}
|
|
4093
|
-
/**
|
|
4094
|
-
* Estimates the gas required for a post request execution on this chain.
|
|
4095
|
-
* This function generates mock proofs for the post request, creates a state override
|
|
4096
|
-
* with the necessary overlay root, and estimates the gas cost for executing the
|
|
4097
|
-
* handlePostRequests transaction on the handler contract.
|
|
4098
|
-
*
|
|
4099
|
-
* @param request - The post request to estimate gas for
|
|
4100
|
-
* @param paraId - The ID of the parachain (Hyperbridge) that will process the request
|
|
4101
|
-
* @returns The estimated gas amount in gas units
|
|
3500
|
+
leafCount: u64,
|
|
3501
|
+
/*
|
|
3502
|
+
* Proof elements (hashes of siblings of inner nodes on the path to the leaf).
|
|
4102
3503
|
*/
|
|
4103
|
-
|
|
4104
|
-
|
|
4105
|
-
|
|
4106
|
-
|
|
4107
|
-
|
|
4108
|
-
|
|
4109
|
-
const { root, proof, index, kIndex, treeSize } = await generateRootWithProof(request, 2n ** 10n);
|
|
4110
|
-
const latestStateMachineHeight = 6291991n;
|
|
4111
|
-
const paraId = 4009n;
|
|
4112
|
-
const overlayRootSlot = getStateCommitmentFieldSlot(
|
|
4113
|
-
paraId,
|
|
4114
|
-
// Hyperbridge chain id
|
|
4115
|
-
latestStateMachineHeight,
|
|
4116
|
-
// Hyperbridge chain height
|
|
4117
|
-
1
|
|
4118
|
-
// For overlayRoot
|
|
4119
|
-
);
|
|
4120
|
-
const postParams = {
|
|
4121
|
-
height: {
|
|
4122
|
-
stateMachineId: BigInt(paraId),
|
|
4123
|
-
height: latestStateMachineHeight
|
|
4124
|
-
},
|
|
4125
|
-
multiproof: proof,
|
|
4126
|
-
leafCount: treeSize
|
|
4127
|
-
};
|
|
4128
|
-
const gas = await this.publicClient.estimateContractGas({
|
|
4129
|
-
address: hostParams.handler,
|
|
4130
|
-
abi: handler_default.ABI,
|
|
4131
|
-
functionName: "handlePostRequests",
|
|
4132
|
-
args: [
|
|
4133
|
-
this.params.host,
|
|
4134
|
-
{
|
|
4135
|
-
proof: postParams,
|
|
4136
|
-
requests: [
|
|
4137
|
-
{
|
|
4138
|
-
request: {
|
|
4139
|
-
...request,
|
|
4140
|
-
source: toHex(request.source),
|
|
4141
|
-
dest: toHex(request.dest)
|
|
4142
|
-
},
|
|
4143
|
-
index,
|
|
4144
|
-
kIndex
|
|
4145
|
-
}
|
|
4146
|
-
]
|
|
4147
|
-
}
|
|
4148
|
-
],
|
|
4149
|
-
stateOverride: [
|
|
4150
|
-
{
|
|
4151
|
-
address: this.params.host,
|
|
4152
|
-
stateDiff: [
|
|
4153
|
-
{
|
|
4154
|
-
slot: overlayRootSlot,
|
|
4155
|
-
value: root
|
|
4156
|
-
}
|
|
4157
|
-
]
|
|
4158
|
-
}
|
|
4159
|
-
]
|
|
4160
|
-
});
|
|
4161
|
-
return gas;
|
|
4162
|
-
}
|
|
4163
|
-
/**
|
|
4164
|
-
* Gets the fee token address and decimals for the chain.
|
|
4165
|
-
* This function gets the fee token address and decimals for the chain.
|
|
4166
|
-
*
|
|
4167
|
-
* @returns The fee token address and decimals
|
|
3504
|
+
items: Vector(H256)
|
|
3505
|
+
});
|
|
3506
|
+
var ConsensusStateId = Vector(u8, 4);
|
|
3507
|
+
var ConsensusMessage = Struct({
|
|
3508
|
+
/*
|
|
3509
|
+
* Consensus message data.
|
|
4168
3510
|
*/
|
|
4169
|
-
|
|
4170
|
-
|
|
4171
|
-
|
|
4172
|
-
address: this.params.host,
|
|
4173
|
-
functionName: "hostParams"
|
|
4174
|
-
});
|
|
4175
|
-
const feeTokenAddress = hostParams.feeToken;
|
|
4176
|
-
const feeTokenDecimals = await this.publicClient.readContract({
|
|
4177
|
-
address: feeTokenAddress,
|
|
4178
|
-
abi: erc20Abi,
|
|
4179
|
-
functionName: "decimals"
|
|
4180
|
-
});
|
|
4181
|
-
return { address: feeTokenAddress, decimals: feeTokenDecimals };
|
|
4182
|
-
}
|
|
4183
|
-
/**
|
|
4184
|
-
* Gets the nonce of the host.
|
|
4185
|
-
* This function gets the nonce of the host.
|
|
4186
|
-
*
|
|
4187
|
-
* @returns The nonce of the host
|
|
3511
|
+
consensusProof: Vector(u8),
|
|
3512
|
+
/*
|
|
3513
|
+
* Consensus state Id
|
|
4188
3514
|
*/
|
|
4189
|
-
|
|
4190
|
-
const nonce = await this.publicClient.readContract({
|
|
4191
|
-
abi: evmHost_default.ABI,
|
|
4192
|
-
address: this.params.host,
|
|
4193
|
-
functionName: "nonce"
|
|
4194
|
-
});
|
|
4195
|
-
return nonce;
|
|
4196
|
-
}
|
|
4197
|
-
};
|
|
4198
|
-
var REQUEST_COMMITMENTS_SLOT = 0n;
|
|
4199
|
-
var RESPONSE_COMMITMENTS_SLOT = 1n;
|
|
4200
|
-
var REQUEST_RECEIPTS_SLOT = 2n;
|
|
4201
|
-
var RESPONSE_RECEIPTS_SLOT = 3n;
|
|
4202
|
-
var STATE_COMMITMENTS_SLOT = 5n;
|
|
4203
|
-
function requestCommitmentKey(key) {
|
|
4204
|
-
const keyBytes = hexToBytes(key);
|
|
4205
|
-
const slot = REQUEST_COMMITMENTS_SLOT;
|
|
4206
|
-
const mappedKey = deriveMapKey(keyBytes, slot);
|
|
4207
|
-
const number = bytesToBigInt(hexToBytes(mappedKey)) + 1n;
|
|
4208
|
-
return pad(`0x${number.toString(16)}`, { size: 32 });
|
|
4209
|
-
}
|
|
4210
|
-
function responseCommitmentKey(key) {
|
|
4211
|
-
const keyBytes = hexToBytes(key);
|
|
4212
|
-
const slot = RESPONSE_COMMITMENTS_SLOT;
|
|
4213
|
-
const mappedKey = deriveMapKey(keyBytes, slot);
|
|
4214
|
-
const number = bytesToBigInt(hexToBytes(mappedKey)) + 1n;
|
|
4215
|
-
return pad(`0x${number.toString(16)}`, { size: 32 });
|
|
4216
|
-
}
|
|
4217
|
-
function deriveMapKey(key, slot) {
|
|
4218
|
-
const slotBytes = pad(`0x${slot.toString(16)}`, { size: 32 });
|
|
4219
|
-
const combined = new Uint8Array([...key, ...toBytes(slotBytes)]);
|
|
4220
|
-
return keccak256(combined);
|
|
4221
|
-
}
|
|
4222
|
-
function getStateCommitmentFieldSlot(stateMachineId, height, field) {
|
|
4223
|
-
const baseSlot = getStateCommitmentSlot(stateMachineId, height);
|
|
4224
|
-
const slotNumber = bytesToBigInt(toBytes(baseSlot)) + BigInt(field);
|
|
4225
|
-
return pad(`0x${slotNumber.toString(16)}`, { size: 32 });
|
|
4226
|
-
}
|
|
4227
|
-
function getStateCommitmentSlot(stateMachineId, height) {
|
|
4228
|
-
const firstLevelSlot = deriveFirstLevelSlot(stateMachineId, STATE_COMMITMENTS_SLOT);
|
|
4229
|
-
return deriveSecondLevelSlot(height, firstLevelSlot);
|
|
4230
|
-
}
|
|
4231
|
-
function deriveFirstLevelSlot(key, slot) {
|
|
4232
|
-
const keyHex = pad(`0x${key.toString(16)}`, { size: 32 });
|
|
4233
|
-
const keyBytes = toBytes(keyHex);
|
|
4234
|
-
const slotBytes = toBytes(pad(`0x${slot.toString(16)}`, { size: 32 }));
|
|
4235
|
-
const combined = new Uint8Array([...keyBytes, ...slotBytes]);
|
|
4236
|
-
return keccak256(combined);
|
|
4237
|
-
}
|
|
4238
|
-
function deriveSecondLevelSlot(key, firstLevelSlot) {
|
|
4239
|
-
const keyHex = pad(`0x${key.toString(16)}`, { size: 32 });
|
|
4240
|
-
const keyBytes = toBytes(keyHex);
|
|
4241
|
-
const slotBytes = toBytes(firstLevelSlot);
|
|
4242
|
-
const combined = new Uint8Array([...keyBytes, ...slotBytes]);
|
|
4243
|
-
return keccak256(combined);
|
|
4244
|
-
}
|
|
4245
|
-
var SubstrateChain = class {
|
|
4246
|
-
constructor(params) {
|
|
4247
|
-
this.params = params;
|
|
4248
|
-
}
|
|
3515
|
+
consensusStateId: ConsensusStateId,
|
|
4249
3516
|
/*
|
|
4250
|
-
*
|
|
3517
|
+
* Public key of the sender
|
|
4251
3518
|
*/
|
|
4252
|
-
|
|
3519
|
+
signer: Vector(u8)
|
|
3520
|
+
});
|
|
3521
|
+
var FraudProofMessage = Struct({
|
|
4253
3522
|
/*
|
|
4254
|
-
*
|
|
3523
|
+
* The first valid consensus proof
|
|
4255
3524
|
*/
|
|
4256
|
-
|
|
4257
|
-
|
|
4258
|
-
|
|
4259
|
-
spec: {
|
|
4260
|
-
nexus: {
|
|
4261
|
-
hasher: keccakAsU8a
|
|
4262
|
-
},
|
|
4263
|
-
gargantua: {
|
|
4264
|
-
hasher: keccakAsU8a
|
|
4265
|
-
}
|
|
4266
|
-
}
|
|
4267
|
-
} : {};
|
|
4268
|
-
this.api = await ApiPromise.create({
|
|
4269
|
-
provider: wsProvider,
|
|
4270
|
-
typesBundle
|
|
4271
|
-
});
|
|
4272
|
-
}
|
|
4273
|
-
/**
|
|
4274
|
-
* Disconnects the Substrate chain connection.
|
|
3525
|
+
proof1: Vector(u8),
|
|
3526
|
+
/*
|
|
3527
|
+
* The second valid consensus proof
|
|
4275
3528
|
*/
|
|
4276
|
-
|
|
4277
|
-
|
|
4278
|
-
|
|
4279
|
-
this.api = void 0;
|
|
4280
|
-
}
|
|
4281
|
-
}
|
|
4282
|
-
/**
|
|
4283
|
-
* Returns the storage key for a request receipt in the child trie
|
|
4284
|
-
* The request commitment is the key
|
|
4285
|
-
* @param key - The H256 hash key (as a 0x-prefixed hex string)
|
|
4286
|
-
* @returns The storage key as a hex string
|
|
3529
|
+
proof2: Vector(u8),
|
|
3530
|
+
/*
|
|
3531
|
+
* Consensus state Id
|
|
4287
3532
|
*/
|
|
4288
|
-
|
|
4289
|
-
|
|
4290
|
-
|
|
4291
|
-
|
|
4292
|
-
|
|
4293
|
-
/**
|
|
4294
|
-
* Returns the storage key for a request commitment in the child trie
|
|
4295
|
-
* The request commitment is the key
|
|
4296
|
-
* @param key - The H256 hash key (as a 0x-prefixed hex string)
|
|
4297
|
-
* @returns The storage key as a hex string
|
|
3533
|
+
consensusStateId: ConsensusStateId
|
|
3534
|
+
});
|
|
3535
|
+
var StateMachine = Enum({
|
|
3536
|
+
/*
|
|
3537
|
+
* Evm state machines
|
|
4298
3538
|
*/
|
|
4299
|
-
|
|
4300
|
-
|
|
4301
|
-
|
|
4302
|
-
return bytesToHex(new Uint8Array([...prefix, ...keyBytes]));
|
|
4303
|
-
}
|
|
4304
|
-
/**
|
|
4305
|
-
* Queries a request commitment from the ISMP child trie storage.
|
|
4306
|
-
* @param {HexString} commitment - The commitment hash to look up.
|
|
4307
|
-
* @returns {Promise<HexString | undefined>} The commitment data if found, undefined otherwise.
|
|
3539
|
+
Evm: u32,
|
|
3540
|
+
/*
|
|
3541
|
+
* Polkadot parachains
|
|
4308
3542
|
*/
|
|
4309
|
-
|
|
4310
|
-
|
|
4311
|
-
|
|
4312
|
-
const rpc = new RpcWebSocketClient();
|
|
4313
|
-
await rpc.connect(this.params.ws);
|
|
4314
|
-
const item = await rpc.call("childstate_getStorage", [prefix, key]);
|
|
4315
|
-
return item;
|
|
4316
|
-
}
|
|
4317
|
-
/**
|
|
4318
|
-
* Queries the request receipt.
|
|
4319
|
-
* @param {HexString} commitment - The commitment to query.
|
|
4320
|
-
* @returns {Promise<HexString | undefined>} The relayer address responsible for delivering the request.
|
|
3543
|
+
Polkadot: u32,
|
|
3544
|
+
/*
|
|
3545
|
+
* Kusama parachains
|
|
4321
3546
|
*/
|
|
4322
|
-
|
|
4323
|
-
|
|
4324
|
-
|
|
4325
|
-
const rpc = new RpcWebSocketClient();
|
|
4326
|
-
await rpc.connect(this.params.ws);
|
|
4327
|
-
const item = await rpc.call("childstate_getStorage", [prefix, key]);
|
|
4328
|
-
return item;
|
|
4329
|
-
}
|
|
4330
|
-
/**
|
|
4331
|
-
* Returns the current timestamp of the chain.
|
|
4332
|
-
* @returns {Promise<bigint>} The current timestamp.
|
|
3547
|
+
Kusama: u32,
|
|
3548
|
+
/*
|
|
3549
|
+
* Substrate-based standalone chain
|
|
4333
3550
|
*/
|
|
4334
|
-
|
|
4335
|
-
|
|
4336
|
-
|
|
4337
|
-
return BigInt(now.toJSON()) / BigInt(1e3);
|
|
4338
|
-
}
|
|
4339
|
-
/**
|
|
4340
|
-
* Queries the proof of the commitments.
|
|
4341
|
-
* @param {IMessage} message - The message to query.
|
|
4342
|
-
* @param {string} counterparty - The counterparty address.
|
|
4343
|
-
* @param {bigint} [at] - The block number to query at.
|
|
4344
|
-
* @returns {Promise<HexString>} The proof.
|
|
3551
|
+
Substrate: ConsensusStateId,
|
|
3552
|
+
/*
|
|
3553
|
+
* Tendermint chains
|
|
4345
3554
|
*/
|
|
4346
|
-
|
|
4347
|
-
|
|
4348
|
-
|
|
4349
|
-
|
|
4350
|
-
|
|
4351
|
-
return toHex(proof.proof);
|
|
4352
|
-
}
|
|
4353
|
-
if (isSubstrateChain(counterparty)) {
|
|
4354
|
-
const childTrieKeys = "Requests" in message ? message.Requests.map(requestCommitmentStorageKey) : message.Responses.map(responseCommitmentStorageKey);
|
|
4355
|
-
const proof = await rpc.call("ismp_queryChildTrieProof", [Number(at), childTrieKeys]);
|
|
4356
|
-
const basicProof = BasicProof.dec(toHex(proof.proof));
|
|
4357
|
-
const encoded = SubstrateStateProof.enc({
|
|
4358
|
-
tag: "OverlayProof",
|
|
4359
|
-
value: {
|
|
4360
|
-
hasher: {
|
|
4361
|
-
tag: this.params.hasher,
|
|
4362
|
-
value: void 0
|
|
4363
|
-
},
|
|
4364
|
-
storageProof: basicProof
|
|
4365
|
-
}
|
|
4366
|
-
});
|
|
4367
|
-
return toHex(encoded);
|
|
4368
|
-
}
|
|
4369
|
-
throw new Error(`Unsupported chain type for counterparty: ${counterparty}`);
|
|
4370
|
-
}
|
|
4371
|
-
/**
|
|
4372
|
-
* Submit an unsigned ISMP transaction to the chain. Resolves when the transaction is finalized.
|
|
4373
|
-
* @param message - The message to be submitted.
|
|
4374
|
-
* @returns A promise that resolves to an object containing the transaction hash, block hash, and block number.
|
|
3555
|
+
Tendermint: ConsensusStateId
|
|
3556
|
+
});
|
|
3557
|
+
var StateMachineId = Struct({
|
|
3558
|
+
/*
|
|
3559
|
+
* The state machine id
|
|
4375
3560
|
*/
|
|
4376
|
-
|
|
4377
|
-
|
|
4378
|
-
|
|
4379
|
-
const args = hexToBytes(this.encode(message)).slice(2);
|
|
4380
|
-
const tx = api.tx.ismp.handleUnsigned(args);
|
|
4381
|
-
return new Promise((resolve, reject) => {
|
|
4382
|
-
let unsub = () => {
|
|
4383
|
-
};
|
|
4384
|
-
tx.send(async ({ isInBlock, isFinalized, isError, dispatchError, txHash, status }) => {
|
|
4385
|
-
if (isFinalized || isInBlock) {
|
|
4386
|
-
unsub();
|
|
4387
|
-
const blockHash = isInBlock ? status.asInBlock.toHex() : status.asFinalized.toHex();
|
|
4388
|
-
const header = await api.rpc.chain.getHeader(blockHash);
|
|
4389
|
-
const apiAt = await api.at(blockHash);
|
|
4390
|
-
const timestamp = await apiAt.query.timestamp.now();
|
|
4391
|
-
resolve({
|
|
4392
|
-
transactionHash: txHash.toHex(),
|
|
4393
|
-
blockHash,
|
|
4394
|
-
blockNumber: header.number.toNumber(),
|
|
4395
|
-
timestamp: Number(timestamp.toJSON()) / 1e3
|
|
4396
|
-
});
|
|
4397
|
-
} else if (isError) {
|
|
4398
|
-
unsub();
|
|
4399
|
-
console.error("Unsigned transaction failed: ", dispatchError);
|
|
4400
|
-
reject(dispatchError);
|
|
4401
|
-
}
|
|
4402
|
-
}).then((unsubscribe) => {
|
|
4403
|
-
unsub = unsubscribe;
|
|
4404
|
-
}).catch(reject);
|
|
4405
|
-
});
|
|
4406
|
-
}
|
|
4407
|
-
/**
|
|
4408
|
-
* Query the state proof for a given set of keys at a specific block height.
|
|
4409
|
-
* @param at The block height to query the state proof at.
|
|
4410
|
-
* @param keys The keys to query the state proof for.
|
|
4411
|
-
* @returns The state proof as a hexadecimal string.
|
|
3561
|
+
id: StateMachine,
|
|
3562
|
+
/*
|
|
3563
|
+
* The consensus state id
|
|
4412
3564
|
*/
|
|
4413
|
-
|
|
4414
|
-
|
|
4415
|
-
|
|
4416
|
-
|
|
4417
|
-
|
|
4418
|
-
const basicProof = BasicProof.dec(toHex(proof.proof));
|
|
4419
|
-
const encoded = SubstrateStateProof.enc({
|
|
4420
|
-
tag: "OverlayProof",
|
|
4421
|
-
value: {
|
|
4422
|
-
hasher: {
|
|
4423
|
-
tag: this.params.hasher,
|
|
4424
|
-
value: void 0
|
|
4425
|
-
},
|
|
4426
|
-
storageProof: basicProof
|
|
4427
|
-
}
|
|
4428
|
-
});
|
|
4429
|
-
return toHex(encoded);
|
|
4430
|
-
}
|
|
4431
|
-
/**
|
|
4432
|
-
* Get the latest state machine height for a given state machine ID.
|
|
4433
|
-
* @param {StateMachineIdParams} stateMachineId - The state machine ID.
|
|
4434
|
-
* @returns {Promise<bigint>} The latest state machine height.
|
|
3565
|
+
consensusStateId: ConsensusStateId
|
|
3566
|
+
});
|
|
3567
|
+
var StateMachineHeight = Struct({
|
|
3568
|
+
/*
|
|
3569
|
+
* The state machine id
|
|
4435
3570
|
*/
|
|
4436
|
-
|
|
4437
|
-
|
|
4438
|
-
|
|
4439
|
-
return BigInt(latestHeight.toString());
|
|
4440
|
-
}
|
|
4441
|
-
/**
|
|
4442
|
-
* Get the state machine update time for a given state machine height.
|
|
4443
|
-
* @param {StateMachineHeight} stateMachineheight - The state machine height.
|
|
4444
|
-
* @returns {Promise<bigint>} The statemachine update time in seconds.
|
|
3571
|
+
id: StateMachineId,
|
|
3572
|
+
/*
|
|
3573
|
+
* The height of the state machine
|
|
4445
3574
|
*/
|
|
4446
|
-
|
|
4447
|
-
|
|
4448
|
-
|
|
4449
|
-
|
|
4450
|
-
|
|
4451
|
-
/**
|
|
4452
|
-
* Get the challenge period for a given state machine id.
|
|
4453
|
-
* @param {StateMachineIdParams} stateMachineId - The state machine ID.
|
|
4454
|
-
* @returns {Promise<bigint>} The challenge period in seconds.
|
|
3575
|
+
height: u64
|
|
3576
|
+
});
|
|
3577
|
+
var Proof = Struct({
|
|
3578
|
+
/*
|
|
3579
|
+
* The height of the state machine
|
|
4455
3580
|
*/
|
|
4456
|
-
|
|
4457
|
-
|
|
4458
|
-
|
|
4459
|
-
return BigInt(challengePeriod.toString());
|
|
4460
|
-
}
|
|
4461
|
-
/**
|
|
4462
|
-
* Encode an ISMP calldata for a substrate chain.
|
|
4463
|
-
* @param message The ISMP message to encode.
|
|
4464
|
-
* @returns The encoded message as a hexadecimal string.
|
|
3581
|
+
height: StateMachineHeight,
|
|
3582
|
+
/*
|
|
3583
|
+
* The proof
|
|
4465
3584
|
*/
|
|
4466
|
-
|
|
4467
|
-
|
|
4468
|
-
|
|
4469
|
-
|
|
4470
|
-
|
|
4471
|
-
}
|
|
4472
|
-
/**
|
|
4473
|
-
* Returns the index of a pallet by its name, by looking up the pallets in the runtime metadata.
|
|
4474
|
-
* @param {string} name - The name of the pallet.
|
|
4475
|
-
* @returns {number} The index of the pallet.
|
|
4476
|
-
*/
|
|
4477
|
-
getPalletIndex(name) {
|
|
4478
|
-
if (!this.api) throw new Error("API not initialized");
|
|
4479
|
-
const pallets = this.api.runtimeMetadata.asLatest.pallets.entries();
|
|
4480
|
-
for (const p of pallets) {
|
|
4481
|
-
if (p[1].name.toString() === name) {
|
|
4482
|
-
const index = p[1].index.toNumber();
|
|
4483
|
-
return index;
|
|
4484
|
-
}
|
|
4485
|
-
}
|
|
4486
|
-
throw new Error(`${name} not found in runtime`);
|
|
4487
|
-
}
|
|
4488
|
-
};
|
|
4489
|
-
function requestCommitmentStorageKey(key) {
|
|
4490
|
-
const prefix = new TextEncoder().encode("RequestCommitments");
|
|
4491
|
-
const keyBytes = hexToBytes(key);
|
|
4492
|
-
return Array.from(new Uint8Array([...prefix, ...keyBytes]));
|
|
4493
|
-
}
|
|
4494
|
-
function responseCommitmentStorageKey(key) {
|
|
4495
|
-
const prefix = new TextEncoder().encode("ResponseCommitments");
|
|
4496
|
-
const keyBytes = hexToBytes(key);
|
|
4497
|
-
return Array.from(new Uint8Array([...prefix, ...keyBytes]));
|
|
4498
|
-
}
|
|
4499
|
-
function convertStateMachineIdToEnum(id) {
|
|
4500
|
-
let [tag, value] = id.split("-");
|
|
4501
|
-
tag = capitalize(tag);
|
|
4502
|
-
if (["Evm", "Polkadot", "Kusama"].includes(tag)) {
|
|
4503
|
-
value = Number.parseInt(value);
|
|
4504
|
-
} else {
|
|
4505
|
-
value = Array.from(toBytes(value));
|
|
4506
|
-
}
|
|
4507
|
-
return { tag, value };
|
|
4508
|
-
}
|
|
4509
|
-
function convertIPostRequestToCodec(request) {
|
|
4510
|
-
return {
|
|
4511
|
-
tag: "Post",
|
|
4512
|
-
value: {
|
|
4513
|
-
source: convertStateMachineIdToEnum(request.source),
|
|
4514
|
-
dest: convertStateMachineIdToEnum(request.dest),
|
|
4515
|
-
from: Array.from(hexToBytes(request.from)),
|
|
4516
|
-
to: Array.from(hexToBytes(request.to)),
|
|
4517
|
-
nonce: request.nonce,
|
|
4518
|
-
body: Array.from(hexToBytes(request.body)),
|
|
4519
|
-
timeoutTimestamp: request.timeoutTimestamp
|
|
4520
|
-
}
|
|
4521
|
-
};
|
|
4522
|
-
}
|
|
4523
|
-
function encodeISMPMessage(message) {
|
|
4524
|
-
try {
|
|
4525
|
-
return match(message).with({ kind: "PostRequest" }, (message2) => {
|
|
4526
|
-
return Vector(Message).enc([
|
|
4527
|
-
{
|
|
4528
|
-
tag: "RequestMessage",
|
|
4529
|
-
value: {
|
|
4530
|
-
requests: message2.requests.map(
|
|
4531
|
-
(post_request) => convertIPostRequestToCodec(post_request).value
|
|
4532
|
-
),
|
|
4533
|
-
proof: {
|
|
4534
|
-
height: {
|
|
4535
|
-
height: message2.proof.height,
|
|
4536
|
-
id: {
|
|
4537
|
-
consensusStateId: Array.from(toBytes(message2.proof.consensusStateId)),
|
|
4538
|
-
id: convertStateMachineIdToEnum(message2.proof.stateMachine)
|
|
4539
|
-
}
|
|
4540
|
-
},
|
|
4541
|
-
proof: Array.from(hexToBytes(message2.proof.proof))
|
|
4542
|
-
},
|
|
4543
|
-
signer: Array.from(hexToBytes(message2.signer))
|
|
4544
|
-
}
|
|
4545
|
-
}
|
|
4546
|
-
]);
|
|
4547
|
-
}).with({ kind: "GetResponse" }, (message2) => {
|
|
4548
|
-
throw new Error("GetResponse is not yet supported on Substrate chains");
|
|
4549
|
-
}).with({ kind: "TimeoutPostRequest" }, (message2) => {
|
|
4550
|
-
return Vector(Message).enc([
|
|
4551
|
-
{
|
|
4552
|
-
tag: "TimeoutMessage",
|
|
4553
|
-
value: {
|
|
4554
|
-
tag: "Post",
|
|
4555
|
-
value: {
|
|
4556
|
-
requests: message2.requests.map((r) => convertIPostRequestToCodec(r)),
|
|
4557
|
-
proof: {
|
|
4558
|
-
height: {
|
|
4559
|
-
height: message2.proof.height,
|
|
4560
|
-
id: {
|
|
4561
|
-
consensusStateId: Array.from(toBytes(message2.proof.consensusStateId)),
|
|
4562
|
-
id: convertStateMachineIdToEnum(message2.proof.stateMachine)
|
|
4563
|
-
}
|
|
4564
|
-
},
|
|
4565
|
-
proof: Array.from(hexToBytes(message2.proof.proof))
|
|
4566
|
-
}
|
|
4567
|
-
}
|
|
4568
|
-
}
|
|
4569
|
-
}
|
|
4570
|
-
]);
|
|
4571
|
-
}).exhaustive();
|
|
4572
|
-
} catch (error) {
|
|
4573
|
-
throw new Error("Failed to encode ISMP message", { cause: error });
|
|
4574
|
-
}
|
|
4575
|
-
}
|
|
4576
|
-
|
|
4577
|
-
// src/chain.ts
|
|
4578
|
-
async function getChain(chainConfig) {
|
|
4579
|
-
if (isEvmChain(chainConfig.stateMachineId)) {
|
|
4580
|
-
const config = chainConfig;
|
|
4581
|
-
const chainId = Number.parseInt(chainConfig.stateMachineId.split("-")[1]);
|
|
4582
|
-
const evmChain = new EvmChain({
|
|
4583
|
-
chainId,
|
|
4584
|
-
url: config.rpcUrl,
|
|
4585
|
-
host: config.host
|
|
4586
|
-
});
|
|
4587
|
-
return evmChain;
|
|
4588
|
-
}
|
|
4589
|
-
if (isSubstrateChain(chainConfig.stateMachineId)) {
|
|
4590
|
-
const config = chainConfig;
|
|
4591
|
-
const substrateChain = new SubstrateChain({
|
|
4592
|
-
ws: config.wsUrl,
|
|
4593
|
-
hasher: config.hasher
|
|
4594
|
-
});
|
|
4595
|
-
await substrateChain.connect();
|
|
4596
|
-
return substrateChain;
|
|
4597
|
-
}
|
|
4598
|
-
throw new Error(`Unsupported chain: ${chainConfig.stateMachineId}`);
|
|
4599
|
-
}
|
|
4600
|
-
function getPeakPosByHeight(height) {
|
|
4601
|
-
return (1n << BigInt(height + 1)) - 2n;
|
|
4602
|
-
}
|
|
4603
|
-
function leftPeakHeightPos(mmrSize) {
|
|
4604
|
-
let height = 1;
|
|
4605
|
-
let prevPos = 0n;
|
|
4606
|
-
let pos = getPeakPosByHeight(height);
|
|
4607
|
-
while (pos < mmrSize) {
|
|
4608
|
-
height += 1;
|
|
4609
|
-
prevPos = pos;
|
|
4610
|
-
pos = getPeakPosByHeight(height);
|
|
4611
|
-
}
|
|
4612
|
-
return [height - 1, prevPos];
|
|
4613
|
-
}
|
|
4614
|
-
function getRightPeak(initialHeight, initialPos, mmrSize) {
|
|
4615
|
-
let height = initialHeight;
|
|
4616
|
-
let pos = initialPos;
|
|
4617
|
-
pos += siblingOffset(height);
|
|
4618
|
-
while (pos > mmrSize - 1n) {
|
|
4619
|
-
if (height === 0) {
|
|
4620
|
-
return null;
|
|
4621
|
-
}
|
|
4622
|
-
pos -= parentOffset(height - 1);
|
|
4623
|
-
height -= 1;
|
|
4624
|
-
}
|
|
4625
|
-
return [height, pos];
|
|
4626
|
-
}
|
|
4627
|
-
function getPeaks(mmrSize) {
|
|
4628
|
-
const positions = [];
|
|
4629
|
-
let [height, pos] = leftPeakHeightPos(mmrSize);
|
|
4630
|
-
positions.push(pos);
|
|
4631
|
-
while (height > 0) {
|
|
4632
|
-
const peak = getRightPeak(height, pos, mmrSize);
|
|
4633
|
-
if (!peak) break;
|
|
4634
|
-
[height, pos] = peak;
|
|
4635
|
-
positions.push(pos);
|
|
4636
|
-
}
|
|
4637
|
-
return positions;
|
|
4638
|
-
}
|
|
4639
|
-
function allOnes(num) {
|
|
4640
|
-
if (num === 0n) return false;
|
|
4641
|
-
return num.toString(2).split("").every((bit) => bit === "1");
|
|
4642
|
-
}
|
|
4643
|
-
function jumpLeft(pos) {
|
|
4644
|
-
const bitLength = pos.toString(2).length;
|
|
4645
|
-
const mostSignificantBits = 1n << BigInt(bitLength - 1);
|
|
4646
|
-
return pos - (mostSignificantBits - 1n);
|
|
4647
|
-
}
|
|
4648
|
-
function posHeightInTree(initialPos) {
|
|
4649
|
-
let pos = initialPos + 1n;
|
|
4650
|
-
while (!allOnes(pos)) {
|
|
4651
|
-
pos = jumpLeft(pos);
|
|
4652
|
-
}
|
|
4653
|
-
return pos.toString(2).length - 1;
|
|
4654
|
-
}
|
|
4655
|
-
function parentOffset(height) {
|
|
4656
|
-
return 2n << BigInt(height);
|
|
4657
|
-
}
|
|
4658
|
-
function siblingOffset(height) {
|
|
4659
|
-
return (2n << BigInt(height)) - 1n;
|
|
4660
|
-
}
|
|
4661
|
-
function takeWhileVec(v, p) {
|
|
4662
|
-
const index = v.findIndex((item) => !p(item));
|
|
4663
|
-
if (index === -1) {
|
|
4664
|
-
const result = [...v];
|
|
4665
|
-
v.length = 0;
|
|
4666
|
-
return result;
|
|
4667
|
-
}
|
|
4668
|
-
return v.splice(0, index);
|
|
4669
|
-
}
|
|
4670
|
-
function mmrPositionToKIndex(initialLeaves, mmrSize) {
|
|
4671
|
-
const leaves = [...initialLeaves];
|
|
4672
|
-
const peaks = getPeaks(mmrSize);
|
|
4673
|
-
const leavesWithKIndices = [];
|
|
4674
|
-
for (const peak of peaks) {
|
|
4675
|
-
const peakLeaves = takeWhileVec(leaves, (pos) => pos <= peak);
|
|
4676
|
-
if (peakLeaves.length > 0) {
|
|
4677
|
-
for (const pos of peakLeaves) {
|
|
4678
|
-
const height = posHeightInTree(peak);
|
|
4679
|
-
let index = 0n;
|
|
4680
|
-
let parentPos = peak;
|
|
4681
|
-
for (let h = height; h >= 1; h--) {
|
|
4682
|
-
const leftChild = parentPos - parentOffset(h - 1);
|
|
4683
|
-
const rightChild = leftChild + siblingOffset(h - 1);
|
|
4684
|
-
index *= 2n;
|
|
4685
|
-
if (leftChild >= pos) {
|
|
4686
|
-
parentPos = leftChild;
|
|
4687
|
-
} else {
|
|
4688
|
-
parentPos = rightChild;
|
|
4689
|
-
index += 1n;
|
|
4690
|
-
}
|
|
4691
|
-
}
|
|
4692
|
-
leavesWithKIndices.push([pos, index]);
|
|
4693
|
-
}
|
|
4694
|
-
}
|
|
4695
|
-
}
|
|
4696
|
-
return leavesWithKIndices;
|
|
4697
|
-
}
|
|
4698
|
-
function calculateMMRSize(numberOfLeaves) {
|
|
4699
|
-
const numberOfPeaks = numberOfLeaves.toString(2).split("1").length - 1;
|
|
4700
|
-
return 2n * numberOfLeaves - BigInt(numberOfPeaks);
|
|
4701
|
-
}
|
|
4702
|
-
async function generateRootWithProof(postRequest, treeSize) {
|
|
4703
|
-
const { generate_root_with_proof: generate_root_with_proof2 } = await load_ckb_mmr();
|
|
4704
|
-
const { commitment: hash, encodePacked: encodePacked3 } = postRequestCommitment(postRequest);
|
|
4705
|
-
const result = JSON.parse(generate_root_with_proof2(hexToBytes(encodePacked3), treeSize));
|
|
4706
|
-
const { root, proof, mmr_size, leaf_positions, keccak_hash_calldata } = result;
|
|
4707
|
-
if (keccak_hash_calldata !== hash) {
|
|
4708
|
-
console.log("keccak_hash", keccak_hash_calldata);
|
|
4709
|
-
console.log("hash", hash);
|
|
4710
|
-
throw new Error("Abi keccak hash mismatch");
|
|
4711
|
-
}
|
|
4712
|
-
const [[, kIndex]] = mmrPositionToKIndex(leaf_positions, BigInt(mmr_size));
|
|
4713
|
-
return {
|
|
4714
|
-
root,
|
|
4715
|
-
proof,
|
|
4716
|
-
index: treeSize - 1n,
|
|
4717
|
-
kIndex,
|
|
4718
|
-
treeSize,
|
|
4719
|
-
mmrSize: mmr_size
|
|
4720
|
-
};
|
|
4721
|
-
}
|
|
4722
|
-
async function load_ckb_mmr() {
|
|
4723
|
-
if (hasWindow) {
|
|
4724
|
-
const wasm2 = await Promise.resolve().then(() => (init_node(), node_exports));
|
|
4725
|
-
await wasm2.default();
|
|
4726
|
-
return wasm2;
|
|
4727
|
-
}
|
|
4728
|
-
if (isNode) {
|
|
4729
|
-
const wasm2 = await Promise.resolve().then(() => (init_node(), node_exports));
|
|
4730
|
-
return wasm2;
|
|
4731
|
-
}
|
|
4732
|
-
throw new Error(`SDK not setup for ${env}`);
|
|
4733
|
-
}
|
|
4734
|
-
async function __test() {
|
|
4735
|
-
const { generate_root_with_proof: generate_root_with_proof2 } = await load_ckb_mmr();
|
|
4736
|
-
return generate_root_with_proof2(new Uint8Array(), 120n);
|
|
4737
|
-
}
|
|
4738
|
-
var H256 = Vector(u8, 32);
|
|
4739
|
-
var EvmStateProof = Struct({
|
|
4740
|
-
/**
|
|
4741
|
-
* Proof of the contract state.
|
|
4742
|
-
*/
|
|
4743
|
-
contractProof: Vector(Vector(u8)),
|
|
4744
|
-
/**
|
|
4745
|
-
* Proof of the storage state.
|
|
4746
|
-
*/
|
|
4747
|
-
storageProof: Vector(Tuple(Vector(u8), Vector(Vector(u8))))
|
|
4748
|
-
});
|
|
4749
|
-
var SubstrateHashing = Enum({
|
|
4750
|
-
/* For chains that use keccak as their hashing algo */
|
|
4751
|
-
Keccak: _void,
|
|
4752
|
-
/* For chains that use blake2b as their hashing algo */
|
|
4753
|
-
Blake2: _void
|
|
4754
|
-
});
|
|
4755
|
-
var SubstrateStateMachineProof = Struct({
|
|
4756
|
-
/**
|
|
4757
|
-
* The hasher used to hash the state machine state.
|
|
4758
|
-
*/
|
|
4759
|
-
hasher: SubstrateHashing,
|
|
4760
|
-
/**
|
|
4761
|
-
* Proof of the state machine state.
|
|
4762
|
-
*/
|
|
4763
|
-
storageProof: Vector(Vector(u8))
|
|
4764
|
-
});
|
|
4765
|
-
var SubstrateStateProof = Enum({
|
|
4766
|
-
/*
|
|
4767
|
-
* Uses overlay root for verification
|
|
4768
|
-
*/
|
|
4769
|
-
OverlayProof: SubstrateStateMachineProof,
|
|
4770
|
-
/*
|
|
4771
|
-
* Uses state root for verification
|
|
4772
|
-
*/
|
|
4773
|
-
StateProof: SubstrateStateMachineProof
|
|
4774
|
-
});
|
|
4775
|
-
var BasicProof = Vector(Vector(u8));
|
|
4776
|
-
var LeafIndexAndPos = Struct({
|
|
4777
|
-
/*
|
|
4778
|
-
* Leaf index
|
|
4779
|
-
*/
|
|
4780
|
-
leafIndex: u64,
|
|
4781
|
-
/*
|
|
4782
|
-
* Leaf position in the MMR
|
|
4783
|
-
*/
|
|
4784
|
-
pos: u64
|
|
4785
|
-
});
|
|
4786
|
-
var MmrProof = Struct({
|
|
4787
|
-
/*
|
|
4788
|
-
* Proof of the leaf index and position.
|
|
4789
|
-
*/
|
|
4790
|
-
leafIndexAndPos: Vector(LeafIndexAndPos),
|
|
4791
|
-
/*
|
|
4792
|
-
* Proof of the leaf data.
|
|
4793
|
-
*/
|
|
4794
|
-
leafCount: u64,
|
|
4795
|
-
/*
|
|
4796
|
-
* Proof elements (hashes of siblings of inner nodes on the path to the leaf).
|
|
4797
|
-
*/
|
|
4798
|
-
items: Vector(H256)
|
|
4799
|
-
});
|
|
4800
|
-
var ConsensusStateId = Vector(u8, 4);
|
|
4801
|
-
var ConsensusMessage = Struct({
|
|
4802
|
-
/*
|
|
4803
|
-
* Consensus message data.
|
|
4804
|
-
*/
|
|
4805
|
-
consensusProof: Vector(u8),
|
|
4806
|
-
/*
|
|
4807
|
-
* Consensus state Id
|
|
4808
|
-
*/
|
|
4809
|
-
consensusStateId: ConsensusStateId,
|
|
4810
|
-
/*
|
|
4811
|
-
* Public key of the sender
|
|
4812
|
-
*/
|
|
4813
|
-
signer: Vector(u8)
|
|
4814
|
-
});
|
|
4815
|
-
var FraudProofMessage = Struct({
|
|
4816
|
-
/*
|
|
4817
|
-
* The first valid consensus proof
|
|
4818
|
-
*/
|
|
4819
|
-
proof1: Vector(u8),
|
|
4820
|
-
/*
|
|
4821
|
-
* The second valid consensus proof
|
|
4822
|
-
*/
|
|
4823
|
-
proof2: Vector(u8),
|
|
4824
|
-
/*
|
|
4825
|
-
* Consensus state Id
|
|
4826
|
-
*/
|
|
4827
|
-
consensusStateId: ConsensusStateId
|
|
4828
|
-
});
|
|
4829
|
-
var StateMachine = Enum({
|
|
4830
|
-
/*
|
|
4831
|
-
* Evm state machines
|
|
4832
|
-
*/
|
|
4833
|
-
Evm: u32,
|
|
4834
|
-
/*
|
|
4835
|
-
* Polkadot parachains
|
|
4836
|
-
*/
|
|
4837
|
-
Polkadot: u32,
|
|
4838
|
-
/*
|
|
4839
|
-
* Kusama parachains
|
|
4840
|
-
*/
|
|
4841
|
-
Kusama: u32,
|
|
4842
|
-
/*
|
|
4843
|
-
* Substrate-based standalone chain
|
|
4844
|
-
*/
|
|
4845
|
-
Substrate: ConsensusStateId,
|
|
4846
|
-
/*
|
|
4847
|
-
* Tendermint chains
|
|
4848
|
-
*/
|
|
4849
|
-
Tendermint: ConsensusStateId
|
|
4850
|
-
});
|
|
4851
|
-
var StateMachineId = Struct({
|
|
4852
|
-
/*
|
|
4853
|
-
* The state machine id
|
|
4854
|
-
*/
|
|
4855
|
-
id: StateMachine,
|
|
4856
|
-
/*
|
|
4857
|
-
* The consensus state id
|
|
4858
|
-
*/
|
|
4859
|
-
consensusStateId: ConsensusStateId
|
|
4860
|
-
});
|
|
4861
|
-
var StateMachineHeight = Struct({
|
|
4862
|
-
/*
|
|
4863
|
-
* The state machine id
|
|
4864
|
-
*/
|
|
4865
|
-
id: StateMachineId,
|
|
4866
|
-
/*
|
|
4867
|
-
* The height of the state machine
|
|
4868
|
-
*/
|
|
4869
|
-
height: u64
|
|
4870
|
-
});
|
|
4871
|
-
var Proof = Struct({
|
|
4872
|
-
/*
|
|
4873
|
-
* The height of the state machine
|
|
4874
|
-
*/
|
|
4875
|
-
height: StateMachineHeight,
|
|
4876
|
-
/*
|
|
4877
|
-
* The proof
|
|
4878
|
-
*/
|
|
4879
|
-
proof: Vector(u8)
|
|
4880
|
-
});
|
|
4881
|
-
var PostRequest = Struct({
|
|
4882
|
-
/*
|
|
4883
|
-
* The source state machine of this request.
|
|
3585
|
+
proof: Vector(u8)
|
|
3586
|
+
});
|
|
3587
|
+
var PostRequest = Struct({
|
|
3588
|
+
/*
|
|
3589
|
+
* The source state machine of this request.
|
|
4884
3590
|
*/
|
|
4885
3591
|
source: StateMachine,
|
|
4886
3592
|
/*
|
|
@@ -5052,474 +3758,1781 @@ var TimeoutMessage = Enum({
|
|
|
5052
3758
|
/*
|
|
5053
3759
|
* A non memership proof for POST responses
|
|
5054
3760
|
*/
|
|
5055
|
-
PostResponse: Struct({
|
|
5056
|
-
/*
|
|
5057
|
-
* Timed out responses
|
|
5058
|
-
*/
|
|
5059
|
-
responses: Vector(Response),
|
|
5060
|
-
/*
|
|
5061
|
-
* Membership batch proof for these responses
|
|
5062
|
-
*/
|
|
5063
|
-
proof: Proof
|
|
5064
|
-
}),
|
|
3761
|
+
PostResponse: Struct({
|
|
3762
|
+
/*
|
|
3763
|
+
* Timed out responses
|
|
3764
|
+
*/
|
|
3765
|
+
responses: Vector(Response),
|
|
3766
|
+
/*
|
|
3767
|
+
* Membership batch proof for these responses
|
|
3768
|
+
*/
|
|
3769
|
+
proof: Proof
|
|
3770
|
+
}),
|
|
3771
|
+
/*
|
|
3772
|
+
* There are no proofs for Get timeouts
|
|
3773
|
+
*/
|
|
3774
|
+
Get: Struct({
|
|
3775
|
+
/*
|
|
3776
|
+
* Timed out requests
|
|
3777
|
+
*/
|
|
3778
|
+
requests: Vector(Request)
|
|
3779
|
+
})
|
|
3780
|
+
});
|
|
3781
|
+
var Message = Enum({
|
|
3782
|
+
/*
|
|
3783
|
+
* A consensus update message
|
|
3784
|
+
*/
|
|
3785
|
+
ConsensusMessage,
|
|
3786
|
+
/*
|
|
3787
|
+
* A fraud proof message
|
|
3788
|
+
*/
|
|
3789
|
+
FraudProofMessage,
|
|
3790
|
+
/*
|
|
3791
|
+
* A request message
|
|
3792
|
+
*/
|
|
3793
|
+
RequestMessage,
|
|
3794
|
+
/*
|
|
3795
|
+
* A response message
|
|
3796
|
+
*/
|
|
3797
|
+
ResponseMessage,
|
|
3798
|
+
/*
|
|
3799
|
+
* A request timeout message
|
|
3800
|
+
*/
|
|
3801
|
+
TimeoutMessage
|
|
3802
|
+
});
|
|
3803
|
+
|
|
3804
|
+
// src/utils.ts
|
|
3805
|
+
var DEFAULT_POLL_INTERVAL = 5e3;
|
|
3806
|
+
var ADDRESS_ZERO = "0x0000000000000000000000000000000000000000";
|
|
3807
|
+
var MOCK_ADDRESS = "0x1234567890123456789012345678901234567890";
|
|
3808
|
+
var DUMMY_PRIVATE_KEY = "0x0000000000000000000000000000000000000000000000000000000000000000";
|
|
3809
|
+
function sleep(ms) {
|
|
3810
|
+
return new Promise((resolve) => setTimeout(resolve, ms || DEFAULT_POLL_INTERVAL));
|
|
3811
|
+
}
|
|
3812
|
+
async function waitForChallengePeriod(chain, stateMachineHeight) {
|
|
3813
|
+
const challengePeriod = await chain.challengePeriod(stateMachineHeight.id);
|
|
3814
|
+
if (challengePeriod === BigInt(0)) return;
|
|
3815
|
+
const updateTime = await chain.stateMachineUpdateTime(stateMachineHeight);
|
|
3816
|
+
let currentTimestamp = await chain.timestamp();
|
|
3817
|
+
let timeElapsed = currentTimestamp - updateTime;
|
|
3818
|
+
if (timeElapsed > challengePeriod) return;
|
|
3819
|
+
await sleep(Number(challengePeriod) * 1e3);
|
|
3820
|
+
while (timeElapsed <= challengePeriod) {
|
|
3821
|
+
const remainingTime = challengePeriod - timeElapsed;
|
|
3822
|
+
await sleep(Number(remainingTime) * 1e3);
|
|
3823
|
+
currentTimestamp = await chain.timestamp();
|
|
3824
|
+
timeElapsed = currentTimestamp - updateTime;
|
|
3825
|
+
}
|
|
3826
|
+
}
|
|
3827
|
+
function isEvmChain(stateMachineId) {
|
|
3828
|
+
return stateMachineId.startsWith("EVM");
|
|
3829
|
+
}
|
|
3830
|
+
function isSubstrateChain(stateMachineId) {
|
|
3831
|
+
return stateMachineId.startsWith("POLKADOT") || stateMachineId.startsWith("KUSAMA") || stateMachineId.startsWith("SUBSTRATE");
|
|
3832
|
+
}
|
|
3833
|
+
function parseStateMachineId(stateMachineId) {
|
|
3834
|
+
const [type, value] = stateMachineId.split("-");
|
|
3835
|
+
if (!type || !value) {
|
|
3836
|
+
throw new Error(
|
|
3837
|
+
`Invalid state machine ID format: ${stateMachineId}. Expected format like "EVM-97" or "SUBSTRATE-cere"`
|
|
3838
|
+
);
|
|
3839
|
+
}
|
|
3840
|
+
const stateId = {};
|
|
3841
|
+
switch (type.toUpperCase()) {
|
|
3842
|
+
case "EVM": {
|
|
3843
|
+
const evmChainId = Number.parseInt(value, 10);
|
|
3844
|
+
if (Number.isNaN(evmChainId)) {
|
|
3845
|
+
throw new Error(`Invalid EVM chain ID: ${value}. Expected a number.`);
|
|
3846
|
+
}
|
|
3847
|
+
stateId.Evm = evmChainId;
|
|
3848
|
+
break;
|
|
3849
|
+
}
|
|
3850
|
+
case "SUBSTRATE": {
|
|
3851
|
+
const bytes = Buffer.from(value, "utf8");
|
|
3852
|
+
stateId.Substrate = `0x${bytes.toString("hex")}`;
|
|
3853
|
+
break;
|
|
3854
|
+
}
|
|
3855
|
+
case "POLKADOT": {
|
|
3856
|
+
const polkadotChainId = Number.parseInt(value, 10);
|
|
3857
|
+
if (Number.isNaN(polkadotChainId)) {
|
|
3858
|
+
throw new Error(`Invalid Polkadot chain ID: ${value}. Expected a number.`);
|
|
3859
|
+
}
|
|
3860
|
+
stateId.Polkadot = polkadotChainId;
|
|
3861
|
+
break;
|
|
3862
|
+
}
|
|
3863
|
+
case "KUSAMA": {
|
|
3864
|
+
const kusamaChainId = Number.parseInt(value, 10);
|
|
3865
|
+
if (Number.isNaN(kusamaChainId)) {
|
|
3866
|
+
throw new Error(`Invalid Kusama chain ID: ${value}. Expected a number.`);
|
|
3867
|
+
}
|
|
3868
|
+
stateId.Kusama = kusamaChainId;
|
|
3869
|
+
break;
|
|
3870
|
+
}
|
|
3871
|
+
default:
|
|
3872
|
+
throw new Error(`Unsupported chain type: ${type}. Expected one of: EVM, SUBSTRATE, POLKADOT, KUSAMA.`);
|
|
3873
|
+
}
|
|
3874
|
+
return { stateId };
|
|
3875
|
+
}
|
|
3876
|
+
function postRequestCommitment(post) {
|
|
3877
|
+
const data = encodePacked(
|
|
3878
|
+
["bytes", "bytes", "uint64", "uint64", "bytes", "bytes", "bytes"],
|
|
3879
|
+
[toHex(post.source), toHex(post.dest), post.nonce, post.timeoutTimestamp, post.from, post.to, post.body]
|
|
3880
|
+
);
|
|
3881
|
+
return {
|
|
3882
|
+
commitment: keccak256(data),
|
|
3883
|
+
encodePacked: data
|
|
3884
|
+
};
|
|
3885
|
+
}
|
|
3886
|
+
function orderCommitment(order) {
|
|
3887
|
+
const encodedOrder = encodeAbiParameters(
|
|
3888
|
+
[
|
|
3889
|
+
{
|
|
3890
|
+
name: "order",
|
|
3891
|
+
type: "tuple",
|
|
3892
|
+
components: [
|
|
3893
|
+
{ name: "user", type: "bytes32" },
|
|
3894
|
+
{ name: "sourceChain", type: "bytes" },
|
|
3895
|
+
{ name: "destChain", type: "bytes" },
|
|
3896
|
+
{ name: "deadline", type: "uint256" },
|
|
3897
|
+
{ name: "nonce", type: "uint256" },
|
|
3898
|
+
{ name: "fees", type: "uint256" },
|
|
3899
|
+
{
|
|
3900
|
+
name: "outputs",
|
|
3901
|
+
type: "tuple[]",
|
|
3902
|
+
components: [
|
|
3903
|
+
{ name: "token", type: "bytes32" },
|
|
3904
|
+
{ name: "amount", type: "uint256" },
|
|
3905
|
+
{ name: "beneficiary", type: "bytes32" }
|
|
3906
|
+
]
|
|
3907
|
+
},
|
|
3908
|
+
{
|
|
3909
|
+
name: "inputs",
|
|
3910
|
+
type: "tuple[]",
|
|
3911
|
+
components: [
|
|
3912
|
+
{ name: "token", type: "bytes32" },
|
|
3913
|
+
{ name: "amount", type: "uint256" }
|
|
3914
|
+
]
|
|
3915
|
+
},
|
|
3916
|
+
{ name: "callData", type: "bytes" }
|
|
3917
|
+
]
|
|
3918
|
+
}
|
|
3919
|
+
],
|
|
3920
|
+
[
|
|
3921
|
+
{
|
|
3922
|
+
user: order.user,
|
|
3923
|
+
sourceChain: order.sourceChain.startsWith("0x") ? order.sourceChain : toHex(order.sourceChain),
|
|
3924
|
+
destChain: order.destChain.startsWith("0x") ? order.destChain : toHex(order.destChain),
|
|
3925
|
+
deadline: order.deadline,
|
|
3926
|
+
nonce: order.nonce,
|
|
3927
|
+
fees: order.fees,
|
|
3928
|
+
outputs: order.outputs,
|
|
3929
|
+
inputs: order.inputs,
|
|
3930
|
+
callData: order.callData
|
|
3931
|
+
}
|
|
3932
|
+
]
|
|
3933
|
+
);
|
|
3934
|
+
return keccak256(encodedOrder);
|
|
3935
|
+
}
|
|
3936
|
+
function bytes32ToBytes20(bytes32Address) {
|
|
3937
|
+
if (bytes32Address === ADDRESS_ZERO) {
|
|
3938
|
+
return ADDRESS_ZERO;
|
|
3939
|
+
}
|
|
3940
|
+
const bytes = hexToBytes(bytes32Address);
|
|
3941
|
+
const addressBytes = bytes.slice(12);
|
|
3942
|
+
return bytesToHex(addressBytes);
|
|
3943
|
+
}
|
|
3944
|
+
function bytes20ToBytes32(bytes20Address) {
|
|
3945
|
+
return `0x${bytes20Address.slice(2).padStart(64, "0")}`;
|
|
3946
|
+
}
|
|
3947
|
+
function hexToString(hex) {
|
|
3948
|
+
const hexWithoutPrefix = hex.startsWith("0x") ? hex.slice(2) : hex;
|
|
3949
|
+
const bytes = new Uint8Array(hexWithoutPrefix.length / 2);
|
|
3950
|
+
for (let i = 0; i < hexWithoutPrefix.length; i += 2) {
|
|
3951
|
+
bytes[i / 2] = Number.parseInt(hexWithoutPrefix.slice(i, i + 2), 16);
|
|
3952
|
+
}
|
|
3953
|
+
return new TextDecoder().decode(bytes);
|
|
3954
|
+
}
|
|
3955
|
+
var DEFAULT_LOGGER = createConsola({
|
|
3956
|
+
level: LogLevels.silent
|
|
3957
|
+
});
|
|
3958
|
+
async function retryPromise(operation, retryConfig) {
|
|
3959
|
+
const { logger = DEFAULT_LOGGER, logMessage = "Retry operation failed" } = retryConfig;
|
|
3960
|
+
let lastError;
|
|
3961
|
+
for (let i = 0; i < retryConfig.maxRetries; i++) {
|
|
3962
|
+
try {
|
|
3963
|
+
return await operation();
|
|
3964
|
+
} catch (error) {
|
|
3965
|
+
logger.trace(`Retrying(${i}) > ${logMessage}`);
|
|
3966
|
+
lastError = error;
|
|
3967
|
+
await new Promise((resolve) => setTimeout(resolve, retryConfig.backoffMs * 2 ** i));
|
|
3968
|
+
}
|
|
3969
|
+
}
|
|
3970
|
+
throw lastError;
|
|
3971
|
+
}
|
|
3972
|
+
function getRequestCommitment(get) {
|
|
3973
|
+
const keysEncoding = "0x".concat(get.keys.map((key) => key.slice(2)).join(""));
|
|
3974
|
+
return keccak256(
|
|
3975
|
+
encodePacked(
|
|
3976
|
+
["bytes", "bytes", "uint64", "uint64", "uint64", "bytes", "bytes", "bytes"],
|
|
3977
|
+
[
|
|
3978
|
+
toHex(get.source),
|
|
3979
|
+
toHex(get.dest),
|
|
3980
|
+
get.nonce,
|
|
3981
|
+
get.height,
|
|
3982
|
+
get.timeoutTimestamp,
|
|
3983
|
+
get.from,
|
|
3984
|
+
keysEncoding,
|
|
3985
|
+
get.context
|
|
3986
|
+
]
|
|
3987
|
+
)
|
|
3988
|
+
);
|
|
3989
|
+
}
|
|
3990
|
+
var REQUEST_STATUS_WEIGHTS = {
|
|
3991
|
+
[RequestStatus.SOURCE]: 0,
|
|
3992
|
+
[RequestStatus.SOURCE_FINALIZED]: 1,
|
|
3993
|
+
[RequestStatus.HYPERBRIDGE_DELIVERED]: 2,
|
|
3994
|
+
[RequestStatus.HYPERBRIDGE_FINALIZED]: 3,
|
|
3995
|
+
[RequestStatus.DESTINATION]: 4,
|
|
3996
|
+
[RequestStatus.HYPERBRIDGE_TIMED_OUT]: 5,
|
|
3997
|
+
[RequestStatus.TIMED_OUT]: 6
|
|
3998
|
+
};
|
|
3999
|
+
var TIMEOUT_STATUS_WEIGHTS = {
|
|
4000
|
+
[TimeoutStatus.PENDING_TIMEOUT]: 1,
|
|
4001
|
+
[TimeoutStatus.DESTINATION_FINALIZED_TIMEOUT]: 2,
|
|
4002
|
+
[TimeoutStatus.HYPERBRIDGE_TIMED_OUT]: 3,
|
|
4003
|
+
[TimeoutStatus.HYPERBRIDGE_FINALIZED_TIMEOUT]: 4,
|
|
4004
|
+
[TimeoutStatus.TIMED_OUT]: 5
|
|
4005
|
+
};
|
|
4006
|
+
var COMBINED_STATUS_WEIGHTS = {
|
|
4007
|
+
[RequestStatus.SOURCE]: 0,
|
|
4008
|
+
[RequestStatus.SOURCE_FINALIZED]: 1,
|
|
4009
|
+
[RequestStatus.HYPERBRIDGE_DELIVERED]: 2,
|
|
4010
|
+
[RequestStatus.HYPERBRIDGE_FINALIZED]: 3,
|
|
4011
|
+
[RequestStatus.DESTINATION]: 4,
|
|
4012
|
+
[TimeoutStatus.PENDING_TIMEOUT]: 5,
|
|
4013
|
+
[TimeoutStatus.DESTINATION_FINALIZED_TIMEOUT]: 6,
|
|
4014
|
+
[TimeoutStatus.HYPERBRIDGE_TIMED_OUT]: 7,
|
|
4015
|
+
[TimeoutStatus.HYPERBRIDGE_FINALIZED_TIMEOUT]: 8,
|
|
4016
|
+
[TimeoutStatus.TIMED_OUT]: 9
|
|
4017
|
+
};
|
|
4018
|
+
async function estimateGasForPost(params) {
|
|
4019
|
+
const hostParams = await params.sourceClient.readContract({
|
|
4020
|
+
address: params.hostAddress,
|
|
4021
|
+
abi: evmHost_default.ABI,
|
|
4022
|
+
functionName: "hostParams"
|
|
4023
|
+
});
|
|
4024
|
+
const { root, proof, index, kIndex, treeSize } = await generateRootWithProof(params.postRequest, 2n ** 10n);
|
|
4025
|
+
const latestStateMachineHeight = params.hostLatestStateMachineHeight;
|
|
4026
|
+
const overlayRootSlot = getStateCommitmentFieldSlot(
|
|
4027
|
+
BigInt(4009n),
|
|
4028
|
+
// Hyperbridge chain id
|
|
4029
|
+
latestStateMachineHeight,
|
|
4030
|
+
// Hyperbridge chain height
|
|
4031
|
+
1
|
|
4032
|
+
// For overlayRoot
|
|
4033
|
+
);
|
|
4034
|
+
const postParams = {
|
|
4035
|
+
height: {
|
|
4036
|
+
stateMachineId: BigInt(4009n),
|
|
4037
|
+
height: latestStateMachineHeight
|
|
4038
|
+
},
|
|
4039
|
+
multiproof: proof,
|
|
4040
|
+
leafCount: treeSize
|
|
4041
|
+
};
|
|
4042
|
+
const call_data = [
|
|
4043
|
+
params.hostAddress,
|
|
4044
|
+
{
|
|
4045
|
+
proof: postParams,
|
|
4046
|
+
requests: [
|
|
4047
|
+
{
|
|
4048
|
+
request: {
|
|
4049
|
+
...params.postRequest,
|
|
4050
|
+
source: toHex(params.postRequest.source),
|
|
4051
|
+
dest: toHex(params.postRequest.dest)
|
|
4052
|
+
},
|
|
4053
|
+
index,
|
|
4054
|
+
kIndex
|
|
4055
|
+
}
|
|
4056
|
+
]
|
|
4057
|
+
}
|
|
4058
|
+
];
|
|
4059
|
+
const gas_fee = await params.sourceClient.estimateContractGas({
|
|
4060
|
+
address: hostParams.handler,
|
|
4061
|
+
abi: handler_default.ABI,
|
|
4062
|
+
functionName: "handlePostRequests",
|
|
4063
|
+
args: call_data,
|
|
4064
|
+
stateOverride: [
|
|
4065
|
+
{
|
|
4066
|
+
address: params.hostAddress,
|
|
4067
|
+
stateDiff: [
|
|
4068
|
+
{
|
|
4069
|
+
slot: overlayRootSlot,
|
|
4070
|
+
value: root
|
|
4071
|
+
}
|
|
4072
|
+
]
|
|
4073
|
+
}
|
|
4074
|
+
]
|
|
4075
|
+
});
|
|
4076
|
+
return { gas_fee, call_data };
|
|
4077
|
+
}
|
|
4078
|
+
function constructRedeemEscrowRequestBody(order, beneficiary) {
|
|
4079
|
+
const commitment = order.id;
|
|
4080
|
+
const inputs = order.inputs;
|
|
4081
|
+
const requestKind = encodePacked(["uint8"], [0 /* RedeemEscrow */]);
|
|
4082
|
+
const requestBody = {
|
|
4083
|
+
commitment,
|
|
4084
|
+
beneficiary: bytes20ToBytes32(beneficiary),
|
|
4085
|
+
tokens: inputs
|
|
4086
|
+
};
|
|
4087
|
+
const encodedRequestBody = encodeAbiParameters(
|
|
4088
|
+
[
|
|
4089
|
+
{
|
|
4090
|
+
name: "requestBody",
|
|
4091
|
+
type: "tuple",
|
|
4092
|
+
components: [
|
|
4093
|
+
{ name: "commitment", type: "bytes32" },
|
|
4094
|
+
{ name: "beneficiary", type: "bytes32" },
|
|
4095
|
+
{
|
|
4096
|
+
name: "tokens",
|
|
4097
|
+
type: "tuple[]",
|
|
4098
|
+
components: [
|
|
4099
|
+
{ name: "token", type: "bytes32" },
|
|
4100
|
+
{ name: "amount", type: "uint256" }
|
|
4101
|
+
]
|
|
4102
|
+
}
|
|
4103
|
+
]
|
|
4104
|
+
}
|
|
4105
|
+
],
|
|
4106
|
+
[requestBody]
|
|
4107
|
+
);
|
|
4108
|
+
return concatHex([requestKind, encodedRequestBody]);
|
|
4109
|
+
}
|
|
4110
|
+
var dateStringtoTimestamp = (date) => {
|
|
4111
|
+
if (!date.endsWith("Z")) {
|
|
4112
|
+
date = `${date}Z`;
|
|
4113
|
+
}
|
|
4114
|
+
return new Date(date).getTime();
|
|
4115
|
+
};
|
|
4116
|
+
function mapTestnetToMainnet(identifier) {
|
|
4117
|
+
identifier = identifier.toLowerCase();
|
|
4118
|
+
switch (identifier) {
|
|
4119
|
+
case "bnb":
|
|
4120
|
+
return "wbnb";
|
|
4121
|
+
case "eth":
|
|
4122
|
+
return "weth";
|
|
4123
|
+
case "tbnb":
|
|
4124
|
+
return "wbnb";
|
|
4125
|
+
case "0xc043f483373072f7f27420d6e7d7ad269c018e18".toLowerCase():
|
|
4126
|
+
return "dai";
|
|
4127
|
+
case "0xae13d989dac2f0debff460ac112a837c89baa7cd".toLowerCase():
|
|
4128
|
+
return "wbnb";
|
|
4129
|
+
case "0x1938165569A5463327fb206bE06d8D9253aa06b7".toLowerCase():
|
|
4130
|
+
return "dai";
|
|
4131
|
+
case "0xC625ec7D30A4b1AAEfb1304610CdAcD0d606aC92".toLowerCase():
|
|
4132
|
+
return "dai";
|
|
4133
|
+
case "0x50B1d3c7c073c9caa1Ef207365A2c9C976bD70b9".toLowerCase():
|
|
4134
|
+
return "dai";
|
|
4135
|
+
case "0xa801da100bf16d07f668f4a49e1f71fc54d05177".toLowerCase():
|
|
4136
|
+
return "dai";
|
|
4137
|
+
default:
|
|
4138
|
+
return identifier;
|
|
4139
|
+
}
|
|
4140
|
+
}
|
|
4141
|
+
async function fetchTokenUsdPrice(identifier) {
|
|
4142
|
+
try {
|
|
4143
|
+
const coinGeckoPrice = await fetchFromCoinGecko(identifier);
|
|
4144
|
+
return coinGeckoPrice;
|
|
4145
|
+
} catch (error) {
|
|
4146
|
+
try {
|
|
4147
|
+
const defillamaPrice = await fetchFromDefillama(identifier);
|
|
4148
|
+
return defillamaPrice;
|
|
4149
|
+
} catch (fallbackError) {
|
|
4150
|
+
console.log(
|
|
4151
|
+
`Both APIs failed for ${identifier}. CoinGecko: ${error}, Defillama: ${fallbackError}. Returning 1`
|
|
4152
|
+
);
|
|
4153
|
+
return 1;
|
|
4154
|
+
}
|
|
4155
|
+
}
|
|
4156
|
+
}
|
|
4157
|
+
async function fetchFromCoinGecko(identifier) {
|
|
4158
|
+
const mappedIdentifier = mapTestnetToMainnet(identifier);
|
|
4159
|
+
const url = mappedIdentifier.startsWith("0x") ? `https://api.coingecko.com/api/v3/simple/token_price/ethereum?contract_addresses=${mappedIdentifier}&vs_currencies=usd` : `https://api.coingecko.com/api/v3/simple/price?ids=${mappedIdentifier}&vs_currencies=usd`;
|
|
4160
|
+
const response = await fetch(url);
|
|
4161
|
+
if (!response.ok) {
|
|
4162
|
+
throw new Error(`CoinGecko API error: ${response.status} ${response.statusText}`);
|
|
4163
|
+
}
|
|
4164
|
+
const data = await response.json();
|
|
4165
|
+
const key = mappedIdentifier.toLowerCase();
|
|
4166
|
+
if (!data[key]?.usd) {
|
|
4167
|
+
throw new Error(`Price not found for token: ${mappedIdentifier}`);
|
|
4168
|
+
}
|
|
4169
|
+
return data[key].usd;
|
|
4170
|
+
}
|
|
4171
|
+
async function fetchFromDefillama(identifier) {
|
|
4172
|
+
const mappedIdentifier = mapTestnetToMainnet(identifier);
|
|
4173
|
+
const coinId = mappedIdentifier.startsWith("0x") ? `ethereum:${mappedIdentifier}` : `coingecko:${mappedIdentifier}`;
|
|
4174
|
+
const url = `https://coins.llama.fi/prices/current/${coinId}`;
|
|
4175
|
+
const response = await fetch(url);
|
|
4176
|
+
if (!response.ok) {
|
|
4177
|
+
throw new Error(`Defillama API error: ${response.status} ${response.statusText}`);
|
|
4178
|
+
}
|
|
4179
|
+
const data = await response.json();
|
|
4180
|
+
const price = data.coins?.[coinId]?.price;
|
|
4181
|
+
if (!price && price !== 0) {
|
|
4182
|
+
throw new Error(`Price not found for token: ${mappedIdentifier}`);
|
|
4183
|
+
}
|
|
4184
|
+
return price;
|
|
4185
|
+
}
|
|
4186
|
+
var ERC20Method = /* @__PURE__ */ ((ERC20Method2) => {
|
|
4187
|
+
ERC20Method2["BALANCE_OF"] = "0x70a08231";
|
|
4188
|
+
ERC20Method2["ALLOWANCE"] = "0xdd62ed3e";
|
|
4189
|
+
return ERC20Method2;
|
|
4190
|
+
})(ERC20Method || {});
|
|
4191
|
+
async function getStorageSlot(client, contractAddress, data) {
|
|
4192
|
+
const traceCallClient = client.extend((client2) => ({
|
|
4193
|
+
async traceCall(args) {
|
|
4194
|
+
return client2.request({
|
|
4195
|
+
// @ts-ignore
|
|
4196
|
+
method: "debug_traceCall",
|
|
4197
|
+
// @ts-ignore
|
|
4198
|
+
params: [args, "latest", {}]
|
|
4199
|
+
});
|
|
4200
|
+
}
|
|
4201
|
+
}));
|
|
4202
|
+
const response = await traceCallClient.traceCall({
|
|
4203
|
+
to: contractAddress,
|
|
4204
|
+
data
|
|
4205
|
+
});
|
|
4206
|
+
const methodSignature = data.slice(0, 10);
|
|
4207
|
+
const logs = response.structLogs;
|
|
4208
|
+
for (let i = logs.length - 1; i >= 0; i--) {
|
|
4209
|
+
const log = logs[i];
|
|
4210
|
+
if (log.op === "SLOAD" && log.stack?.length >= 3) {
|
|
4211
|
+
const sigHash = log.stack[0];
|
|
4212
|
+
const slotHex = log.stack[log.stack.length - 1];
|
|
4213
|
+
if (sigHash === methodSignature && slotHex.length === 66) {
|
|
4214
|
+
return slotHex;
|
|
4215
|
+
}
|
|
4216
|
+
}
|
|
4217
|
+
}
|
|
4218
|
+
throw new Error(`Storage slot not found for data: ${methodSignature}`);
|
|
4219
|
+
}
|
|
4220
|
+
function adjustFeeDecimals(feeInFeeToken, fromDecimals, toDecimals) {
|
|
4221
|
+
if (fromDecimals === toDecimals) return feeInFeeToken;
|
|
4222
|
+
if (fromDecimals < toDecimals) {
|
|
4223
|
+
const scaleFactor = BigInt(10 ** (toDecimals - fromDecimals));
|
|
4224
|
+
return feeInFeeToken * scaleFactor;
|
|
4225
|
+
} else {
|
|
4226
|
+
const scaleFactor = BigInt(10 ** (fromDecimals - toDecimals));
|
|
4227
|
+
return (feeInFeeToken + scaleFactor - 1n) / scaleFactor;
|
|
4228
|
+
}
|
|
4229
|
+
}
|
|
4230
|
+
|
|
4231
|
+
// src/utils/exceptions.ts
|
|
4232
|
+
var AbortSignalInternal = class _AbortSignalInternal extends Error {
|
|
4233
|
+
constructor(message) {
|
|
4234
|
+
super();
|
|
4235
|
+
this.name = "Hyperbridge/SDK/AbortSignalInternal";
|
|
4236
|
+
this.message = message;
|
|
4237
|
+
}
|
|
4238
|
+
static isError(error) {
|
|
4239
|
+
return error instanceof _AbortSignalInternal;
|
|
4240
|
+
}
|
|
4241
|
+
};
|
|
4242
|
+
var ExpectedError = class _ExpectedError extends Error {
|
|
4243
|
+
constructor(message) {
|
|
4244
|
+
super();
|
|
4245
|
+
this.name = "Hyperbridge/SDK/ExpectedError";
|
|
4246
|
+
this.message = message;
|
|
4247
|
+
}
|
|
4248
|
+
static isError(error) {
|
|
4249
|
+
return error instanceof _ExpectedError;
|
|
4250
|
+
}
|
|
4251
|
+
};
|
|
4252
|
+
var Chains = /* @__PURE__ */ ((Chains2) => {
|
|
4253
|
+
Chains2["BSC_CHAPEL"] = "EVM-97";
|
|
4254
|
+
Chains2["GNOSIS_CHIADO"] = "EVM-10200";
|
|
4255
|
+
Chains2["HYPERBRIDGE_GARGANTUA"] = "KUSAMA-4009";
|
|
4256
|
+
Chains2["SEPOLIA"] = "EVM-11155111";
|
|
4257
|
+
Chains2["MAINNET"] = "EVM-1";
|
|
4258
|
+
Chains2["BSC_MAINNET"] = "EVM-56";
|
|
4259
|
+
return Chains2;
|
|
4260
|
+
})(Chains || {});
|
|
4261
|
+
var chainIds = {
|
|
4262
|
+
["EVM-97" /* BSC_CHAPEL */]: 97,
|
|
4263
|
+
["EVM-10200" /* GNOSIS_CHIADO */]: 10200,
|
|
4264
|
+
["KUSAMA-4009" /* HYPERBRIDGE_GARGANTUA */]: 4009,
|
|
4265
|
+
["EVM-11155111" /* SEPOLIA */]: 11155111,
|
|
4266
|
+
["EVM-1" /* MAINNET */]: 1,
|
|
4267
|
+
["EVM-56" /* BSC_MAINNET */]: 56
|
|
4268
|
+
};
|
|
4269
|
+
var viemChains = {
|
|
4270
|
+
"97": bscTestnet,
|
|
4271
|
+
"10200": gnosisChiado,
|
|
4272
|
+
"11155111": sepolia,
|
|
4273
|
+
"1": mainnet,
|
|
4274
|
+
"56": bsc
|
|
4275
|
+
};
|
|
4276
|
+
var WrappedNativeDecimals = {
|
|
4277
|
+
["EVM-97" /* BSC_CHAPEL */]: 18,
|
|
4278
|
+
["EVM-10200" /* GNOSIS_CHIADO */]: 18,
|
|
4279
|
+
["EVM-11155111" /* SEPOLIA */]: 18,
|
|
4280
|
+
["EVM-1" /* MAINNET */]: 18,
|
|
4281
|
+
["EVM-56" /* BSC_MAINNET */]: 18
|
|
4282
|
+
};
|
|
4283
|
+
var assets = {
|
|
4284
|
+
["EVM-97" /* BSC_CHAPEL */]: {
|
|
4285
|
+
WETH: "0xae13d989dac2f0debff460ac112a837c89baa7cd".toLowerCase(),
|
|
4286
|
+
DAI: "0x1938165569A5463327fb206bE06d8D9253aa06b7".toLowerCase(),
|
|
4287
|
+
USDC: "0xC625ec7D30A4b1AAEfb1304610CdAcD0d606aC92".toLowerCase(),
|
|
4288
|
+
USDT: "0xc043f483373072f7f27420d6e7d7ad269c018e18".toLowerCase()
|
|
4289
|
+
},
|
|
4290
|
+
["EVM-10200" /* GNOSIS_CHIADO */]: {
|
|
4291
|
+
WETH: "0x0000000000000000000000000000000000000000".toLowerCase(),
|
|
4292
|
+
DAI: "0x50B1d3c7c073c9caa1Ef207365A2c9C976bD70b9".toLowerCase(),
|
|
4293
|
+
USDC: "0x0000000000000000000000000000000000000000".toLowerCase(),
|
|
4294
|
+
USDT: "0x0000000000000000000000000000000000000000".toLowerCase()
|
|
4295
|
+
},
|
|
4296
|
+
["EVM-11155111" /* SEPOLIA */]: {
|
|
4297
|
+
WETH: "0x7b79995e5f793A07Bc00c21412e50Ecae098E7f9".toLowerCase(),
|
|
4298
|
+
USDC: "0x0000000000000000000000000000000000000000".toLowerCase(),
|
|
4299
|
+
USDT: "0x0000000000000000000000000000000000000000".toLowerCase(),
|
|
4300
|
+
DAI: "0x0000000000000000000000000000000000000000".toLowerCase()
|
|
4301
|
+
},
|
|
4302
|
+
["EVM-1" /* MAINNET */]: {
|
|
4303
|
+
WETH: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2".toLowerCase(),
|
|
4304
|
+
DAI: "0x6B175474E89094C44Da98b954EedeAC495271d0F".toLowerCase(),
|
|
4305
|
+
USDC: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48".toLowerCase(),
|
|
4306
|
+
USDT: "0xdAC17F958D2ee523a2206206994597C13D831ec7".toLowerCase()
|
|
4307
|
+
},
|
|
4308
|
+
["EVM-56" /* BSC_MAINNET */]: {
|
|
4309
|
+
WETH: "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c".toLowerCase(),
|
|
4310
|
+
DAI: "0x1AF3F329e8BE154074D8769D1FFa4eE058B1DBc3".toLowerCase(),
|
|
4311
|
+
USDC: "0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d".toLowerCase(),
|
|
4312
|
+
USDT: "0x55d398326f99059fF775485246999027B3197955".toLowerCase()
|
|
4313
|
+
}
|
|
4314
|
+
};
|
|
4315
|
+
var addresses = {
|
|
4316
|
+
IntentGateway: {
|
|
4317
|
+
["EVM-97" /* BSC_CHAPEL */]: "0xb6C27F4beF379d0b5e2fe3Bb36c248D6B71f91A6",
|
|
4318
|
+
["EVM-10200" /* GNOSIS_CHIADO */]: "0xb6C27F4beF379d0b5e2fe3Bb36c248D6B71f91A6",
|
|
4319
|
+
["EVM-11155111" /* SEPOLIA */]: "0x0000000000000000000000000000000000000000",
|
|
4320
|
+
["EVM-1" /* MAINNET */]: "0xd54165e45926720b062C192a5bacEC64d5bB08DA",
|
|
4321
|
+
["EVM-56" /* BSC_MAINNET */]: "0xd54165e45926720b062C192a5bacEC64d5bB08DA"
|
|
4322
|
+
},
|
|
4323
|
+
Host: {
|
|
4324
|
+
["EVM-97" /* BSC_CHAPEL */]: "0x8Aa0Dea6D675d785A882967Bf38183f6117C09b7",
|
|
4325
|
+
["EVM-10200" /* GNOSIS_CHIADO */]: "0x58a41b89f4871725e5d898d98ef4bf917601c5eb",
|
|
4326
|
+
["EVM-11155111" /* SEPOLIA */]: "0x2EdB74C269948b60ec1000040E104cef0eABaae8",
|
|
4327
|
+
["EVM-1" /* MAINNET */]: "0x792A6236AF69787C40cF76b69B4c8c7B28c4cA20",
|
|
4328
|
+
["EVM-56" /* BSC_MAINNET */]: "0x24B5d421Ec373FcA57325dd2F0C074009Af021F7"
|
|
4329
|
+
},
|
|
4330
|
+
UniswapRouter02: {
|
|
4331
|
+
["EVM-97" /* BSC_CHAPEL */]: "0x9639379819420704457B07A0C33B678D9E0F8Df0",
|
|
4332
|
+
["EVM-10200" /* GNOSIS_CHIADO */]: "0x0000000000000000000000000000000000000000",
|
|
4333
|
+
["EVM-11155111" /* SEPOLIA */]: "0x0000000000000000000000000000000000000000",
|
|
4334
|
+
["EVM-1" /* MAINNET */]: "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D",
|
|
4335
|
+
["EVM-56" /* BSC_MAINNET */]: "0x0000000000000000000000000000000000000000"
|
|
4336
|
+
},
|
|
4337
|
+
UniswapV2Factory: {
|
|
4338
|
+
["EVM-97" /* BSC_CHAPEL */]: "0x12e036669DA18F4A2777853d6e2136b32AceEC86",
|
|
4339
|
+
["EVM-10200" /* GNOSIS_CHIADO */]: "0x0000000000000000000000000000000000000000",
|
|
4340
|
+
["EVM-11155111" /* SEPOLIA */]: "0x0000000000000000000000000000000000000000",
|
|
4341
|
+
["EVM-1" /* MAINNET */]: "0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f",
|
|
4342
|
+
["EVM-56" /* BSC_MAINNET */]: "0x0000000000000000000000000000000000000000"
|
|
4343
|
+
},
|
|
4344
|
+
BatchExecutor: {
|
|
4345
|
+
["EVM-97" /* BSC_CHAPEL */]: "0x4CC58B5D8FBf838d062E4b21F75C327835B5F0ef",
|
|
4346
|
+
["EVM-1" /* MAINNET */]: "0x0000000000000000000000000000000000000000",
|
|
4347
|
+
["EVM-56" /* BSC_MAINNET */]: "0x0000000000000000000000000000000000000000"
|
|
4348
|
+
},
|
|
4349
|
+
UniversalRouter: {
|
|
4350
|
+
["EVM-97" /* BSC_CHAPEL */]: "0xcc6d5ece3d4a57245bf5a2f64f3ed9179b81f714",
|
|
4351
|
+
["EVM-1" /* MAINNET */]: "0x0000000000000000000000000000000000000000",
|
|
4352
|
+
["EVM-56" /* BSC_MAINNET */]: "0x0000000000000000000000000000000000000000"
|
|
4353
|
+
},
|
|
4354
|
+
UniswapV3Router: {
|
|
4355
|
+
["EVM-97" /* BSC_CHAPEL */]: "0x0000000000000000000000000000000000000000",
|
|
4356
|
+
["EVM-1" /* MAINNET */]: "0x1F98431c8aD98523631AE4a59f267346ea31F984",
|
|
4357
|
+
["EVM-56" /* BSC_MAINNET */]: "0x0000000000000000000000000000000000000000"
|
|
4358
|
+
},
|
|
4359
|
+
UniswapV3Factory: {
|
|
4360
|
+
["EVM-97" /* BSC_CHAPEL */]: "0x0000000000000000000000000000000000000000",
|
|
4361
|
+
["EVM-1" /* MAINNET */]: "0x1F98431c8aD98523631AE4a59f267346ea31F984",
|
|
4362
|
+
["EVM-56" /* BSC_MAINNET */]: "0x0000000000000000000000000000000000000000"
|
|
4363
|
+
},
|
|
4364
|
+
UniswapV3Quoter: {
|
|
4365
|
+
["EVM-97" /* BSC_CHAPEL */]: "0x0000000000000000000000000000000000000000",
|
|
4366
|
+
["EVM-1" /* MAINNET */]: "0x61fFE014bA17989E743c5F6cB21bF9697530B21e",
|
|
4367
|
+
["EVM-56" /* BSC_MAINNET */]: "0x0000000000000000000000000000000000000000"
|
|
4368
|
+
},
|
|
4369
|
+
UniswapV4PoolManager: {
|
|
4370
|
+
["EVM-97" /* BSC_CHAPEL */]: "0x0000000000000000000000000000000000000000",
|
|
4371
|
+
["EVM-1" /* MAINNET */]: "0x0000000000000000000000000000000000000000",
|
|
4372
|
+
["EVM-56" /* BSC_MAINNET */]: "0x0000000000000000000000000000000000000000"
|
|
4373
|
+
},
|
|
4374
|
+
UniswapV4Quoter: {
|
|
4375
|
+
["EVM-97" /* BSC_CHAPEL */]: "0x0000000000000000000000000000000000000000",
|
|
4376
|
+
["EVM-1" /* MAINNET */]: "0x52f0e24d1c21c8a0cb1e5a5dd6198556bd9e1203",
|
|
4377
|
+
["EVM-56" /* BSC_MAINNET */]: "0x0000000000000000000000000000000000000000"
|
|
4378
|
+
},
|
|
4379
|
+
Calldispatcher: {
|
|
4380
|
+
["EVM-11155111" /* SEPOLIA */]: "0xC7f13b6D03A0A7F3239d38897503E90553ABe155"
|
|
4381
|
+
}
|
|
4382
|
+
};
|
|
4383
|
+
var createRpcUrls = (env2) => ({
|
|
4384
|
+
["EVM-97" /* BSC_CHAPEL */]: env2.BSC_CHAPEL || "https://bnb-testnet.api.onfinality.io/public",
|
|
4385
|
+
["EVM-10200" /* GNOSIS_CHIADO */]: env2.GNOSIS_CHIADO || "https://gnosis-chiado-rpc.publicnode.com",
|
|
4386
|
+
["KUSAMA-4009" /* HYPERBRIDGE_GARGANTUA */]: env2.HYPERBRIDGE_GARGANTUA || "",
|
|
4387
|
+
["EVM-11155111" /* SEPOLIA */]: env2.SEPOLIA || "https://1rpc.io/sepolia",
|
|
4388
|
+
["EVM-1" /* MAINNET */]: env2.ETH_MAINNET || "https://eth-mainnet.g.alchemy.com/v2/demo",
|
|
4389
|
+
["EVM-56" /* BSC_MAINNET */]: env2.BSC_MAINNET || "https://binance.llamarpc.com"
|
|
4390
|
+
});
|
|
4391
|
+
var consensusStateIds = {
|
|
4392
|
+
["EVM-97" /* BSC_CHAPEL */]: "BSC0",
|
|
4393
|
+
["EVM-10200" /* GNOSIS_CHIADO */]: "GNO0",
|
|
4394
|
+
["KUSAMA-4009" /* HYPERBRIDGE_GARGANTUA */]: "PAS0",
|
|
4395
|
+
["EVM-11155111" /* SEPOLIA */]: "ETH0",
|
|
4396
|
+
["EVM-1" /* MAINNET */]: "ETH0",
|
|
4397
|
+
["EVM-56" /* BSC_MAINNET */]: "BSC0"
|
|
4398
|
+
};
|
|
4399
|
+
|
|
4400
|
+
// src/configs/ChainConfigService.ts
|
|
4401
|
+
var ChainConfigService = class {
|
|
4402
|
+
rpcUrls;
|
|
4403
|
+
constructor(env2 = process.env) {
|
|
4404
|
+
this.rpcUrls = createRpcUrls(env2);
|
|
4405
|
+
}
|
|
4406
|
+
getChainConfig(chain) {
|
|
4407
|
+
return {
|
|
4408
|
+
chainId: chainIds[chain],
|
|
4409
|
+
rpcUrl: this.rpcUrls[chain],
|
|
4410
|
+
intentGatewayAddress: addresses.IntentGateway[chain]
|
|
4411
|
+
};
|
|
4412
|
+
}
|
|
4413
|
+
getIntentGatewayAddress(chain) {
|
|
4414
|
+
return addresses.IntentGateway[chain];
|
|
4415
|
+
}
|
|
4416
|
+
getHostAddress(chain) {
|
|
4417
|
+
return addresses.Host[chain];
|
|
4418
|
+
}
|
|
4419
|
+
getWrappedNativeAssetWithDecimals(chain) {
|
|
4420
|
+
return {
|
|
4421
|
+
asset: assets[chain].WETH,
|
|
4422
|
+
decimals: WrappedNativeDecimals[chain]
|
|
4423
|
+
};
|
|
4424
|
+
}
|
|
4425
|
+
getDaiAsset(chain) {
|
|
4426
|
+
return assets[chain].DAI;
|
|
4427
|
+
}
|
|
4428
|
+
getUsdtAsset(chain) {
|
|
4429
|
+
return assets[chain].USDT;
|
|
4430
|
+
}
|
|
4431
|
+
getUsdcAsset(chain) {
|
|
4432
|
+
return assets[chain].USDC;
|
|
4433
|
+
}
|
|
4434
|
+
getChainId(chain) {
|
|
4435
|
+
return chainIds[chain];
|
|
4436
|
+
}
|
|
4437
|
+
getConsensusStateId(chain) {
|
|
4438
|
+
return toHex(consensusStateIds[chain]);
|
|
4439
|
+
}
|
|
4440
|
+
getHyperbridgeChainId() {
|
|
4441
|
+
return chainIds["KUSAMA-4009" /* HYPERBRIDGE_GARGANTUA */];
|
|
4442
|
+
}
|
|
4443
|
+
getRpcUrl(chain) {
|
|
4444
|
+
return this.rpcUrls[chain];
|
|
4445
|
+
}
|
|
4446
|
+
getUniswapRouterV2Address(chain) {
|
|
4447
|
+
return addresses.UniswapRouter02[chain];
|
|
4448
|
+
}
|
|
4449
|
+
getUniswapV2FactoryAddress(chain) {
|
|
4450
|
+
return addresses.UniswapV2Factory[chain];
|
|
4451
|
+
}
|
|
4452
|
+
getBatchExecutorAddress(chain) {
|
|
4453
|
+
return addresses.BatchExecutor[chain];
|
|
4454
|
+
}
|
|
4455
|
+
getUniversalRouterAddress(chain) {
|
|
4456
|
+
return addresses.UniversalRouter[chain];
|
|
4457
|
+
}
|
|
4458
|
+
getUniswapV3RouterAddress(chain) {
|
|
4459
|
+
return addresses.UniswapV3Router[chain];
|
|
4460
|
+
}
|
|
4461
|
+
getUniswapV3FactoryAddress(chain) {
|
|
4462
|
+
return addresses.UniswapV3Factory[chain];
|
|
4463
|
+
}
|
|
4464
|
+
getUniswapV3QuoterAddress(chain) {
|
|
4465
|
+
return addresses.UniswapV3Quoter[chain];
|
|
4466
|
+
}
|
|
4467
|
+
getUniswapV4PoolManagerAddress(chain) {
|
|
4468
|
+
return addresses.UniswapV4PoolManager[chain];
|
|
4469
|
+
}
|
|
4470
|
+
getUniswapV4QuoterAddress(chain) {
|
|
4471
|
+
return addresses.UniswapV4Quoter[chain];
|
|
4472
|
+
}
|
|
4473
|
+
};
|
|
4474
|
+
|
|
4475
|
+
// src/chains/evm.ts
|
|
4476
|
+
var chains = {
|
|
4477
|
+
[mainnet.id]: mainnet,
|
|
4478
|
+
[arbitrum.id]: arbitrum,
|
|
4479
|
+
[arbitrumSepolia.id]: arbitrumSepolia,
|
|
4480
|
+
[optimism.id]: optimism,
|
|
4481
|
+
[optimismSepolia.id]: optimismSepolia,
|
|
4482
|
+
[base.id]: base,
|
|
4483
|
+
[baseSepolia.id]: baseSepolia,
|
|
4484
|
+
[soneium.id]: soneium,
|
|
4485
|
+
[bsc.id]: bsc,
|
|
4486
|
+
[bscTestnet.id]: bscTestnet,
|
|
4487
|
+
[gnosis.id]: gnosis,
|
|
4488
|
+
[gnosisChiado.id]: gnosisChiado
|
|
4489
|
+
};
|
|
4490
|
+
var DEFAULT_ADDRESS = "0x0000000000000000000000000000000000000000";
|
|
4491
|
+
var EvmChain = class {
|
|
4492
|
+
constructor(params) {
|
|
4493
|
+
this.params = params;
|
|
4494
|
+
this.publicClient = createPublicClient({
|
|
4495
|
+
// @ts-ignore
|
|
4496
|
+
chain: chains[params.chainId],
|
|
4497
|
+
transport: http(params.url)
|
|
4498
|
+
});
|
|
4499
|
+
this.chainConfigService = new ChainConfigService();
|
|
4500
|
+
}
|
|
4501
|
+
publicClient;
|
|
4502
|
+
chainConfigService;
|
|
4503
|
+
// Expose minimal getters for external helpers/classes
|
|
4504
|
+
get client() {
|
|
4505
|
+
return this.publicClient;
|
|
4506
|
+
}
|
|
4507
|
+
get host() {
|
|
4508
|
+
return this.params.host;
|
|
4509
|
+
}
|
|
4510
|
+
get config() {
|
|
4511
|
+
return this.chainConfigService;
|
|
4512
|
+
}
|
|
4513
|
+
/**
|
|
4514
|
+
* Derives the key for the request receipt.
|
|
4515
|
+
* @param {HexString} commitment - The commitment to derive the key from.
|
|
4516
|
+
* @returns {HexString} The derived key.
|
|
4517
|
+
*/
|
|
4518
|
+
requestReceiptKey(commitment) {
|
|
4519
|
+
return deriveMapKey(hexToBytes(commitment), REQUEST_RECEIPTS_SLOT);
|
|
4520
|
+
}
|
|
4521
|
+
/**
|
|
4522
|
+
* Queries the request receipt.
|
|
4523
|
+
* @param {HexString} commitment - The commitment to query.
|
|
4524
|
+
* @returns {Promise<HexString | undefined>} The relayer address responsible for delivering the request.
|
|
4525
|
+
*/
|
|
4526
|
+
async queryRequestReceipt(commitment) {
|
|
4527
|
+
const relayer = await this.publicClient.readContract({
|
|
4528
|
+
address: this.params.host,
|
|
4529
|
+
abi: evmHost_default.ABI,
|
|
4530
|
+
functionName: "requestReceipts",
|
|
4531
|
+
args: [commitment]
|
|
4532
|
+
});
|
|
4533
|
+
return relayer === DEFAULT_ADDRESS ? void 0 : relayer;
|
|
4534
|
+
}
|
|
4535
|
+
/**
|
|
4536
|
+
* Queries the proof of the commitments.
|
|
4537
|
+
* @param {IMessage} message - The message to query.
|
|
4538
|
+
* @param {string} counterparty - The counterparty address.
|
|
4539
|
+
* @param {bigint} [at] - The block number to query at.
|
|
4540
|
+
* @returns {Promise<HexString>} The proof.
|
|
4541
|
+
*/
|
|
4542
|
+
async queryProof(message, counterparty, at) {
|
|
4543
|
+
const commitmentKeys = "Requests" in message ? message.Requests.map((key) => requestCommitmentKey(key)) : message.Responses.map((key) => responseCommitmentKey(key));
|
|
4544
|
+
const config = {
|
|
4545
|
+
address: this.params.host,
|
|
4546
|
+
storageKeys: commitmentKeys
|
|
4547
|
+
};
|
|
4548
|
+
if (!at) {
|
|
4549
|
+
config.blockTag = "latest";
|
|
4550
|
+
} else {
|
|
4551
|
+
config.blockNumber = at;
|
|
4552
|
+
}
|
|
4553
|
+
const proof = await this.publicClient.getProof(config);
|
|
4554
|
+
const flattenedProof = Array.from(new Set(flatten(proof.storageProof.map((item) => item.proof))));
|
|
4555
|
+
const encoded = EvmStateProof.enc({
|
|
4556
|
+
contractProof: proof.accountProof.map((item) => Array.from(hexToBytes(item))),
|
|
4557
|
+
storageProof: [
|
|
4558
|
+
[Array.from(hexToBytes(this.params.host)), flattenedProof.map((item) => Array.from(hexToBytes(item)))]
|
|
4559
|
+
]
|
|
4560
|
+
});
|
|
4561
|
+
return toHex(encoded);
|
|
4562
|
+
}
|
|
4563
|
+
/**
|
|
4564
|
+
* Query and return the encoded storage proof for the provided keys at the given height.
|
|
4565
|
+
* @param {bigint} at - The block height at which to query the storage proof.
|
|
4566
|
+
* @param {HexString[]} keys - The keys for which to query the storage proof.
|
|
4567
|
+
* @returns {Promise<HexString>} The encoded storage proof.
|
|
4568
|
+
*/
|
|
4569
|
+
async queryStateProof(at, keys) {
|
|
4570
|
+
const config = {
|
|
4571
|
+
address: this.params.host,
|
|
4572
|
+
storageKeys: keys
|
|
4573
|
+
};
|
|
4574
|
+
if (!at) {
|
|
4575
|
+
config.blockTag = "latest";
|
|
4576
|
+
} else {
|
|
4577
|
+
config.blockNumber = at;
|
|
4578
|
+
}
|
|
4579
|
+
const proof = await this.publicClient.getProof(config);
|
|
4580
|
+
const flattenedProof = Array.from(new Set(flatten(proof.storageProof.map((item) => item.proof))));
|
|
4581
|
+
const encoded = EvmStateProof.enc({
|
|
4582
|
+
contractProof: proof.accountProof.map((item) => Array.from(hexToBytes(item))),
|
|
4583
|
+
storageProof: [
|
|
4584
|
+
[Array.from(hexToBytes(this.params.host)), flattenedProof.map((item) => Array.from(hexToBytes(item)))]
|
|
4585
|
+
]
|
|
4586
|
+
});
|
|
4587
|
+
return toHex(encoded);
|
|
4588
|
+
}
|
|
4589
|
+
/**
|
|
4590
|
+
* Returns the current timestamp of the chain.
|
|
4591
|
+
* @returns {Promise<bigint>} The current timestamp.
|
|
4592
|
+
*/
|
|
4593
|
+
async timestamp() {
|
|
4594
|
+
const data = await this.publicClient.readContract({
|
|
4595
|
+
address: this.params.host,
|
|
4596
|
+
abi: evmHost_default.ABI,
|
|
4597
|
+
functionName: "timestamp"
|
|
4598
|
+
});
|
|
4599
|
+
return BigInt(data);
|
|
4600
|
+
}
|
|
4601
|
+
/**
|
|
4602
|
+
* Get the latest state machine height for a given state machine ID.
|
|
4603
|
+
* @param {StateMachineIdParams} stateMachineId - The state machine ID.
|
|
4604
|
+
* @returns {Promise<bigint>} The latest state machine height.
|
|
4605
|
+
*/
|
|
4606
|
+
async latestStateMachineHeight(stateMachineId) {
|
|
4607
|
+
if (!this.publicClient) throw new Error("API not initialized");
|
|
4608
|
+
const id = stateMachineId.stateId.Polkadot || stateMachineId.stateId.Kusama;
|
|
4609
|
+
if (!id)
|
|
4610
|
+
throw new Error(
|
|
4611
|
+
"Expected Polakdot or Kusama State machine id when reading latest state machine height on evm"
|
|
4612
|
+
);
|
|
4613
|
+
const data = await this.publicClient.readContract({
|
|
4614
|
+
address: this.params.host,
|
|
4615
|
+
abi: evmHost_default.ABI,
|
|
4616
|
+
functionName: "latestStateMachineHeight",
|
|
4617
|
+
args: [BigInt(id)]
|
|
4618
|
+
});
|
|
4619
|
+
return data;
|
|
4620
|
+
}
|
|
4621
|
+
/**
|
|
4622
|
+
* Get the state machine update time for a given state machine height.
|
|
4623
|
+
* @param {StateMachineHeight} stateMachineHeight - The state machine height.
|
|
4624
|
+
* @returns {Promise<bigint>} The statemachine update time in seconds.
|
|
4625
|
+
*/
|
|
4626
|
+
async stateMachineUpdateTime(stateMachineHeight) {
|
|
4627
|
+
if (!this.publicClient) throw new Error("API not initialized");
|
|
4628
|
+
const id = stateMachineHeight.id.stateId.Polkadot || stateMachineHeight.id.stateId.Kusama;
|
|
4629
|
+
if (!id) throw new Error("Expected Polkadot or Kusama State machine id when reading state machine update time");
|
|
4630
|
+
const data = await this.publicClient.readContract({
|
|
4631
|
+
address: this.params.host,
|
|
4632
|
+
abi: evmHost_default.ABI,
|
|
4633
|
+
functionName: "stateMachineCommitmentUpdateTime",
|
|
4634
|
+
args: [{ stateMachineId: BigInt(id), height: stateMachineHeight.height }]
|
|
4635
|
+
});
|
|
4636
|
+
return data;
|
|
4637
|
+
}
|
|
4638
|
+
/**
|
|
4639
|
+
* Get the challenge period for a given state machine id.
|
|
4640
|
+
* @param {StateMachineIdParams} stateMachineId - The state machine ID.
|
|
4641
|
+
* @returns {Promise<bigint>} The challenge period in seconds.
|
|
4642
|
+
*/
|
|
4643
|
+
async challengePeriod(stateMachineId) {
|
|
4644
|
+
if (!this.publicClient) throw new Error("API not initialized");
|
|
4645
|
+
const id = stateMachineId.stateId.Polkadot || stateMachineId.stateId.Kusama;
|
|
4646
|
+
if (!id)
|
|
4647
|
+
throw new Error(
|
|
4648
|
+
"Expected Polkadot or Kusama State machine id when reading latest state machine height on evm"
|
|
4649
|
+
);
|
|
4650
|
+
const data = await this.publicClient.readContract({
|
|
4651
|
+
address: this.params.host,
|
|
4652
|
+
abi: evmHost_default.ABI,
|
|
4653
|
+
functionName: "challengePeriod"
|
|
4654
|
+
});
|
|
4655
|
+
return data;
|
|
4656
|
+
}
|
|
4657
|
+
/**
|
|
4658
|
+
* Encodes an ISMP message for the EVM chain.
|
|
4659
|
+
* @param {IIsmpMessage} message The ISMP message to encode.
|
|
4660
|
+
* @returns {HexString} The encoded calldata.
|
|
4661
|
+
*/
|
|
4662
|
+
encode(message) {
|
|
4663
|
+
const encoded = match(message).with({ kind: "PostRequest" }, (request) => {
|
|
4664
|
+
const mmrProof = MmrProof.dec(request.proof.proof);
|
|
4665
|
+
const requests = zip(request.requests, mmrProof.leafIndexAndPos).map(([req, leafIndexAndPos]) => {
|
|
4666
|
+
if (!req || !leafIndexAndPos) return;
|
|
4667
|
+
const [[, kIndex]] = mmrPositionToKIndex(
|
|
4668
|
+
[leafIndexAndPos?.pos],
|
|
4669
|
+
calculateMMRSize(mmrProof.leafCount)
|
|
4670
|
+
);
|
|
4671
|
+
return {
|
|
4672
|
+
request: {
|
|
4673
|
+
source: toHex(req.source),
|
|
4674
|
+
dest: toHex(req.dest),
|
|
4675
|
+
to: req.to,
|
|
4676
|
+
from: req.from,
|
|
4677
|
+
nonce: req.nonce,
|
|
4678
|
+
timeoutTimestamp: req.timeoutTimestamp,
|
|
4679
|
+
body: req.body
|
|
4680
|
+
},
|
|
4681
|
+
index: leafIndexAndPos?.leafIndex,
|
|
4682
|
+
kIndex
|
|
4683
|
+
};
|
|
4684
|
+
}).filter((item) => !!item);
|
|
4685
|
+
const proof = {
|
|
4686
|
+
height: {
|
|
4687
|
+
stateMachineId: BigInt(Number.parseInt(request.proof.stateMachine.split("-")[1])),
|
|
4688
|
+
height: request.proof.height
|
|
4689
|
+
},
|
|
4690
|
+
multiproof: mmrProof.items.map((item) => bytesToHex(new Uint8Array(item))),
|
|
4691
|
+
leafCount: mmrProof.leafCount
|
|
4692
|
+
};
|
|
4693
|
+
const encoded2 = encodeFunctionData({
|
|
4694
|
+
abi: handler_default.ABI,
|
|
4695
|
+
functionName: "handlePostRequests",
|
|
4696
|
+
args: [
|
|
4697
|
+
this.params.host,
|
|
4698
|
+
{
|
|
4699
|
+
proof,
|
|
4700
|
+
requests
|
|
4701
|
+
}
|
|
4702
|
+
]
|
|
4703
|
+
});
|
|
4704
|
+
return encoded2;
|
|
4705
|
+
}).with({ kind: "TimeoutPostRequest" }, (timeout) => {
|
|
4706
|
+
const proof = SubstrateStateProof.dec(timeout.proof.proof).value.storageProof.map(
|
|
4707
|
+
(item) => toHex(new Uint8Array(item))
|
|
4708
|
+
);
|
|
4709
|
+
const encoded2 = encodeFunctionData({
|
|
4710
|
+
abi: handler_default.ABI,
|
|
4711
|
+
functionName: "handlePostRequestTimeouts",
|
|
4712
|
+
args: [
|
|
4713
|
+
this.params.host,
|
|
4714
|
+
{
|
|
4715
|
+
height: {
|
|
4716
|
+
stateMachineId: BigInt(Number.parseInt(timeout.proof.stateMachine.split("-")[1])),
|
|
4717
|
+
height: timeout.proof.height
|
|
4718
|
+
},
|
|
4719
|
+
timeouts: timeout.requests.map((req) => ({
|
|
4720
|
+
source: toHex(req.source),
|
|
4721
|
+
dest: toHex(req.dest),
|
|
4722
|
+
to: req.to,
|
|
4723
|
+
from: req.from,
|
|
4724
|
+
nonce: req.nonce,
|
|
4725
|
+
timeoutTimestamp: req.timeoutTimestamp,
|
|
4726
|
+
body: req.body
|
|
4727
|
+
})),
|
|
4728
|
+
proof
|
|
4729
|
+
}
|
|
4730
|
+
]
|
|
4731
|
+
});
|
|
4732
|
+
return encoded2;
|
|
4733
|
+
}).with({ kind: "GetResponse" }, (request) => {
|
|
4734
|
+
const mmrProof = MmrProof.dec(request.proof.proof);
|
|
4735
|
+
const responses = zip(request.responses, mmrProof.leafIndexAndPos).map(([req, leafIndexAndPos]) => {
|
|
4736
|
+
if (!req || !leafIndexAndPos) return;
|
|
4737
|
+
const [[, kIndex]] = mmrPositionToKIndex(
|
|
4738
|
+
[leafIndexAndPos?.pos],
|
|
4739
|
+
calculateMMRSize(mmrProof.leafCount)
|
|
4740
|
+
);
|
|
4741
|
+
return {
|
|
4742
|
+
response: {
|
|
4743
|
+
request: {
|
|
4744
|
+
source: toHex(req.get.source),
|
|
4745
|
+
dest: toHex(req.get.dest),
|
|
4746
|
+
from: req.get.from,
|
|
4747
|
+
nonce: req.get.nonce,
|
|
4748
|
+
timeoutTimestamp: req.get.timeoutTimestamp,
|
|
4749
|
+
keys: req.get.keys,
|
|
4750
|
+
context: req.get.context,
|
|
4751
|
+
height: req.get.height
|
|
4752
|
+
},
|
|
4753
|
+
values: req.values
|
|
4754
|
+
},
|
|
4755
|
+
index: leafIndexAndPos?.leafIndex,
|
|
4756
|
+
kIndex
|
|
4757
|
+
};
|
|
4758
|
+
}).filter((item) => !!item);
|
|
4759
|
+
const proof = {
|
|
4760
|
+
height: {
|
|
4761
|
+
stateMachineId: BigInt(Number.parseInt(request.proof.stateMachine.split("-")[1])),
|
|
4762
|
+
height: request.proof.height
|
|
4763
|
+
},
|
|
4764
|
+
multiproof: mmrProof.items.map((item) => bytesToHex(new Uint8Array(item))),
|
|
4765
|
+
leafCount: mmrProof.leafCount
|
|
4766
|
+
};
|
|
4767
|
+
const encoded2 = encodeFunctionData({
|
|
4768
|
+
abi: handler_default.ABI,
|
|
4769
|
+
functionName: "handleGetResponses",
|
|
4770
|
+
args: [
|
|
4771
|
+
this.params.host,
|
|
4772
|
+
{
|
|
4773
|
+
proof,
|
|
4774
|
+
responses
|
|
4775
|
+
}
|
|
4776
|
+
]
|
|
4777
|
+
});
|
|
4778
|
+
return encoded2;
|
|
4779
|
+
}).exhaustive();
|
|
4780
|
+
return encoded;
|
|
4781
|
+
}
|
|
4782
|
+
/**
|
|
4783
|
+
* Calculates the fee required to send a post request to the destination chain.
|
|
4784
|
+
* The fee is calculated based on the per-byte fee for the destination chain
|
|
4785
|
+
* multiplied by the size of the request body.
|
|
4786
|
+
*
|
|
4787
|
+
* @param request - The post request to calculate the fee for
|
|
4788
|
+
* @returns The total fee in wei required to send the post request
|
|
4789
|
+
*/
|
|
4790
|
+
async quote(request) {
|
|
4791
|
+
const perByteFee = await this.publicClient.readContract({
|
|
4792
|
+
address: this.params.host,
|
|
4793
|
+
abi: evmHost_default.ABI,
|
|
4794
|
+
functionName: "perByteFee",
|
|
4795
|
+
args: [toHex(request.dest)]
|
|
4796
|
+
});
|
|
4797
|
+
const bodyByteLength = Math.floor((request.body.length - 2) / 2);
|
|
4798
|
+
const length = bodyByteLength < 32 ? 32 : bodyByteLength;
|
|
4799
|
+
return perByteFee * BigInt(length);
|
|
4800
|
+
}
|
|
4801
|
+
/**
|
|
4802
|
+
* Estimates the gas required for a post request execution on this chain.
|
|
4803
|
+
* This function generates mock proofs for the post request, creates a state override
|
|
4804
|
+
* with the necessary overlay root, and estimates the gas cost for executing the
|
|
4805
|
+
* handlePostRequests transaction on the handler contract.
|
|
4806
|
+
*
|
|
4807
|
+
* @param request - The post request to estimate gas for
|
|
4808
|
+
* @param paraId - The ID of the parachain (Hyperbridge) that will process the request
|
|
4809
|
+
* @returns The estimated gas amount in gas units
|
|
4810
|
+
*/
|
|
4811
|
+
async estimateGas(request) {
|
|
4812
|
+
const hostParams = await this.publicClient.readContract({
|
|
4813
|
+
address: this.params.host,
|
|
4814
|
+
abi: evmHost_default.ABI,
|
|
4815
|
+
functionName: "hostParams"
|
|
4816
|
+
});
|
|
4817
|
+
const { root, proof, index, kIndex, treeSize } = await generateRootWithProof(request, 2n ** 10n);
|
|
4818
|
+
const latestStateMachineHeight = 6291991n;
|
|
4819
|
+
const paraId = 4009n;
|
|
4820
|
+
const overlayRootSlot = getStateCommitmentFieldSlot(
|
|
4821
|
+
paraId,
|
|
4822
|
+
// Hyperbridge chain id
|
|
4823
|
+
latestStateMachineHeight,
|
|
4824
|
+
// Hyperbridge chain height
|
|
4825
|
+
1
|
|
4826
|
+
// For overlayRoot
|
|
4827
|
+
);
|
|
4828
|
+
const postParams = {
|
|
4829
|
+
height: {
|
|
4830
|
+
stateMachineId: BigInt(paraId),
|
|
4831
|
+
height: latestStateMachineHeight
|
|
4832
|
+
},
|
|
4833
|
+
multiproof: proof,
|
|
4834
|
+
leafCount: treeSize
|
|
4835
|
+
};
|
|
4836
|
+
const gas = await this.publicClient.estimateContractGas({
|
|
4837
|
+
address: hostParams.handler,
|
|
4838
|
+
abi: handler_default.ABI,
|
|
4839
|
+
functionName: "handlePostRequests",
|
|
4840
|
+
args: [
|
|
4841
|
+
this.params.host,
|
|
4842
|
+
{
|
|
4843
|
+
proof: postParams,
|
|
4844
|
+
requests: [
|
|
4845
|
+
{
|
|
4846
|
+
request: {
|
|
4847
|
+
...request,
|
|
4848
|
+
source: toHex(request.source),
|
|
4849
|
+
dest: toHex(request.dest)
|
|
4850
|
+
},
|
|
4851
|
+
index,
|
|
4852
|
+
kIndex
|
|
4853
|
+
}
|
|
4854
|
+
]
|
|
4855
|
+
}
|
|
4856
|
+
],
|
|
4857
|
+
stateOverride: [
|
|
4858
|
+
{
|
|
4859
|
+
address: this.params.host,
|
|
4860
|
+
stateDiff: [
|
|
4861
|
+
{
|
|
4862
|
+
slot: overlayRootSlot,
|
|
4863
|
+
value: root
|
|
4864
|
+
}
|
|
4865
|
+
]
|
|
4866
|
+
}
|
|
4867
|
+
]
|
|
4868
|
+
});
|
|
4869
|
+
return gas;
|
|
4870
|
+
}
|
|
4871
|
+
/**
|
|
4872
|
+
* Gets the fee token address and decimals for the chain.
|
|
4873
|
+
* This function gets the fee token address and decimals for the chain.
|
|
4874
|
+
*
|
|
4875
|
+
* @returns The fee token address and decimals
|
|
4876
|
+
*/
|
|
4877
|
+
async getFeeTokenWithDecimals() {
|
|
4878
|
+
const hostParams = await this.publicClient.readContract({
|
|
4879
|
+
abi: evmHost_default.ABI,
|
|
4880
|
+
address: this.params.host,
|
|
4881
|
+
functionName: "hostParams"
|
|
4882
|
+
});
|
|
4883
|
+
const feeTokenAddress = hostParams.feeToken;
|
|
4884
|
+
const feeTokenDecimals = await this.publicClient.readContract({
|
|
4885
|
+
address: feeTokenAddress,
|
|
4886
|
+
abi: erc20Abi,
|
|
4887
|
+
functionName: "decimals"
|
|
4888
|
+
});
|
|
4889
|
+
return { address: feeTokenAddress, decimals: feeTokenDecimals };
|
|
4890
|
+
}
|
|
4891
|
+
/**
|
|
4892
|
+
* Gets the nonce of the host.
|
|
4893
|
+
* This function gets the nonce of the host.
|
|
4894
|
+
*
|
|
4895
|
+
* @returns The nonce of the host
|
|
4896
|
+
*/
|
|
4897
|
+
async getHostNonce() {
|
|
4898
|
+
const nonce = await this.publicClient.readContract({
|
|
4899
|
+
abi: evmHost_default.ABI,
|
|
4900
|
+
address: this.params.host,
|
|
4901
|
+
functionName: "nonce"
|
|
4902
|
+
});
|
|
4903
|
+
return nonce;
|
|
4904
|
+
}
|
|
4905
|
+
};
|
|
4906
|
+
var REQUEST_COMMITMENTS_SLOT = 0n;
|
|
4907
|
+
var RESPONSE_COMMITMENTS_SLOT = 1n;
|
|
4908
|
+
var REQUEST_RECEIPTS_SLOT = 2n;
|
|
4909
|
+
var RESPONSE_RECEIPTS_SLOT = 3n;
|
|
4910
|
+
var STATE_COMMITMENTS_SLOT = 5n;
|
|
4911
|
+
function requestCommitmentKey(key) {
|
|
4912
|
+
const keyBytes = hexToBytes(key);
|
|
4913
|
+
const slot = REQUEST_COMMITMENTS_SLOT;
|
|
4914
|
+
const mappedKey = deriveMapKey(keyBytes, slot);
|
|
4915
|
+
const number = bytesToBigInt(hexToBytes(mappedKey)) + 1n;
|
|
4916
|
+
return pad(`0x${number.toString(16)}`, { size: 32 });
|
|
4917
|
+
}
|
|
4918
|
+
function responseCommitmentKey(key) {
|
|
4919
|
+
const keyBytes = hexToBytes(key);
|
|
4920
|
+
const slot = RESPONSE_COMMITMENTS_SLOT;
|
|
4921
|
+
const mappedKey = deriveMapKey(keyBytes, slot);
|
|
4922
|
+
const number = bytesToBigInt(hexToBytes(mappedKey)) + 1n;
|
|
4923
|
+
return pad(`0x${number.toString(16)}`, { size: 32 });
|
|
4924
|
+
}
|
|
4925
|
+
function deriveMapKey(key, slot) {
|
|
4926
|
+
const slotBytes = pad(`0x${slot.toString(16)}`, { size: 32 });
|
|
4927
|
+
const combined = new Uint8Array([...key, ...toBytes(slotBytes)]);
|
|
4928
|
+
return keccak256(combined);
|
|
4929
|
+
}
|
|
4930
|
+
function getStateCommitmentFieldSlot(stateMachineId, height, field) {
|
|
4931
|
+
const baseSlot = getStateCommitmentSlot(stateMachineId, height);
|
|
4932
|
+
const slotNumber = bytesToBigInt(toBytes(baseSlot)) + BigInt(field);
|
|
4933
|
+
return pad(`0x${slotNumber.toString(16)}`, { size: 32 });
|
|
4934
|
+
}
|
|
4935
|
+
function getStateCommitmentSlot(stateMachineId, height) {
|
|
4936
|
+
const firstLevelSlot = deriveFirstLevelSlot(stateMachineId, STATE_COMMITMENTS_SLOT);
|
|
4937
|
+
return deriveSecondLevelSlot(height, firstLevelSlot);
|
|
4938
|
+
}
|
|
4939
|
+
function deriveFirstLevelSlot(key, slot) {
|
|
4940
|
+
const keyHex = pad(`0x${key.toString(16)}`, { size: 32 });
|
|
4941
|
+
const keyBytes = toBytes(keyHex);
|
|
4942
|
+
const slotBytes = toBytes(pad(`0x${slot.toString(16)}`, { size: 32 }));
|
|
4943
|
+
const combined = new Uint8Array([...keyBytes, ...slotBytes]);
|
|
4944
|
+
return keccak256(combined);
|
|
4945
|
+
}
|
|
4946
|
+
function deriveSecondLevelSlot(key, firstLevelSlot) {
|
|
4947
|
+
const keyHex = pad(`0x${key.toString(16)}`, { size: 32 });
|
|
4948
|
+
const keyBytes = toBytes(keyHex);
|
|
4949
|
+
const slotBytes = toBytes(firstLevelSlot);
|
|
4950
|
+
const combined = new Uint8Array([...keyBytes, ...slotBytes]);
|
|
4951
|
+
return keccak256(combined);
|
|
4952
|
+
}
|
|
4953
|
+
var SubstrateChain = class {
|
|
4954
|
+
constructor(params) {
|
|
4955
|
+
this.params = params;
|
|
4956
|
+
}
|
|
5065
4957
|
/*
|
|
5066
|
-
*
|
|
4958
|
+
* api: The Polkadot API instance for the Substrate chain.
|
|
5067
4959
|
*/
|
|
5068
|
-
|
|
5069
|
-
/*
|
|
5070
|
-
* Timed out requests
|
|
5071
|
-
*/
|
|
5072
|
-
requests: Vector(Request)
|
|
5073
|
-
})
|
|
5074
|
-
});
|
|
5075
|
-
var Message = Enum({
|
|
4960
|
+
api;
|
|
5076
4961
|
/*
|
|
5077
|
-
*
|
|
4962
|
+
* connect: Connects to the Substrate chain using the provided WebSocket URL.
|
|
5078
4963
|
*/
|
|
5079
|
-
|
|
5080
|
-
|
|
5081
|
-
|
|
4964
|
+
async connect() {
|
|
4965
|
+
const wsProvider = new WsProvider(this.params.ws);
|
|
4966
|
+
const typesBundle = this.params.hasher === "Keccak" ? {
|
|
4967
|
+
spec: {
|
|
4968
|
+
nexus: {
|
|
4969
|
+
hasher: keccakAsU8a
|
|
4970
|
+
},
|
|
4971
|
+
gargantua: {
|
|
4972
|
+
hasher: keccakAsU8a
|
|
4973
|
+
}
|
|
4974
|
+
}
|
|
4975
|
+
} : {};
|
|
4976
|
+
this.api = await ApiPromise.create({
|
|
4977
|
+
provider: wsProvider,
|
|
4978
|
+
typesBundle
|
|
4979
|
+
});
|
|
4980
|
+
}
|
|
4981
|
+
/**
|
|
4982
|
+
* Disconnects the Substrate chain connection.
|
|
5082
4983
|
*/
|
|
5083
|
-
|
|
5084
|
-
|
|
5085
|
-
|
|
4984
|
+
async disconnect() {
|
|
4985
|
+
if (this.api) {
|
|
4986
|
+
await this.api.disconnect();
|
|
4987
|
+
this.api = void 0;
|
|
4988
|
+
}
|
|
4989
|
+
}
|
|
4990
|
+
/**
|
|
4991
|
+
* Returns the storage key for a request receipt in the child trie
|
|
4992
|
+
* The request commitment is the key
|
|
4993
|
+
* @param key - The H256 hash key (as a 0x-prefixed hex string)
|
|
4994
|
+
* @returns The storage key as a hex string
|
|
5086
4995
|
*/
|
|
5087
|
-
|
|
5088
|
-
|
|
5089
|
-
|
|
4996
|
+
requestReceiptKey(key) {
|
|
4997
|
+
const prefix = new TextEncoder().encode("RequestReceipts");
|
|
4998
|
+
const keyBytes = hexToBytes(key);
|
|
4999
|
+
return bytesToHex(new Uint8Array([...prefix, ...keyBytes]));
|
|
5000
|
+
}
|
|
5001
|
+
/**
|
|
5002
|
+
* Returns the storage key for a request commitment in the child trie
|
|
5003
|
+
* The request commitment is the key
|
|
5004
|
+
* @param key - The H256 hash key (as a 0x-prefixed hex string)
|
|
5005
|
+
* @returns The storage key as a hex string
|
|
5090
5006
|
*/
|
|
5091
|
-
|
|
5092
|
-
|
|
5093
|
-
|
|
5007
|
+
requestCommitmentKey(key) {
|
|
5008
|
+
const prefix = new TextEncoder().encode("RequestCommitments");
|
|
5009
|
+
const keyBytes = hexToBytes(key);
|
|
5010
|
+
return bytesToHex(new Uint8Array([...prefix, ...keyBytes]));
|
|
5011
|
+
}
|
|
5012
|
+
/**
|
|
5013
|
+
* Queries a request commitment from the ISMP child trie storage.
|
|
5014
|
+
* @param {HexString} commitment - The commitment hash to look up.
|
|
5015
|
+
* @returns {Promise<HexString | undefined>} The commitment data if found, undefined otherwise.
|
|
5094
5016
|
*/
|
|
5095
|
-
|
|
5096
|
-
|
|
5097
|
-
|
|
5098
|
-
|
|
5099
|
-
|
|
5100
|
-
|
|
5101
|
-
|
|
5102
|
-
var DUMMY_PRIVATE_KEY = "0x0000000000000000000000000000000000000000000000000000000000000000";
|
|
5103
|
-
function sleep(ms) {
|
|
5104
|
-
return new Promise((resolve) => setTimeout(resolve, ms || DEFAULT_POLL_INTERVAL));
|
|
5105
|
-
}
|
|
5106
|
-
async function waitForChallengePeriod(chain, stateMachineHeight) {
|
|
5107
|
-
const challengePeriod = await chain.challengePeriod(stateMachineHeight.id);
|
|
5108
|
-
if (challengePeriod === BigInt(0)) return;
|
|
5109
|
-
const updateTime = await chain.stateMachineUpdateTime(stateMachineHeight);
|
|
5110
|
-
let currentTimestamp = await chain.timestamp();
|
|
5111
|
-
let timeElapsed = currentTimestamp - updateTime;
|
|
5112
|
-
if (timeElapsed > challengePeriod) return;
|
|
5113
|
-
await sleep(Number(challengePeriod) * 1e3);
|
|
5114
|
-
while (timeElapsed <= challengePeriod) {
|
|
5115
|
-
const remainingTime = challengePeriod - timeElapsed;
|
|
5116
|
-
await sleep(Number(remainingTime) * 1e3);
|
|
5117
|
-
currentTimestamp = await chain.timestamp();
|
|
5118
|
-
timeElapsed = currentTimestamp - updateTime;
|
|
5017
|
+
async queryRequestCommitment(commitment) {
|
|
5018
|
+
const prefix = toHex(":child_storage:default:ISMP");
|
|
5019
|
+
const key = this.requestCommitmentKey(commitment);
|
|
5020
|
+
const rpc = new RpcWebSocketClient();
|
|
5021
|
+
await rpc.connect(this.params.ws);
|
|
5022
|
+
const item = await rpc.call("childstate_getStorage", [prefix, key]);
|
|
5023
|
+
return item;
|
|
5119
5024
|
}
|
|
5120
|
-
|
|
5121
|
-
|
|
5122
|
-
|
|
5123
|
-
}
|
|
5124
|
-
|
|
5125
|
-
|
|
5126
|
-
|
|
5127
|
-
|
|
5128
|
-
|
|
5129
|
-
|
|
5130
|
-
|
|
5131
|
-
|
|
5132
|
-
);
|
|
5025
|
+
/**
|
|
5026
|
+
* Queries the request receipt.
|
|
5027
|
+
* @param {HexString} commitment - The commitment to query.
|
|
5028
|
+
* @returns {Promise<HexString | undefined>} The relayer address responsible for delivering the request.
|
|
5029
|
+
*/
|
|
5030
|
+
async queryRequestReceipt(commitment) {
|
|
5031
|
+
const prefix = toHex(":child_storage:default:ISMP");
|
|
5032
|
+
const key = this.requestReceiptKey(commitment);
|
|
5033
|
+
const rpc = new RpcWebSocketClient();
|
|
5034
|
+
await rpc.connect(this.params.ws);
|
|
5035
|
+
const item = await rpc.call("childstate_getStorage", [prefix, key]);
|
|
5036
|
+
return item;
|
|
5133
5037
|
}
|
|
5134
|
-
|
|
5135
|
-
|
|
5136
|
-
|
|
5137
|
-
|
|
5138
|
-
|
|
5139
|
-
|
|
5140
|
-
|
|
5141
|
-
|
|
5142
|
-
|
|
5143
|
-
|
|
5144
|
-
|
|
5145
|
-
|
|
5146
|
-
|
|
5147
|
-
|
|
5148
|
-
|
|
5149
|
-
|
|
5150
|
-
|
|
5151
|
-
|
|
5152
|
-
|
|
5153
|
-
|
|
5154
|
-
|
|
5155
|
-
|
|
5038
|
+
/**
|
|
5039
|
+
* Returns the current timestamp of the chain.
|
|
5040
|
+
* @returns {Promise<bigint>} The current timestamp.
|
|
5041
|
+
*/
|
|
5042
|
+
async timestamp() {
|
|
5043
|
+
if (!this.api) throw new Error("API not initialized");
|
|
5044
|
+
const now = await this.api.query.timestamp.now();
|
|
5045
|
+
return BigInt(now.toJSON()) / BigInt(1e3);
|
|
5046
|
+
}
|
|
5047
|
+
/**
|
|
5048
|
+
* Queries the proof of the commitments.
|
|
5049
|
+
* @param {IMessage} message - The message to query.
|
|
5050
|
+
* @param {string} counterparty - The counterparty address.
|
|
5051
|
+
* @param {bigint} [at] - The block number to query at.
|
|
5052
|
+
* @returns {Promise<HexString>} The proof.
|
|
5053
|
+
*/
|
|
5054
|
+
async queryProof(message, counterparty, at) {
|
|
5055
|
+
const rpc = new RpcWebSocketClient();
|
|
5056
|
+
await rpc.connect(this.params.ws);
|
|
5057
|
+
if (isEvmChain(counterparty)) {
|
|
5058
|
+
const proof = await rpc.call("mmr_queryProof", [Number(at), message]);
|
|
5059
|
+
return toHex(proof.proof);
|
|
5156
5060
|
}
|
|
5157
|
-
|
|
5158
|
-
const
|
|
5159
|
-
|
|
5160
|
-
|
|
5161
|
-
|
|
5162
|
-
|
|
5163
|
-
|
|
5061
|
+
if (isSubstrateChain(counterparty)) {
|
|
5062
|
+
const childTrieKeys = "Requests" in message ? message.Requests.map(requestCommitmentStorageKey) : message.Responses.map(responseCommitmentStorageKey);
|
|
5063
|
+
const proof = await rpc.call("ismp_queryChildTrieProof", [Number(at), childTrieKeys]);
|
|
5064
|
+
const basicProof = BasicProof.dec(toHex(proof.proof));
|
|
5065
|
+
const encoded = SubstrateStateProof.enc({
|
|
5066
|
+
tag: "OverlayProof",
|
|
5067
|
+
value: {
|
|
5068
|
+
hasher: {
|
|
5069
|
+
tag: this.params.hasher,
|
|
5070
|
+
value: void 0
|
|
5071
|
+
},
|
|
5072
|
+
storageProof: basicProof
|
|
5073
|
+
}
|
|
5074
|
+
});
|
|
5075
|
+
return toHex(encoded);
|
|
5164
5076
|
}
|
|
5165
|
-
|
|
5166
|
-
throw new Error(`Unsupported chain type: ${type}. Expected one of: EVM, SUBSTRATE, POLKADOT, KUSAMA.`);
|
|
5077
|
+
throw new ExpectedError(`Unsupported chain type for counterparty: ${counterparty}`);
|
|
5167
5078
|
}
|
|
5168
|
-
|
|
5169
|
-
|
|
5170
|
-
|
|
5171
|
-
|
|
5172
|
-
|
|
5173
|
-
|
|
5174
|
-
|
|
5175
|
-
|
|
5176
|
-
|
|
5177
|
-
|
|
5178
|
-
|
|
5179
|
-
|
|
5180
|
-
|
|
5181
|
-
|
|
5182
|
-
|
|
5183
|
-
|
|
5184
|
-
|
|
5185
|
-
|
|
5186
|
-
|
|
5187
|
-
|
|
5188
|
-
{
|
|
5189
|
-
|
|
5190
|
-
|
|
5191
|
-
|
|
5192
|
-
|
|
5193
|
-
|
|
5194
|
-
|
|
5195
|
-
|
|
5196
|
-
|
|
5197
|
-
|
|
5198
|
-
|
|
5199
|
-
|
|
5200
|
-
|
|
5201
|
-
|
|
5202
|
-
|
|
5203
|
-
|
|
5204
|
-
|
|
5205
|
-
|
|
5206
|
-
|
|
5207
|
-
|
|
5208
|
-
|
|
5209
|
-
|
|
5210
|
-
|
|
5211
|
-
|
|
5212
|
-
|
|
5213
|
-
|
|
5214
|
-
[
|
|
5215
|
-
|
|
5216
|
-
|
|
5217
|
-
|
|
5218
|
-
|
|
5219
|
-
|
|
5220
|
-
|
|
5221
|
-
|
|
5222
|
-
|
|
5223
|
-
|
|
5224
|
-
callData: order.callData
|
|
5079
|
+
/**
|
|
5080
|
+
* Submit an unsigned ISMP transaction to the chain. Resolves when the transaction is finalized.
|
|
5081
|
+
* @param message - The message to be submitted.
|
|
5082
|
+
* @returns A promise that resolves to an object containing the transaction hash, block hash, and block number.
|
|
5083
|
+
*/
|
|
5084
|
+
async submitUnsigned(message) {
|
|
5085
|
+
if (!this.api) throw new Error("API not initialized");
|
|
5086
|
+
const { api } = this;
|
|
5087
|
+
const args = hexToBytes(this.encode(message)).slice(2);
|
|
5088
|
+
const tx = api.tx.ismp.handleUnsigned(args);
|
|
5089
|
+
return new Promise((resolve, reject) => {
|
|
5090
|
+
let unsub = () => {
|
|
5091
|
+
};
|
|
5092
|
+
tx.send(async ({ isInBlock, isFinalized, isError, dispatchError, txHash, status }) => {
|
|
5093
|
+
if (isFinalized || isInBlock) {
|
|
5094
|
+
unsub();
|
|
5095
|
+
const blockHash = isInBlock ? status.asInBlock.toHex() : status.asFinalized.toHex();
|
|
5096
|
+
const header = await api.rpc.chain.getHeader(blockHash);
|
|
5097
|
+
const apiAt = await api.at(blockHash);
|
|
5098
|
+
const timestamp = await apiAt.query.timestamp.now();
|
|
5099
|
+
resolve({
|
|
5100
|
+
transactionHash: txHash.toHex(),
|
|
5101
|
+
blockHash,
|
|
5102
|
+
blockNumber: header.number.toNumber(),
|
|
5103
|
+
timestamp: Number(timestamp.toJSON()) / 1e3
|
|
5104
|
+
});
|
|
5105
|
+
} else if (isError) {
|
|
5106
|
+
unsub();
|
|
5107
|
+
console.error("Unsigned transaction failed: ", dispatchError);
|
|
5108
|
+
reject(dispatchError);
|
|
5109
|
+
}
|
|
5110
|
+
}).then((unsubscribe) => {
|
|
5111
|
+
unsub = unsubscribe;
|
|
5112
|
+
}).catch(reject);
|
|
5113
|
+
});
|
|
5114
|
+
}
|
|
5115
|
+
/**
|
|
5116
|
+
* Query the state proof for a given set of keys at a specific block height.
|
|
5117
|
+
* @param at The block height to query the state proof at.
|
|
5118
|
+
* @param keys The keys to query the state proof for.
|
|
5119
|
+
* @returns The state proof as a hexadecimal string.
|
|
5120
|
+
*/
|
|
5121
|
+
async queryStateProof(at, keys) {
|
|
5122
|
+
const rpc = new RpcWebSocketClient();
|
|
5123
|
+
await rpc.connect(this.params.ws);
|
|
5124
|
+
const encodedKeys = keys.map((key) => Array.from(hexToBytes(key)));
|
|
5125
|
+
const proof = await rpc.call("ismp_queryChildTrieProof", [Number(at), encodedKeys]);
|
|
5126
|
+
const basicProof = BasicProof.dec(toHex(proof.proof));
|
|
5127
|
+
const encoded = SubstrateStateProof.enc({
|
|
5128
|
+
tag: "OverlayProof",
|
|
5129
|
+
value: {
|
|
5130
|
+
hasher: {
|
|
5131
|
+
tag: this.params.hasher,
|
|
5132
|
+
value: void 0
|
|
5133
|
+
},
|
|
5134
|
+
storageProof: basicProof
|
|
5225
5135
|
}
|
|
5226
|
-
|
|
5227
|
-
|
|
5228
|
-
return keccak256(encodedOrder);
|
|
5229
|
-
}
|
|
5230
|
-
function bytes32ToBytes202(bytes32Address) {
|
|
5231
|
-
if (bytes32Address === ADDRESS_ZERO2) {
|
|
5232
|
-
return ADDRESS_ZERO2;
|
|
5136
|
+
});
|
|
5137
|
+
return toHex(encoded);
|
|
5233
5138
|
}
|
|
5234
|
-
|
|
5235
|
-
|
|
5236
|
-
|
|
5237
|
-
}
|
|
5238
|
-
|
|
5239
|
-
|
|
5240
|
-
|
|
5241
|
-
|
|
5242
|
-
|
|
5243
|
-
const bytes = new Uint8Array(hexWithoutPrefix.length / 2);
|
|
5244
|
-
for (let i = 0; i < hexWithoutPrefix.length; i += 2) {
|
|
5245
|
-
bytes[i / 2] = Number.parseInt(hexWithoutPrefix.slice(i, i + 2), 16);
|
|
5139
|
+
/**
|
|
5140
|
+
* Get the latest state machine height for a given state machine ID.
|
|
5141
|
+
* @param {StateMachineIdParams} stateMachineId - The state machine ID.
|
|
5142
|
+
* @returns {Promise<bigint>} The latest state machine height.
|
|
5143
|
+
*/
|
|
5144
|
+
async latestStateMachineHeight(stateMachineId) {
|
|
5145
|
+
if (!this.api) throw new Error("API not initialized");
|
|
5146
|
+
const latestHeight = await this.api.query.ismp.latestStateMachineHeight(stateMachineId);
|
|
5147
|
+
return BigInt(latestHeight.toString());
|
|
5246
5148
|
}
|
|
5247
|
-
|
|
5248
|
-
|
|
5249
|
-
|
|
5250
|
-
|
|
5251
|
-
|
|
5252
|
-
async
|
|
5253
|
-
|
|
5254
|
-
|
|
5255
|
-
|
|
5256
|
-
|
|
5257
|
-
|
|
5258
|
-
|
|
5259
|
-
|
|
5260
|
-
|
|
5261
|
-
|
|
5262
|
-
|
|
5149
|
+
/**
|
|
5150
|
+
* Get the state machine update time for a given state machine height.
|
|
5151
|
+
* @param {StateMachineHeight} stateMachineHeight - The state machine height.
|
|
5152
|
+
* @returns {Promise<bigint>} The statemachine update time in seconds.
|
|
5153
|
+
*/
|
|
5154
|
+
async stateMachineUpdateTime(stateMachineHeight) {
|
|
5155
|
+
if (!this.api) throw new Error("API not initialized");
|
|
5156
|
+
const updateTime = await this.api.query.ismp.stateMachineUpdateTime(stateMachineHeight);
|
|
5157
|
+
return BigInt(updateTime.toString());
|
|
5158
|
+
}
|
|
5159
|
+
/**
|
|
5160
|
+
* Get the challenge period for a given state machine id.
|
|
5161
|
+
* @param {StateMachineIdParams} stateMachineId - The state machine ID.
|
|
5162
|
+
* @returns {Promise<bigint>} The challenge period in seconds.
|
|
5163
|
+
*/
|
|
5164
|
+
async challengePeriod(stateMachineId) {
|
|
5165
|
+
if (!this.api) throw new Error("API not initialized");
|
|
5166
|
+
const challengePeriod = await this.api.query.ismp.challengePeriod(stateMachineId);
|
|
5167
|
+
return BigInt(challengePeriod.toString());
|
|
5168
|
+
}
|
|
5169
|
+
/**
|
|
5170
|
+
* Encode an ISMP calldata for a substrate chain.
|
|
5171
|
+
* @param message The ISMP message to encode.
|
|
5172
|
+
* @returns The encoded message as a hexadecimal string.
|
|
5173
|
+
*/
|
|
5174
|
+
encode(message) {
|
|
5175
|
+
const palletIndex = this.getPalletIndex("Ismp");
|
|
5176
|
+
const args = encodeISMPMessage(message);
|
|
5177
|
+
const call = Vector(u8, 2).enc([palletIndex, 0]);
|
|
5178
|
+
return toHex(new Uint8Array([...call, ...args]));
|
|
5179
|
+
}
|
|
5180
|
+
/**
|
|
5181
|
+
* Returns the index of a pallet by its name, by looking up the pallets in the runtime metadata.
|
|
5182
|
+
* @param {string} name - The name of the pallet.
|
|
5183
|
+
* @returns {number} The index of the pallet.
|
|
5184
|
+
*/
|
|
5185
|
+
getPalletIndex(name) {
|
|
5186
|
+
if (!this.api) throw new Error("API not initialized");
|
|
5187
|
+
const pallets = this.api.runtimeMetadata.asLatest.pallets.entries();
|
|
5188
|
+
for (const p of pallets) {
|
|
5189
|
+
if (p[1].name.toString() === name) {
|
|
5190
|
+
const index = p[1].index.toNumber();
|
|
5191
|
+
return index;
|
|
5192
|
+
}
|
|
5193
|
+
}
|
|
5194
|
+
throw new Error(`${name} not found in runtime`);
|
|
5263
5195
|
}
|
|
5264
|
-
throw lastError;
|
|
5265
|
-
}
|
|
5266
|
-
function getRequestCommitment(get) {
|
|
5267
|
-
const keysEncoding = "0x".concat(get.keys.map((key) => key.slice(2)).join(""));
|
|
5268
|
-
return keccak256(
|
|
5269
|
-
encodePacked(
|
|
5270
|
-
["bytes", "bytes", "uint64", "uint64", "uint64", "bytes", "bytes", "bytes"],
|
|
5271
|
-
[
|
|
5272
|
-
toHex(get.source),
|
|
5273
|
-
toHex(get.dest),
|
|
5274
|
-
get.nonce,
|
|
5275
|
-
get.height,
|
|
5276
|
-
get.timeoutTimestamp,
|
|
5277
|
-
get.from,
|
|
5278
|
-
keysEncoding,
|
|
5279
|
-
get.context
|
|
5280
|
-
]
|
|
5281
|
-
)
|
|
5282
|
-
);
|
|
5283
|
-
}
|
|
5284
|
-
var REQUEST_STATUS_WEIGHTS = {
|
|
5285
|
-
[RequestStatus.SOURCE]: 0,
|
|
5286
|
-
[RequestStatus.SOURCE_FINALIZED]: 1,
|
|
5287
|
-
[RequestStatus.HYPERBRIDGE_DELIVERED]: 2,
|
|
5288
|
-
[RequestStatus.HYPERBRIDGE_FINALIZED]: 3,
|
|
5289
|
-
[RequestStatus.DESTINATION]: 4,
|
|
5290
|
-
[RequestStatus.HYPERBRIDGE_TIMED_OUT]: 5,
|
|
5291
|
-
[RequestStatus.TIMED_OUT]: 6
|
|
5292
|
-
};
|
|
5293
|
-
var TIMEOUT_STATUS_WEIGHTS = {
|
|
5294
|
-
[TimeoutStatus.PENDING_TIMEOUT]: 1,
|
|
5295
|
-
[TimeoutStatus.DESTINATION_FINALIZED_TIMEOUT]: 2,
|
|
5296
|
-
[TimeoutStatus.HYPERBRIDGE_TIMED_OUT]: 3,
|
|
5297
|
-
[TimeoutStatus.HYPERBRIDGE_FINALIZED_TIMEOUT]: 4,
|
|
5298
|
-
[TimeoutStatus.TIMED_OUT]: 5
|
|
5299
|
-
};
|
|
5300
|
-
var COMBINED_STATUS_WEIGHTS = {
|
|
5301
|
-
[RequestStatus.SOURCE]: 0,
|
|
5302
|
-
[RequestStatus.SOURCE_FINALIZED]: 1,
|
|
5303
|
-
[RequestStatus.HYPERBRIDGE_DELIVERED]: 2,
|
|
5304
|
-
[RequestStatus.HYPERBRIDGE_FINALIZED]: 3,
|
|
5305
|
-
[RequestStatus.DESTINATION]: 4,
|
|
5306
|
-
[TimeoutStatus.PENDING_TIMEOUT]: 5,
|
|
5307
|
-
[TimeoutStatus.DESTINATION_FINALIZED_TIMEOUT]: 6,
|
|
5308
|
-
[TimeoutStatus.HYPERBRIDGE_TIMED_OUT]: 7,
|
|
5309
|
-
[TimeoutStatus.HYPERBRIDGE_FINALIZED_TIMEOUT]: 8,
|
|
5310
|
-
[TimeoutStatus.TIMED_OUT]: 9
|
|
5311
5196
|
};
|
|
5312
|
-
|
|
5313
|
-
const
|
|
5314
|
-
|
|
5315
|
-
|
|
5316
|
-
|
|
5317
|
-
|
|
5318
|
-
const
|
|
5319
|
-
const
|
|
5320
|
-
|
|
5321
|
-
|
|
5322
|
-
|
|
5323
|
-
|
|
5324
|
-
|
|
5325
|
-
|
|
5326
|
-
|
|
5327
|
-
|
|
5328
|
-
|
|
5329
|
-
|
|
5330
|
-
|
|
5331
|
-
|
|
5332
|
-
|
|
5333
|
-
|
|
5334
|
-
|
|
5197
|
+
function requestCommitmentStorageKey(key) {
|
|
5198
|
+
const prefix = new TextEncoder().encode("RequestCommitments");
|
|
5199
|
+
const keyBytes = hexToBytes(key);
|
|
5200
|
+
return Array.from(new Uint8Array([...prefix, ...keyBytes]));
|
|
5201
|
+
}
|
|
5202
|
+
function responseCommitmentStorageKey(key) {
|
|
5203
|
+
const prefix = new TextEncoder().encode("ResponseCommitments");
|
|
5204
|
+
const keyBytes = hexToBytes(key);
|
|
5205
|
+
return Array.from(new Uint8Array([...prefix, ...keyBytes]));
|
|
5206
|
+
}
|
|
5207
|
+
function convertStateMachineIdToEnum(id) {
|
|
5208
|
+
let [tag, value] = id.split("-");
|
|
5209
|
+
tag = capitalize(tag);
|
|
5210
|
+
if (["Evm", "Polkadot", "Kusama"].includes(tag)) {
|
|
5211
|
+
value = Number.parseInt(value);
|
|
5212
|
+
} else {
|
|
5213
|
+
value = Array.from(toBytes(value));
|
|
5214
|
+
}
|
|
5215
|
+
return { tag, value };
|
|
5216
|
+
}
|
|
5217
|
+
function convertIPostRequestToCodec(request) {
|
|
5218
|
+
return {
|
|
5219
|
+
tag: "Post",
|
|
5220
|
+
value: {
|
|
5221
|
+
source: convertStateMachineIdToEnum(request.source),
|
|
5222
|
+
dest: convertStateMachineIdToEnum(request.dest),
|
|
5223
|
+
from: Array.from(hexToBytes(request.from)),
|
|
5224
|
+
to: Array.from(hexToBytes(request.to)),
|
|
5225
|
+
nonce: request.nonce,
|
|
5226
|
+
body: Array.from(hexToBytes(request.body)),
|
|
5227
|
+
timeoutTimestamp: request.timeoutTimestamp
|
|
5228
|
+
}
|
|
5335
5229
|
};
|
|
5336
|
-
|
|
5337
|
-
|
|
5338
|
-
|
|
5339
|
-
|
|
5340
|
-
|
|
5341
|
-
|
|
5342
|
-
|
|
5343
|
-
|
|
5344
|
-
|
|
5345
|
-
|
|
5346
|
-
|
|
5347
|
-
|
|
5348
|
-
|
|
5349
|
-
|
|
5230
|
+
}
|
|
5231
|
+
function encodeISMPMessage(message) {
|
|
5232
|
+
try {
|
|
5233
|
+
return match(message).with({ kind: "PostRequest" }, (message2) => {
|
|
5234
|
+
return Vector(Message).enc([
|
|
5235
|
+
{
|
|
5236
|
+
tag: "RequestMessage",
|
|
5237
|
+
value: {
|
|
5238
|
+
requests: message2.requests.map(
|
|
5239
|
+
(post_request) => convertIPostRequestToCodec(post_request).value
|
|
5240
|
+
),
|
|
5241
|
+
proof: {
|
|
5242
|
+
height: {
|
|
5243
|
+
height: message2.proof.height,
|
|
5244
|
+
id: {
|
|
5245
|
+
consensusStateId: Array.from(toBytes(message2.proof.consensusStateId)),
|
|
5246
|
+
id: convertStateMachineIdToEnum(message2.proof.stateMachine)
|
|
5247
|
+
}
|
|
5248
|
+
},
|
|
5249
|
+
proof: Array.from(hexToBytes(message2.proof.proof))
|
|
5350
5250
|
},
|
|
5351
|
-
|
|
5352
|
-
kIndex
|
|
5251
|
+
signer: Array.from(hexToBytes(message2.signer))
|
|
5353
5252
|
}
|
|
5354
|
-
|
|
5355
|
-
|
|
5356
|
-
|
|
5357
|
-
|
|
5358
|
-
|
|
5359
|
-
|
|
5360
|
-
|
|
5361
|
-
|
|
5362
|
-
|
|
5363
|
-
|
|
5253
|
+
}
|
|
5254
|
+
]);
|
|
5255
|
+
}).with({ kind: "GetResponse" }, (message2) => {
|
|
5256
|
+
throw new Error("GetResponse is not yet supported on Substrate chains");
|
|
5257
|
+
}).with({ kind: "TimeoutPostRequest" }, (message2) => {
|
|
5258
|
+
return Vector(Message).enc([
|
|
5259
|
+
{
|
|
5260
|
+
tag: "TimeoutMessage",
|
|
5261
|
+
value: {
|
|
5262
|
+
tag: "Post",
|
|
5263
|
+
value: {
|
|
5264
|
+
requests: message2.requests.map((r) => convertIPostRequestToCodec(r)),
|
|
5265
|
+
proof: {
|
|
5266
|
+
height: {
|
|
5267
|
+
height: message2.proof.height,
|
|
5268
|
+
id: {
|
|
5269
|
+
consensusStateId: Array.from(toBytes(message2.proof.consensusStateId)),
|
|
5270
|
+
id: convertStateMachineIdToEnum(message2.proof.stateMachine)
|
|
5271
|
+
}
|
|
5272
|
+
},
|
|
5273
|
+
proof: Array.from(hexToBytes(message2.proof.proof))
|
|
5274
|
+
}
|
|
5275
|
+
}
|
|
5364
5276
|
}
|
|
5365
|
-
|
|
5366
|
-
|
|
5367
|
-
|
|
5368
|
-
})
|
|
5369
|
-
|
|
5277
|
+
}
|
|
5278
|
+
]);
|
|
5279
|
+
}).exhaustive();
|
|
5280
|
+
} catch (error) {
|
|
5281
|
+
throw new Error("Failed to encode ISMP message", { cause: error });
|
|
5282
|
+
}
|
|
5370
5283
|
}
|
|
5371
|
-
|
|
5372
|
-
|
|
5373
|
-
|
|
5374
|
-
|
|
5375
|
-
|
|
5376
|
-
|
|
5377
|
-
|
|
5378
|
-
|
|
5379
|
-
|
|
5380
|
-
|
|
5381
|
-
|
|
5382
|
-
|
|
5383
|
-
|
|
5384
|
-
|
|
5385
|
-
|
|
5386
|
-
|
|
5387
|
-
|
|
5388
|
-
|
|
5389
|
-
|
|
5390
|
-
|
|
5391
|
-
|
|
5392
|
-
|
|
5393
|
-
|
|
5394
|
-
]
|
|
5395
|
-
}
|
|
5396
|
-
]
|
|
5397
|
-
}
|
|
5398
|
-
],
|
|
5399
|
-
[requestBody]
|
|
5400
|
-
);
|
|
5401
|
-
return concatHex([requestKind, encodedRequestBody]);
|
|
5284
|
+
|
|
5285
|
+
// src/chain.ts
|
|
5286
|
+
async function getChain(chainConfig) {
|
|
5287
|
+
if (isEvmChain(chainConfig.stateMachineId)) {
|
|
5288
|
+
const config = chainConfig;
|
|
5289
|
+
const chainId = Number.parseInt(chainConfig.stateMachineId.split("-")[1]);
|
|
5290
|
+
const evmChain = new EvmChain({
|
|
5291
|
+
chainId,
|
|
5292
|
+
url: config.rpcUrl,
|
|
5293
|
+
host: config.host
|
|
5294
|
+
});
|
|
5295
|
+
return evmChain;
|
|
5296
|
+
}
|
|
5297
|
+
if (isSubstrateChain(chainConfig.stateMachineId)) {
|
|
5298
|
+
const config = chainConfig;
|
|
5299
|
+
const substrateChain = new SubstrateChain({
|
|
5300
|
+
ws: config.wsUrl,
|
|
5301
|
+
hasher: config.hasher
|
|
5302
|
+
});
|
|
5303
|
+
await substrateChain.connect();
|
|
5304
|
+
return substrateChain;
|
|
5305
|
+
}
|
|
5306
|
+
throw new ExpectedError(`Unsupported chain: ${chainConfig.stateMachineId}`);
|
|
5402
5307
|
}
|
|
5403
|
-
|
|
5404
|
-
|
|
5405
|
-
|
|
5308
|
+
|
|
5309
|
+
// src/queries.ts
|
|
5310
|
+
var POST_REQUEST_STATUS = `
|
|
5311
|
+
query RequestStatusM($hash: String!) {
|
|
5312
|
+
requests(
|
|
5313
|
+
filter: { commitment: { equalTo: $hash } }
|
|
5314
|
+
) {
|
|
5315
|
+
nodes {
|
|
5316
|
+
commitment
|
|
5317
|
+
timeoutTimestamp
|
|
5318
|
+
source
|
|
5319
|
+
dest
|
|
5320
|
+
to
|
|
5321
|
+
from
|
|
5322
|
+
nonce
|
|
5323
|
+
body
|
|
5324
|
+
statusMetadata {
|
|
5325
|
+
nodes {
|
|
5326
|
+
blockHash
|
|
5327
|
+
blockNumber
|
|
5328
|
+
timestamp
|
|
5329
|
+
chain
|
|
5330
|
+
status
|
|
5331
|
+
transactionHash
|
|
5332
|
+
}
|
|
5333
|
+
}
|
|
5334
|
+
}
|
|
5406
5335
|
}
|
|
5407
|
-
|
|
5408
|
-
|
|
5409
|
-
|
|
5410
|
-
|
|
5411
|
-
|
|
5412
|
-
|
|
5413
|
-
|
|
5414
|
-
|
|
5415
|
-
|
|
5416
|
-
|
|
5417
|
-
|
|
5418
|
-
|
|
5419
|
-
|
|
5420
|
-
|
|
5421
|
-
|
|
5422
|
-
|
|
5423
|
-
|
|
5424
|
-
|
|
5425
|
-
|
|
5426
|
-
|
|
5427
|
-
|
|
5428
|
-
|
|
5429
|
-
|
|
5430
|
-
|
|
5431
|
-
|
|
5336
|
+
}
|
|
5337
|
+
`;
|
|
5338
|
+
var GET_REQUEST_STATUS = `
|
|
5339
|
+
query GetRequestDetails($commitment: String!) {
|
|
5340
|
+
getRequests(
|
|
5341
|
+
filter: { commitment: { equalTo: $commitment } }
|
|
5342
|
+
) {
|
|
5343
|
+
nodes {
|
|
5344
|
+
id
|
|
5345
|
+
source
|
|
5346
|
+
dest
|
|
5347
|
+
from
|
|
5348
|
+
keys
|
|
5349
|
+
nonce
|
|
5350
|
+
height
|
|
5351
|
+
context
|
|
5352
|
+
timeoutTimestamp
|
|
5353
|
+
fee
|
|
5354
|
+
blockNumber
|
|
5355
|
+
blockHash
|
|
5356
|
+
transactionHash
|
|
5357
|
+
blockTimestamp
|
|
5358
|
+
status
|
|
5359
|
+
chain
|
|
5360
|
+
commitment
|
|
5361
|
+
statusMetadata {
|
|
5362
|
+
nodes {
|
|
5363
|
+
status
|
|
5364
|
+
chain
|
|
5365
|
+
timestamp
|
|
5366
|
+
blockNumber
|
|
5367
|
+
blockHash
|
|
5368
|
+
transactionHash
|
|
5369
|
+
}
|
|
5370
|
+
}
|
|
5371
|
+
}
|
|
5432
5372
|
}
|
|
5433
|
-
}
|
|
5434
|
-
|
|
5435
|
-
|
|
5436
|
-
|
|
5437
|
-
|
|
5438
|
-
|
|
5439
|
-
|
|
5440
|
-
|
|
5441
|
-
|
|
5442
|
-
|
|
5443
|
-
|
|
5444
|
-
|
|
5445
|
-
|
|
5446
|
-
|
|
5373
|
+
}`;
|
|
5374
|
+
var STATE_MACHINE_UPDATES_BY_HEIGHT = `
|
|
5375
|
+
query StateMachineUpdatesByHeight($statemachineId: String!, $height: Int!, $chain: String!) {
|
|
5376
|
+
stateMachineUpdateEvents(
|
|
5377
|
+
filter: {
|
|
5378
|
+
and: [
|
|
5379
|
+
{ stateMachineId: { equalTo: $statemachineId } }
|
|
5380
|
+
{ height: { greaterThanOrEqualTo: $height } }
|
|
5381
|
+
{ chain: { equalTo: $chain } }
|
|
5382
|
+
]
|
|
5383
|
+
}
|
|
5384
|
+
orderBy: HEIGHT_ASC
|
|
5385
|
+
first: 1
|
|
5386
|
+
) {
|
|
5387
|
+
nodes {
|
|
5388
|
+
height
|
|
5389
|
+
stateMachineId
|
|
5390
|
+
chain
|
|
5391
|
+
blockHash
|
|
5392
|
+
blockNumber
|
|
5393
|
+
transactionHash
|
|
5394
|
+
createdAt
|
|
5447
5395
|
}
|
|
5448
5396
|
}
|
|
5449
5397
|
}
|
|
5450
|
-
|
|
5451
|
-
|
|
5452
|
-
|
|
5453
|
-
|
|
5454
|
-
|
|
5455
|
-
|
|
5398
|
+
`;
|
|
5399
|
+
var STATE_MACHINE_UPDATES_BY_TIMESTAMP = `
|
|
5400
|
+
query StateMachineUpdatesByTimestamp($statemachineId: String!, $commitmentTimestamp: BigFloat!, $chain: String!) {
|
|
5401
|
+
stateMachineUpdateEvents(
|
|
5402
|
+
filter: {
|
|
5403
|
+
and: [
|
|
5404
|
+
{ stateMachineId: { equalTo: $statemachineId } }
|
|
5405
|
+
{ commitmentTimestamp: { greaterThanOrEqualTo: $commitmentTimestamp } }
|
|
5406
|
+
{ chain: { equalTo: $chain } }
|
|
5407
|
+
]
|
|
5408
|
+
}
|
|
5409
|
+
orderBy: COMMITMENT_TIMESTAMP_DESC
|
|
5410
|
+
first: 1
|
|
5411
|
+
) {
|
|
5412
|
+
nodes {
|
|
5413
|
+
height
|
|
5414
|
+
stateMachineId
|
|
5415
|
+
chain
|
|
5416
|
+
blockHash
|
|
5417
|
+
blockNumber
|
|
5418
|
+
transactionHash
|
|
5419
|
+
commitmentTimestamp
|
|
5420
|
+
createdAt
|
|
5421
|
+
}
|
|
5422
|
+
}
|
|
5456
5423
|
}
|
|
5457
|
-
|
|
5458
|
-
|
|
5459
|
-
|
|
5460
|
-
|
|
5424
|
+
`;
|
|
5425
|
+
var ASSET_TELEPORTED_BY_PARAMS = `
|
|
5426
|
+
query AssetTeleportedByParams($from: String!, $to: String!, $dest: String!, $blockNumber: Int!) {
|
|
5427
|
+
assetTeleporteds(
|
|
5428
|
+
filter: {
|
|
5429
|
+
and: [
|
|
5430
|
+
{ from: { equalTo: $from } }
|
|
5431
|
+
{ to: { equalTo: $to } }
|
|
5432
|
+
{ dest: { includes: $dest } }
|
|
5433
|
+
{ blockNumber: { greaterThanOrEqualTo: $blockNumber } }
|
|
5434
|
+
]
|
|
5435
|
+
}
|
|
5436
|
+
orderBy: CREATED_AT_DESC
|
|
5437
|
+
first: 1
|
|
5438
|
+
) {
|
|
5439
|
+
nodes {
|
|
5440
|
+
id
|
|
5441
|
+
from
|
|
5442
|
+
to
|
|
5443
|
+
amount
|
|
5444
|
+
dest
|
|
5445
|
+
commitment
|
|
5446
|
+
createdAt
|
|
5447
|
+
blockNumber
|
|
5448
|
+
}
|
|
5461
5449
|
}
|
|
5462
|
-
return data[key].usd;
|
|
5463
5450
|
}
|
|
5464
|
-
|
|
5465
|
-
|
|
5466
|
-
|
|
5467
|
-
|
|
5468
|
-
|
|
5469
|
-
|
|
5470
|
-
|
|
5471
|
-
|
|
5472
|
-
|
|
5473
|
-
const price = data.coins?.[coinId]?.price;
|
|
5474
|
-
if (!price && price !== 0) {
|
|
5475
|
-
throw new Error(`Price not found for token: ${mappedIdentifier}`);
|
|
5451
|
+
`;
|
|
5452
|
+
var GET_RESPONSE_BY_REQUEST_ID = `
|
|
5453
|
+
query GetResponseByRequestId($requestId: String!) {
|
|
5454
|
+
getResponses(filter: {requestId: {equalTo: $requestId}}) {
|
|
5455
|
+
nodes {
|
|
5456
|
+
id
|
|
5457
|
+
commitment
|
|
5458
|
+
responseMessage
|
|
5459
|
+
}
|
|
5476
5460
|
}
|
|
5477
|
-
return price;
|
|
5478
5461
|
}
|
|
5479
|
-
|
|
5480
|
-
|
|
5481
|
-
|
|
5482
|
-
|
|
5483
|
-
|
|
5484
|
-
|
|
5485
|
-
|
|
5486
|
-
|
|
5487
|
-
|
|
5488
|
-
|
|
5489
|
-
|
|
5490
|
-
|
|
5491
|
-
|
|
5492
|
-
|
|
5493
|
-
|
|
5494
|
-
|
|
5495
|
-
|
|
5496
|
-
|
|
5497
|
-
|
|
5498
|
-
|
|
5499
|
-
|
|
5500
|
-
|
|
5501
|
-
|
|
5502
|
-
|
|
5503
|
-
|
|
5504
|
-
|
|
5505
|
-
|
|
5506
|
-
|
|
5507
|
-
|
|
5462
|
+
`;
|
|
5463
|
+
var ORDER_STATUS = `
|
|
5464
|
+
query OrderStatus($commitment: String!) {
|
|
5465
|
+
orderPlaceds(
|
|
5466
|
+
filter: { commitment: { equalTo: $commitment } }
|
|
5467
|
+
) {
|
|
5468
|
+
nodes {
|
|
5469
|
+
id
|
|
5470
|
+
user
|
|
5471
|
+
sourceChain
|
|
5472
|
+
destChain
|
|
5473
|
+
commitment
|
|
5474
|
+
deadline
|
|
5475
|
+
nonce
|
|
5476
|
+
fees
|
|
5477
|
+
inputTokens
|
|
5478
|
+
inputAmounts
|
|
5479
|
+
inputValuesUSD
|
|
5480
|
+
inputUSD
|
|
5481
|
+
outputTokens
|
|
5482
|
+
outputAmounts
|
|
5483
|
+
outputBeneficiaries
|
|
5484
|
+
calldata
|
|
5485
|
+
status
|
|
5486
|
+
createdAt
|
|
5487
|
+
blockNumber
|
|
5488
|
+
blockTimestamp
|
|
5489
|
+
transactionHash
|
|
5490
|
+
statusMetadata {
|
|
5491
|
+
nodes {
|
|
5492
|
+
status
|
|
5493
|
+
chain
|
|
5494
|
+
timestamp
|
|
5495
|
+
blockNumber
|
|
5496
|
+
transactionHash
|
|
5497
|
+
filler
|
|
5498
|
+
}
|
|
5508
5499
|
}
|
|
5509
5500
|
}
|
|
5510
5501
|
}
|
|
5511
|
-
|
|
5512
|
-
|
|
5513
|
-
|
|
5514
|
-
|
|
5515
|
-
|
|
5516
|
-
|
|
5517
|
-
|
|
5518
|
-
|
|
5519
|
-
|
|
5520
|
-
|
|
5502
|
+
}`;
|
|
5503
|
+
var TOKEN_GATEWAY_ASSET_TELEPORTED_STATUS = `
|
|
5504
|
+
query TokenGatewayAssetTeleportedStatus($commitment: String!) {
|
|
5505
|
+
tokenGatewayAssetTeleporteds(
|
|
5506
|
+
filter: { commitment: { equalTo: $commitment } }
|
|
5507
|
+
) {
|
|
5508
|
+
nodes {
|
|
5509
|
+
id
|
|
5510
|
+
from
|
|
5511
|
+
to
|
|
5512
|
+
sourceChain
|
|
5513
|
+
destChain
|
|
5514
|
+
commitment
|
|
5515
|
+
amount
|
|
5516
|
+
usdValue
|
|
5517
|
+
assetId
|
|
5518
|
+
redeem
|
|
5519
|
+
status
|
|
5520
|
+
createdAt
|
|
5521
|
+
blockNumber
|
|
5522
|
+
blockTimestamp
|
|
5523
|
+
transactionHash
|
|
5524
|
+
statusMetadata {
|
|
5525
|
+
nodes {
|
|
5526
|
+
status
|
|
5527
|
+
chain
|
|
5528
|
+
timestamp
|
|
5529
|
+
blockNumber
|
|
5530
|
+
transactionHash
|
|
5531
|
+
}
|
|
5532
|
+
}
|
|
5533
|
+
}
|
|
5521
5534
|
}
|
|
5522
|
-
}
|
|
5535
|
+
}`;
|
|
5523
5536
|
function createQueryClient(config) {
|
|
5524
5537
|
return new GraphQLClient(config.url);
|
|
5525
5538
|
}
|
|
@@ -6155,7 +6168,7 @@ var IndexerClient = class {
|
|
|
6155
6168
|
switch (status) {
|
|
6156
6169
|
// request has been dispatched from source chain
|
|
6157
6170
|
case RequestStatus.SOURCE: {
|
|
6158
|
-
|
|
6171
|
+
const sourceUpdate = await this.waitOrAbort({
|
|
6159
6172
|
signal,
|
|
6160
6173
|
promise: () => this.queryStateMachineUpdateByHeight({
|
|
6161
6174
|
statemachineId: request.source,
|
|
@@ -6197,7 +6210,7 @@ var IndexerClient = class {
|
|
|
6197
6210
|
}
|
|
6198
6211
|
// the request has been verified and aggregated on Hyperbridge
|
|
6199
6212
|
case RequestStatus.HYPERBRIDGE_DELIVERED: {
|
|
6200
|
-
|
|
6213
|
+
const hyperbridgeFinalized = await this.waitOrAbort({
|
|
6201
6214
|
signal,
|
|
6202
6215
|
promise: () => {
|
|
6203
6216
|
const stateMachineId = this.config.hyperbridge.stateMachineId;
|
|
@@ -6214,17 +6227,36 @@ var IndexerClient = class {
|
|
|
6214
6227
|
...this.config.hyperbridge,
|
|
6215
6228
|
hasher: "Keccak"
|
|
6216
6229
|
});
|
|
6217
|
-
const
|
|
6218
|
-
{
|
|
6219
|
-
|
|
6220
|
-
|
|
6221
|
-
|
|
6230
|
+
const safeFetchProof = async () => {
|
|
6231
|
+
try {
|
|
6232
|
+
const proof_hex = await hyperbridge.queryProof(
|
|
6233
|
+
{ Requests: [postRequestCommitment(request).commitment] },
|
|
6234
|
+
request.dest,
|
|
6235
|
+
BigInt(hyperbridgeFinalized.height)
|
|
6236
|
+
);
|
|
6237
|
+
return { data: proof_hex, error: null };
|
|
6238
|
+
} catch (err) {
|
|
6239
|
+
return { error: err, data: null };
|
|
6240
|
+
}
|
|
6241
|
+
};
|
|
6242
|
+
const proof = await this.waitOrAbort({
|
|
6243
|
+
signal,
|
|
6244
|
+
promise: () => this.withRetry(safeFetchProof, {
|
|
6245
|
+
backoffMs: 2e3,
|
|
6246
|
+
maxRetries: 6
|
|
6247
|
+
// <-- should fail after 2mins
|
|
6248
|
+
})
|
|
6249
|
+
});
|
|
6250
|
+
if (proof.data === null) {
|
|
6251
|
+
this.logger.error("Failed to fetch proof:", proof.error);
|
|
6252
|
+
throw proof.error;
|
|
6253
|
+
}
|
|
6222
6254
|
const calldata = destChain.encode({
|
|
6223
6255
|
kind: "PostRequest",
|
|
6224
6256
|
proof: {
|
|
6225
6257
|
stateMachine: this.config.hyperbridge.stateMachineId,
|
|
6226
6258
|
consensusStateId: this.config.hyperbridge.consensusStateId,
|
|
6227
|
-
proof,
|
|
6259
|
+
proof: proof.data,
|
|
6228
6260
|
height: BigInt(hyperbridgeFinalized.height)
|
|
6229
6261
|
},
|
|
6230
6262
|
requests: [request],
|
|
@@ -6313,7 +6345,7 @@ var IndexerClient = class {
|
|
|
6313
6345
|
async *getRequestStatusStream(hash) {
|
|
6314
6346
|
const controller = new AbortController();
|
|
6315
6347
|
try {
|
|
6316
|
-
|
|
6348
|
+
const request = await this.waitOrAbort({
|
|
6317
6349
|
signal: controller.signal,
|
|
6318
6350
|
promise: () => this.queryGetRequest(hash)
|
|
6319
6351
|
});
|
|
@@ -6349,7 +6381,7 @@ var IndexerClient = class {
|
|
|
6349
6381
|
switch (status) {
|
|
6350
6382
|
// request has been dispatched from source chain
|
|
6351
6383
|
case RequestStatus.SOURCE: {
|
|
6352
|
-
|
|
6384
|
+
const sourceUpdate = await this.waitOrAbort({
|
|
6353
6385
|
signal,
|
|
6354
6386
|
promise: () => this.queryStateMachineUpdateByHeight({
|
|
6355
6387
|
statemachineId: request.source,
|
|
@@ -6394,7 +6426,7 @@ var IndexerClient = class {
|
|
|
6394
6426
|
if (request.source === this.config.hyperbridge.stateMachineId) {
|
|
6395
6427
|
return;
|
|
6396
6428
|
}
|
|
6397
|
-
|
|
6429
|
+
const hyperbridgeFinalized = await this.waitOrAbort({
|
|
6398
6430
|
signal,
|
|
6399
6431
|
promise: () => this.queryStateMachineUpdateByHeight({
|
|
6400
6432
|
statemachineId: this.config.hyperbridge.stateMachineId,
|
|
@@ -6645,7 +6677,7 @@ var IndexerClient = class {
|
|
|
6645
6677
|
})
|
|
6646
6678
|
});
|
|
6647
6679
|
} else {
|
|
6648
|
-
|
|
6680
|
+
const timeout = await this.waitOrAbort({
|
|
6649
6681
|
signal,
|
|
6650
6682
|
promise: async () => {
|
|
6651
6683
|
const req = await this.queryPostRequest(hash);
|
|
@@ -11321,7 +11353,7 @@ var IntentGateway = class {
|
|
|
11321
11353
|
const postRequest = {
|
|
11322
11354
|
source: order.destChain,
|
|
11323
11355
|
dest: order.sourceChain,
|
|
11324
|
-
body:
|
|
11356
|
+
body: constructRedeemEscrowRequestBody(order, MOCK_ADDRESS),
|
|
11325
11357
|
timeoutTimestamp: 0n,
|
|
11326
11358
|
nonce: await this.source.getHostNonce(),
|
|
11327
11359
|
from: this.source.config.getIntentGatewayAddress(order.destChain),
|
|
@@ -11345,23 +11377,23 @@ var IntentGateway = class {
|
|
|
11345
11377
|
const fillOptions = {
|
|
11346
11378
|
relayerFee: relayerFeeInDestFeeToken
|
|
11347
11379
|
};
|
|
11348
|
-
const totalEthValue = order.outputs.filter((output) =>
|
|
11380
|
+
const totalEthValue = order.outputs.filter((output) => bytes32ToBytes20(output.token) === ADDRESS_ZERO).reduce((sum, output) => sum + output.amount, 0n);
|
|
11349
11381
|
const intentGatewayAddress = this.source.config.getIntentGatewayAddress(order.destChain);
|
|
11350
11382
|
const testValue = toHex(maxUint256 / 2n);
|
|
11351
11383
|
const orderOverrides = await Promise.all(
|
|
11352
11384
|
order.outputs.map(async (output) => {
|
|
11353
|
-
const tokenAddress =
|
|
11354
|
-
if (tokenAddress ===
|
|
11385
|
+
const tokenAddress = bytes32ToBytes20(output.token);
|
|
11386
|
+
if (tokenAddress === ADDRESS_ZERO) {
|
|
11355
11387
|
return null;
|
|
11356
11388
|
}
|
|
11357
11389
|
try {
|
|
11358
11390
|
const stateDiffs = [];
|
|
11359
|
-
const balanceData = "0x70a08231" /* BALANCE_OF */ + bytes20ToBytes32(
|
|
11360
|
-
const balanceSlot = await
|
|
11391
|
+
const balanceData = "0x70a08231" /* BALANCE_OF */ + bytes20ToBytes32(MOCK_ADDRESS).slice(2);
|
|
11392
|
+
const balanceSlot = await getStorageSlot(this.dest.client, tokenAddress, balanceData);
|
|
11361
11393
|
stateDiffs.push({ slot: balanceSlot, value: testValue });
|
|
11362
11394
|
try {
|
|
11363
|
-
const allowanceData = "0xdd62ed3e" /* ALLOWANCE */ + bytes20ToBytes32(
|
|
11364
|
-
const allowanceSlot = await
|
|
11395
|
+
const allowanceData = "0xdd62ed3e" /* ALLOWANCE */ + bytes20ToBytes32(MOCK_ADDRESS).slice(2) + bytes20ToBytes32(intentGatewayAddress).slice(2);
|
|
11396
|
+
const allowanceSlot = await getStorageSlot(
|
|
11365
11397
|
this.dest.client,
|
|
11366
11398
|
tokenAddress,
|
|
11367
11399
|
allowanceData
|
|
@@ -11377,14 +11409,14 @@ var IntentGateway = class {
|
|
|
11377
11409
|
}
|
|
11378
11410
|
})
|
|
11379
11411
|
).then((results) => results.filter(Boolean));
|
|
11380
|
-
const destFeeTokenBalanceData = "0x70a08231" /* BALANCE_OF */ + bytes20ToBytes32(
|
|
11381
|
-
const destFeeTokenBalanceSlot = await
|
|
11412
|
+
const destFeeTokenBalanceData = "0x70a08231" /* BALANCE_OF */ + bytes20ToBytes32(MOCK_ADDRESS).slice(2);
|
|
11413
|
+
const destFeeTokenBalanceSlot = await getStorageSlot(
|
|
11382
11414
|
this.dest.client,
|
|
11383
11415
|
destChainFeeTokenAddress,
|
|
11384
11416
|
destFeeTokenBalanceData
|
|
11385
11417
|
);
|
|
11386
|
-
const destFeeTokenAllowanceData = "0xdd62ed3e" /* ALLOWANCE */ + bytes20ToBytes32(
|
|
11387
|
-
const destFeeTokenAllowanceSlot = await
|
|
11418
|
+
const destFeeTokenAllowanceData = "0xdd62ed3e" /* ALLOWANCE */ + bytes20ToBytes32(MOCK_ADDRESS).slice(2) + bytes20ToBytes32(intentGatewayAddress).slice(2);
|
|
11419
|
+
const destFeeTokenAllowanceSlot = await getStorageSlot(
|
|
11388
11420
|
this.dest.client,
|
|
11389
11421
|
destChainFeeTokenAddress,
|
|
11390
11422
|
destFeeTokenAllowanceData
|
|
@@ -11401,7 +11433,7 @@ var IntentGateway = class {
|
|
|
11401
11433
|
// Mock address with ETH balance so that any chain estimation runs
|
|
11402
11434
|
// even when the address doesn't hold any native token in that chain
|
|
11403
11435
|
{
|
|
11404
|
-
address:
|
|
11436
|
+
address: MOCK_ADDRESS,
|
|
11405
11437
|
balance: maxUint256
|
|
11406
11438
|
},
|
|
11407
11439
|
...orderOverrides.map((override) => ({
|
|
@@ -11414,7 +11446,7 @@ var IntentGateway = class {
|
|
|
11414
11446
|
address: intentGatewayAddress,
|
|
11415
11447
|
functionName: "fillOrder",
|
|
11416
11448
|
args: [transformOrderForContract(order), fillOptions],
|
|
11417
|
-
account:
|
|
11449
|
+
account: MOCK_ADDRESS,
|
|
11418
11450
|
value: totalEthValue,
|
|
11419
11451
|
stateOverride
|
|
11420
11452
|
});
|
|
@@ -11458,8 +11490,8 @@ var IntentGateway = class {
|
|
|
11458
11490
|
const v3Quoter = this.source.config.getUniswapV3QuoterAddress(chain);
|
|
11459
11491
|
const v4Quoter = this.source.config.getUniswapV4QuoterAddress(chain);
|
|
11460
11492
|
const wethAsset = this.source.config.getWrappedNativeAssetWithDecimals(chain).asset;
|
|
11461
|
-
const tokenInForQuote = tokenIn ===
|
|
11462
|
-
const tokenOutForQuote = tokenOut ===
|
|
11493
|
+
const tokenInForQuote = tokenIn === ADDRESS_ZERO ? wethAsset : tokenIn;
|
|
11494
|
+
const tokenOutForQuote = tokenOut === ADDRESS_ZERO ? wethAsset : tokenOut;
|
|
11463
11495
|
try {
|
|
11464
11496
|
const v2PairExists = await destClient.readContract({
|
|
11465
11497
|
address: v2Factory,
|
|
@@ -11467,7 +11499,7 @@ var IntentGateway = class {
|
|
|
11467
11499
|
functionName: "getPair",
|
|
11468
11500
|
args: [tokenInForQuote, tokenOutForQuote]
|
|
11469
11501
|
});
|
|
11470
|
-
if (v2PairExists !==
|
|
11502
|
+
if (v2PairExists !== ADDRESS_ZERO) {
|
|
11471
11503
|
const v2AmountIn = await destClient.readContract({
|
|
11472
11504
|
address: v2Router,
|
|
11473
11505
|
abi: uniswapRouterV2_default.ABI,
|
|
@@ -11488,7 +11520,7 @@ var IntentGateway = class {
|
|
|
11488
11520
|
functionName: "getPool",
|
|
11489
11521
|
args: [tokenInForQuote, tokenOutForQuote, fee]
|
|
11490
11522
|
});
|
|
11491
|
-
if (pool !==
|
|
11523
|
+
if (pool !== ADDRESS_ZERO) {
|
|
11492
11524
|
const liquidity = await destClient.readContract({
|
|
11493
11525
|
address: pool,
|
|
11494
11526
|
abi: uniswapV3Pool_default.ABI,
|
|
@@ -11532,7 +11564,7 @@ var IntentGateway = class {
|
|
|
11532
11564
|
currency1,
|
|
11533
11565
|
fee,
|
|
11534
11566
|
tickSpacing: this.getTickSpacing(fee),
|
|
11535
|
-
hooks:
|
|
11567
|
+
hooks: ADDRESS_ZERO
|
|
11536
11568
|
// No hooks
|
|
11537
11569
|
};
|
|
11538
11570
|
const quoteResult = (await destClient.simulateContract({
|
|
@@ -11622,8 +11654,8 @@ var IntentGateway = class {
|
|
|
11622
11654
|
const v3Quoter = this.source.config.getUniswapV3QuoterAddress(chain);
|
|
11623
11655
|
const v4Quoter = this.source.config.getUniswapV4QuoterAddress(chain);
|
|
11624
11656
|
const wethAsset = this.source.config.getWrappedNativeAssetWithDecimals(chain).asset;
|
|
11625
|
-
const tokenInForQuote = tokenIn ===
|
|
11626
|
-
const tokenOutForQuote = tokenOut ===
|
|
11657
|
+
const tokenInForQuote = tokenIn === ADDRESS_ZERO ? wethAsset : tokenIn;
|
|
11658
|
+
const tokenOutForQuote = tokenOut === ADDRESS_ZERO ? wethAsset : tokenOut;
|
|
11627
11659
|
try {
|
|
11628
11660
|
const v2PairExists = await destClient.readContract({
|
|
11629
11661
|
address: v2Factory,
|
|
@@ -11631,7 +11663,7 @@ var IntentGateway = class {
|
|
|
11631
11663
|
functionName: "getPair",
|
|
11632
11664
|
args: [tokenInForQuote, tokenOutForQuote]
|
|
11633
11665
|
});
|
|
11634
|
-
if (v2PairExists !==
|
|
11666
|
+
if (v2PairExists !== ADDRESS_ZERO) {
|
|
11635
11667
|
const v2AmountOut = await destClient.readContract({
|
|
11636
11668
|
address: v2Router,
|
|
11637
11669
|
abi: uniswapRouterV2_default.ABI,
|
|
@@ -11652,7 +11684,7 @@ var IntentGateway = class {
|
|
|
11652
11684
|
functionName: "getPool",
|
|
11653
11685
|
args: [tokenInForQuote, tokenOutForQuote, fee]
|
|
11654
11686
|
});
|
|
11655
|
-
if (pool !==
|
|
11687
|
+
if (pool !== ADDRESS_ZERO) {
|
|
11656
11688
|
const liquidity = await destClient.readContract({
|
|
11657
11689
|
address: pool,
|
|
11658
11690
|
abi: uniswapV3Pool_default.ABI,
|
|
@@ -11696,7 +11728,7 @@ var IntentGateway = class {
|
|
|
11696
11728
|
currency1,
|
|
11697
11729
|
fee,
|
|
11698
11730
|
tickSpacing: this.getTickSpacing(fee),
|
|
11699
|
-
hooks:
|
|
11731
|
+
hooks: ADDRESS_ZERO
|
|
11700
11732
|
// No hooks
|
|
11701
11733
|
};
|
|
11702
11734
|
const quoteResult = (await destClient.simulateContract({
|
|
@@ -11780,9 +11812,9 @@ var IntentGateway = class {
|
|
|
11780
11812
|
throw new Error("Chain native currency information not available");
|
|
11781
11813
|
}
|
|
11782
11814
|
const gasCostInToken = Number(gasCostInWei) / Math.pow(10, nativeToken.decimals);
|
|
11783
|
-
const tokenPriceUsd = await
|
|
11815
|
+
const tokenPriceUsd = await fetchTokenUsdPrice(nativeToken.symbol);
|
|
11784
11816
|
const gasCostUsd = gasCostInToken * tokenPriceUsd;
|
|
11785
|
-
const feeTokenPriceUsd = await
|
|
11817
|
+
const feeTokenPriceUsd = await fetchTokenUsdPrice("DAI");
|
|
11786
11818
|
const gasCostInFeeToken = gasCostUsd / feeTokenPriceUsd;
|
|
11787
11819
|
return BigInt(Math.floor(gasCostInFeeToken * Math.pow(10, targetDecimals)));
|
|
11788
11820
|
}
|
|
@@ -12150,6 +12182,6 @@ async function teleportDot(param_) {
|
|
|
12150
12182
|
return stream;
|
|
12151
12183
|
}
|
|
12152
12184
|
|
|
12153
|
-
export {
|
|
12185
|
+
export { ADDRESS_ZERO, ChainConfigService, Chains, DEFAULT_ADDRESS, DUMMY_PRIVATE_KEY, ERC20Method, EvmChain, HyperClientStatus, IndexerClient, IntentGateway, OrderStatus, REQUEST_COMMITMENTS_SLOT, REQUEST_RECEIPTS_SLOT, RESPONSE_COMMITMENTS_SLOT, RESPONSE_RECEIPTS_SLOT, RequestKind, RequestStatus, STATE_COMMITMENTS_SLOT, SubstrateChain, TeleportStatus, TimeoutStatus, WrappedNativeDecimals, __test, addresses, adjustFeeDecimals, assets, bytes20ToBytes32, bytes32ToBytes20, chainIds, consensusStateIds, constructRedeemEscrowRequestBody, convertStateMachineIdToEnum, createQueryClient, createRpcUrls, encodeISMPMessage, estimateGasForPost, fetchTokenUsdPrice, generateRootWithProof, getChain, getRequestCommitment, getStateCommitmentFieldSlot, getStateCommitmentSlot, getStorageSlot, hexToString, orderCommitment, postRequestCommitment, queryGetRequest, queryPostRequest, teleport, teleportDot, viemChains };
|
|
12154
12186
|
//# sourceMappingURL=index.js.map
|
|
12155
12187
|
//# sourceMappingURL=index.js.map
|