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