@hyperbridge/sdk 1.2.2 → 1.3.0-canary-000001
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 +629 -27
- package/dist/browser/index.js +2291 -2188
- package/dist/browser/index.js.map +1 -1
- package/dist/node/index.d.ts +629 -27
- package/dist/node/index.js +2294 -2191
- package/dist/node/index.js.map +1 -1
- package/package.json +2 -2
- package/plugins/vite.js +52 -39
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,1985 +3352,2243 @@ 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
|
-
|
|
3990
|
-
|
|
3991
|
-
|
|
3992
|
-
|
|
3993
|
-
|
|
3994
|
-
|
|
3995
|
-
|
|
3996
|
-
|
|
3539
|
+
pos: u64
|
|
3540
|
+
});
|
|
3541
|
+
var MmrProof = Struct({
|
|
3542
|
+
/*
|
|
3543
|
+
* Proof of the leaf index and position.
|
|
3544
|
+
*/
|
|
3545
|
+
leafIndexAndPos: Vector(LeafIndexAndPos),
|
|
3546
|
+
/*
|
|
3547
|
+
* Proof of the leaf data.
|
|
3548
|
+
*/
|
|
3549
|
+
leafCount: u64,
|
|
3550
|
+
/*
|
|
3551
|
+
* Proof elements (hashes of siblings of inner nodes on the path to the leaf).
|
|
3552
|
+
*/
|
|
3553
|
+
items: Vector(H256)
|
|
3554
|
+
});
|
|
3555
|
+
var ConsensusStateId = Vector(u8, 4);
|
|
3556
|
+
var ConsensusMessage = Struct({
|
|
3557
|
+
/*
|
|
3558
|
+
* Consensus message data.
|
|
3559
|
+
*/
|
|
3560
|
+
consensusProof: Vector(u8),
|
|
3561
|
+
/*
|
|
3562
|
+
* Consensus state Id
|
|
3563
|
+
*/
|
|
3564
|
+
consensusStateId: ConsensusStateId,
|
|
3565
|
+
/*
|
|
3566
|
+
* Public key of the sender
|
|
3567
|
+
*/
|
|
3568
|
+
signer: Vector(u8)
|
|
3569
|
+
});
|
|
3570
|
+
var FraudProofMessage = Struct({
|
|
3571
|
+
/*
|
|
3572
|
+
* The first valid consensus proof
|
|
3573
|
+
*/
|
|
3574
|
+
proof1: Vector(u8),
|
|
3575
|
+
/*
|
|
3576
|
+
* The second valid consensus proof
|
|
3577
|
+
*/
|
|
3578
|
+
proof2: Vector(u8),
|
|
3579
|
+
/*
|
|
3580
|
+
* Consensus state Id
|
|
3581
|
+
*/
|
|
3582
|
+
consensusStateId: ConsensusStateId
|
|
3583
|
+
});
|
|
3584
|
+
var StateMachine = Enum({
|
|
3585
|
+
/*
|
|
3586
|
+
* Evm state machines
|
|
3587
|
+
*/
|
|
3588
|
+
Evm: u32,
|
|
3589
|
+
/*
|
|
3590
|
+
* Polkadot parachains
|
|
3591
|
+
*/
|
|
3592
|
+
Polkadot: u32,
|
|
3593
|
+
/*
|
|
3594
|
+
* Kusama parachains
|
|
3595
|
+
*/
|
|
3596
|
+
Kusama: u32,
|
|
3597
|
+
/*
|
|
3598
|
+
* Substrate-based standalone chain
|
|
3599
|
+
*/
|
|
3600
|
+
Substrate: ConsensusStateId,
|
|
3601
|
+
/*
|
|
3602
|
+
* Tendermint chains
|
|
3603
|
+
*/
|
|
3604
|
+
Tendermint: ConsensusStateId
|
|
3605
|
+
});
|
|
3606
|
+
var StateMachineId = Struct({
|
|
3607
|
+
/*
|
|
3608
|
+
* The state machine id
|
|
3609
|
+
*/
|
|
3610
|
+
id: StateMachine,
|
|
3611
|
+
/*
|
|
3612
|
+
* The consensus state id
|
|
3613
|
+
*/
|
|
3614
|
+
consensusStateId: ConsensusStateId
|
|
3615
|
+
});
|
|
3616
|
+
var StateMachineHeight = Struct({
|
|
3617
|
+
/*
|
|
3618
|
+
* The state machine id
|
|
3619
|
+
*/
|
|
3620
|
+
id: StateMachineId,
|
|
3621
|
+
/*
|
|
3622
|
+
* The height of the state machine
|
|
3623
|
+
*/
|
|
3624
|
+
height: u64
|
|
3625
|
+
});
|
|
3626
|
+
var Proof = Struct({
|
|
3627
|
+
/*
|
|
3628
|
+
* The height of the state machine
|
|
3629
|
+
*/
|
|
3630
|
+
height: StateMachineHeight,
|
|
3631
|
+
/*
|
|
3632
|
+
* The proof
|
|
3633
|
+
*/
|
|
3634
|
+
proof: Vector(u8)
|
|
3635
|
+
});
|
|
3636
|
+
var PostRequest = Struct({
|
|
3637
|
+
/*
|
|
3638
|
+
* The source state machine of this request.
|
|
3639
|
+
*/
|
|
3640
|
+
source: StateMachine,
|
|
3641
|
+
/*
|
|
3642
|
+
* The destination state machine of this request.
|
|
3643
|
+
*/
|
|
3644
|
+
dest: StateMachine,
|
|
3645
|
+
/*
|
|
3646
|
+
* The nonce of this request on the source chain
|
|
3647
|
+
*/
|
|
3648
|
+
nonce: u64,
|
|
3649
|
+
/*
|
|
3650
|
+
* Module identifier of the sending module
|
|
3651
|
+
*/
|
|
3652
|
+
from: Vector(u8),
|
|
3653
|
+
/*
|
|
3654
|
+
* Module identifier of the receiving module
|
|
3655
|
+
*/
|
|
3656
|
+
to: Vector(u8),
|
|
3657
|
+
/*
|
|
3658
|
+
* Timestamp which this request expires in seconds.
|
|
3659
|
+
*/
|
|
3660
|
+
timeoutTimestamp: u64,
|
|
3661
|
+
/*
|
|
3662
|
+
* Encoded request body
|
|
3663
|
+
*/
|
|
3664
|
+
body: Vector(u8)
|
|
3665
|
+
});
|
|
3666
|
+
var PostResponse = Struct({
|
|
3667
|
+
/*
|
|
3668
|
+
* The request that triggered this response.
|
|
3669
|
+
*/
|
|
3670
|
+
post: PostRequest,
|
|
3671
|
+
/*
|
|
3672
|
+
* The response message.
|
|
3673
|
+
*/
|
|
3674
|
+
response: Vector(u8),
|
|
3675
|
+
/*
|
|
3676
|
+
* Timestamp at which this response expires in seconds.
|
|
3677
|
+
*/
|
|
3678
|
+
timeoutTimestamp: u64
|
|
3679
|
+
});
|
|
3680
|
+
var GetRequest = Struct({
|
|
3681
|
+
/*
|
|
3682
|
+
* The source state machine of this request.
|
|
3683
|
+
*/
|
|
3684
|
+
source: StateMachine,
|
|
3685
|
+
/*
|
|
3686
|
+
* The destination state machine of this request.
|
|
3687
|
+
*/
|
|
3688
|
+
dest: StateMachine,
|
|
3689
|
+
/*
|
|
3690
|
+
* The nonce of this request on the source chain
|
|
3691
|
+
*/
|
|
3692
|
+
nonce: u64,
|
|
3693
|
+
/*
|
|
3694
|
+
* Module identifier of the sending module
|
|
3695
|
+
*/
|
|
3696
|
+
from: Vector(u8),
|
|
3697
|
+
/*
|
|
3698
|
+
* Raw Storage keys that would be used to fetch the values from the counterparty
|
|
3699
|
+
* For deriving storage keys for ink contract fields follow the guide in the link below
|
|
3700
|
+
* `<https://use.ink/datastructures/storage-in-metadata#a-full-example>`
|
|
3701
|
+
* Substrate Keys
|
|
3702
|
+
*/
|
|
3703
|
+
keys: Vector(Vector(u8)),
|
|
3704
|
+
/*
|
|
3705
|
+
* Some application-specific metadata relating to this request
|
|
3706
|
+
*/
|
|
3707
|
+
context: Vector(u8),
|
|
3708
|
+
/*
|
|
3709
|
+
* Host timestamp at which this request expires in seconds
|
|
3710
|
+
*/
|
|
3711
|
+
timeoutTimestamp: u64
|
|
3712
|
+
});
|
|
3713
|
+
var StorageValue = Struct({
|
|
3714
|
+
/*
|
|
3715
|
+
* The request storage keys
|
|
3716
|
+
*/
|
|
3717
|
+
key: Vector(u8),
|
|
3718
|
+
/*
|
|
3719
|
+
* The verified value
|
|
3720
|
+
*/
|
|
3721
|
+
value: Option(Vector(u8))
|
|
3722
|
+
});
|
|
3723
|
+
var GetResponse = Struct({
|
|
3724
|
+
/*
|
|
3725
|
+
* The Get request that triggered this response.
|
|
3726
|
+
*/
|
|
3727
|
+
get: GetRequest,
|
|
3728
|
+
/*
|
|
3729
|
+
* Values derived from the state proof
|
|
3730
|
+
*/
|
|
3731
|
+
values: Vector(StorageValue)
|
|
3732
|
+
});
|
|
3733
|
+
var Request2 = Enum({
|
|
3734
|
+
/*
|
|
3735
|
+
* A post request allows a module on a state machine to send arbitrary bytes to another module
|
|
3736
|
+
* living in another state machine.
|
|
3737
|
+
*/
|
|
3738
|
+
Post: PostRequest,
|
|
3739
|
+
/*
|
|
3740
|
+
* A get request allows a module on a state machine to read the storage of another module
|
|
3741
|
+
* living in another state machine.
|
|
3742
|
+
*/
|
|
3743
|
+
Get: GetRequest
|
|
3744
|
+
});
|
|
3745
|
+
var Response2 = Enum({
|
|
3746
|
+
/*
|
|
3747
|
+
* The response to a POST request
|
|
3748
|
+
*/
|
|
3749
|
+
Post: PostResponse,
|
|
3750
|
+
/*
|
|
3751
|
+
* The response to a GET request
|
|
3752
|
+
*/
|
|
3753
|
+
Get: GetResponse
|
|
3754
|
+
});
|
|
3755
|
+
var RequestMessage = Struct({
|
|
3756
|
+
/*
|
|
3757
|
+
* Requests from source chain
|
|
3758
|
+
*/
|
|
3759
|
+
requests: Vector(PostRequest),
|
|
3760
|
+
/*
|
|
3761
|
+
* Membership batch proof for these requests
|
|
3762
|
+
*/
|
|
3763
|
+
proof: Proof,
|
|
3764
|
+
/*
|
|
3765
|
+
* Signer information. Ideally should be their account identifier
|
|
3766
|
+
*/
|
|
3767
|
+
signer: Vector(u8)
|
|
3768
|
+
});
|
|
3769
|
+
var RequestResponse = Enum({
|
|
3770
|
+
/*
|
|
3771
|
+
* A set of requests
|
|
3772
|
+
*/
|
|
3773
|
+
Request: Vector(Request2),
|
|
3774
|
+
/*
|
|
3775
|
+
* A set of responses
|
|
3776
|
+
*/
|
|
3777
|
+
Response: Vector(Response2)
|
|
3778
|
+
});
|
|
3779
|
+
var ResponseMessage = Struct({
|
|
3780
|
+
/*
|
|
3781
|
+
* A set of either POST requests or responses to be handled
|
|
3782
|
+
*/
|
|
3783
|
+
datagram: Vector(RequestResponse),
|
|
3784
|
+
/*
|
|
3785
|
+
* Membership batch proof for these requests/responses
|
|
3786
|
+
*/
|
|
3787
|
+
proof: Proof,
|
|
3788
|
+
/*
|
|
3789
|
+
* Signer information. Ideally should be their account identifier
|
|
3790
|
+
*/
|
|
3791
|
+
signer: Vector(u8)
|
|
3792
|
+
});
|
|
3793
|
+
var TimeoutMessage = Enum({
|
|
3794
|
+
/*
|
|
3795
|
+
* A non memership proof for POST requests
|
|
3796
|
+
*/
|
|
3797
|
+
Post: Struct({
|
|
3798
|
+
/*
|
|
3799
|
+
* Timed out requests
|
|
3800
|
+
*/
|
|
3801
|
+
requests: Vector(Request2),
|
|
3802
|
+
/*
|
|
3803
|
+
* Membership batch proof for these requests
|
|
3804
|
+
*/
|
|
3805
|
+
proof: Proof
|
|
3806
|
+
}),
|
|
3807
|
+
/*
|
|
3808
|
+
* A non memership proof for POST responses
|
|
3809
|
+
*/
|
|
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.`);
|
|
3997
3922
|
}
|
|
3998
|
-
|
|
3999
|
-
|
|
4000
|
-
|
|
4001
|
-
|
|
4002
|
-
|
|
4003
|
-
|
|
4004
|
-
|
|
4005
|
-
|
|
4006
|
-
|
|
4007
|
-
|
|
4008
|
-
|
|
4009
|
-
|
|
4010
|
-
|
|
4011
|
-
|
|
4012
|
-
|
|
4013
|
-
|
|
4014
|
-
|
|
4015
|
-
|
|
4016
|
-
|
|
4017
|
-
|
|
4018
|
-
|
|
4019
|
-
|
|
4020
|
-
|
|
4021
|
-
},
|
|
4022
|
-
|
|
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,
|
|
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" },
|
|
4039
3948
|
{
|
|
4040
|
-
|
|
4041
|
-
|
|
4042
|
-
|
|
4043
|
-
|
|
4044
|
-
|
|
4045
|
-
|
|
4046
|
-
|
|
4047
|
-
|
|
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,
|
|
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
|
+
},
|
|
4055
3957
|
{
|
|
4056
|
-
|
|
4057
|
-
|
|
4058
|
-
|
|
4059
|
-
|
|
4060
|
-
|
|
4061
|
-
|
|
4062
|
-
|
|
4063
|
-
|
|
4064
|
-
from: req.from,
|
|
4065
|
-
nonce: req.nonce,
|
|
4066
|
-
timeoutTimestamp: req.timeoutTimestamp,
|
|
4067
|
-
body: req.body
|
|
4068
|
-
})),
|
|
4069
|
-
proof
|
|
4070
|
-
}
|
|
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" }
|
|
4071
3966
|
]
|
|
4072
|
-
}
|
|
4073
|
-
|
|
4074
|
-
|
|
4075
|
-
|
|
4076
|
-
|
|
4077
|
-
|
|
4078
|
-
|
|
4079
|
-
|
|
4080
|
-
|
|
4081
|
-
|
|
4082
|
-
|
|
4083
|
-
|
|
4084
|
-
|
|
4085
|
-
|
|
4086
|
-
|
|
4087
|
-
|
|
4088
|
-
|
|
4089
|
-
|
|
4090
|
-
|
|
4091
|
-
|
|
4092
|
-
|
|
4093
|
-
|
|
4094
|
-
|
|
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)
|
|
4095
4101
|
},
|
|
4096
|
-
index
|
|
4102
|
+
index,
|
|
4097
4103
|
kIndex
|
|
4098
|
-
}
|
|
4099
|
-
|
|
4100
|
-
|
|
4101
|
-
|
|
4102
|
-
|
|
4103
|
-
|
|
4104
|
-
|
|
4105
|
-
|
|
4106
|
-
|
|
4107
|
-
|
|
4108
|
-
|
|
4109
|
-
|
|
4110
|
-
|
|
4111
|
-
args: [
|
|
4112
|
-
this.params.host,
|
|
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: [
|
|
4113
4117
|
{
|
|
4114
|
-
|
|
4115
|
-
|
|
4118
|
+
slot: overlayRootSlot,
|
|
4119
|
+
value: root
|
|
4116
4120
|
}
|
|
4117
4121
|
]
|
|
4118
|
-
}
|
|
4119
|
-
|
|
4120
|
-
|
|
4121
|
-
|
|
4122
|
-
|
|
4123
|
-
|
|
4124
|
-
|
|
4125
|
-
|
|
4126
|
-
|
|
4127
|
-
|
|
4128
|
-
|
|
4129
|
-
|
|
4130
|
-
|
|
4131
|
-
|
|
4132
|
-
|
|
4133
|
-
|
|
4134
|
-
|
|
4135
|
-
|
|
4136
|
-
|
|
4137
|
-
|
|
4138
|
-
|
|
4139
|
-
|
|
4140
|
-
|
|
4141
|
-
|
|
4142
|
-
|
|
4143
|
-
|
|
4144
|
-
|
|
4145
|
-
|
|
4146
|
-
|
|
4147
|
-
|
|
4148
|
-
|
|
4149
|
-
|
|
4150
|
-
|
|
4151
|
-
|
|
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
|
|
4217
|
-
*/
|
|
4218
|
-
async getFeeTokenWithDecimals() {
|
|
4219
|
-
const hostParams = await this.publicClient.readContract({
|
|
4220
|
-
abi: evmHost_default.ABI,
|
|
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
|
|
4237
|
-
*/
|
|
4238
|
-
async getHostNonce() {
|
|
4239
|
-
const nonce = await this.publicClient.readContract({
|
|
4240
|
-
abi: evmHost_default.ABI,
|
|
4241
|
-
address: this.params.host,
|
|
4242
|
-
functionName: "nonce"
|
|
4243
|
-
});
|
|
4244
|
-
return nonce;
|
|
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`;
|
|
4245
4162
|
}
|
|
4163
|
+
return new Date(date).getTime();
|
|
4246
4164
|
};
|
|
4247
|
-
|
|
4248
|
-
|
|
4249
|
-
|
|
4250
|
-
|
|
4251
|
-
|
|
4252
|
-
|
|
4253
|
-
|
|
4254
|
-
|
|
4255
|
-
|
|
4256
|
-
|
|
4257
|
-
|
|
4258
|
-
|
|
4259
|
-
|
|
4260
|
-
|
|
4261
|
-
|
|
4262
|
-
|
|
4263
|
-
|
|
4264
|
-
|
|
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
|
+
}
|
|
4265
4189
|
}
|
|
4266
|
-
function
|
|
4267
|
-
|
|
4268
|
-
|
|
4269
|
-
|
|
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
|
+
}
|
|
4270
4205
|
}
|
|
4271
|
-
function
|
|
4272
|
-
const
|
|
4273
|
-
const
|
|
4274
|
-
|
|
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;
|
|
4275
4219
|
}
|
|
4276
|
-
function
|
|
4277
|
-
const
|
|
4278
|
-
|
|
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;
|
|
4279
4234
|
}
|
|
4280
|
-
|
|
4281
|
-
|
|
4282
|
-
|
|
4283
|
-
|
|
4284
|
-
|
|
4285
|
-
|
|
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}`);
|
|
4286
4268
|
}
|
|
4287
|
-
function
|
|
4288
|
-
|
|
4289
|
-
|
|
4290
|
-
|
|
4291
|
-
|
|
4292
|
-
|
|
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
|
+
}
|
|
4293
4278
|
}
|
|
4294
|
-
|
|
4295
|
-
|
|
4296
|
-
|
|
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;
|
|
4297
4286
|
}
|
|
4298
|
-
|
|
4299
|
-
|
|
4300
|
-
*/
|
|
4301
|
-
api;
|
|
4302
|
-
/*
|
|
4303
|
-
* connect: Connects to the Substrate chain using the provided WebSocket URL.
|
|
4304
|
-
*/
|
|
4305
|
-
async connect() {
|
|
4306
|
-
const wsProvider = new WsProvider(this.params.ws);
|
|
4307
|
-
const typesBundle = this.params.hasher === "Keccak" ? {
|
|
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
|
-
});
|
|
4287
|
+
static isError(error) {
|
|
4288
|
+
return error instanceof _AbortSignalInternal;
|
|
4321
4289
|
}
|
|
4322
|
-
|
|
4323
|
-
|
|
4324
|
-
|
|
4325
|
-
|
|
4326
|
-
|
|
4327
|
-
|
|
4328
|
-
this.api = void 0;
|
|
4329
|
-
}
|
|
4290
|
+
};
|
|
4291
|
+
var ExpectedError = class _ExpectedError extends Error {
|
|
4292
|
+
constructor(message) {
|
|
4293
|
+
super();
|
|
4294
|
+
this.name = "Hyperbridge/SDK/ExpectedError";
|
|
4295
|
+
this.message = message;
|
|
4330
4296
|
}
|
|
4331
|
-
|
|
4332
|
-
|
|
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
|
|
4336
|
-
*/
|
|
4337
|
-
requestReceiptKey(key) {
|
|
4338
|
-
const prefix = new TextEncoder().encode("RequestReceipts");
|
|
4339
|
-
const keyBytes = hexToBytes(key);
|
|
4340
|
-
return bytesToHex(new Uint8Array([...prefix, ...keyBytes]));
|
|
4297
|
+
static isError(error) {
|
|
4298
|
+
return error instanceof _ExpectedError;
|
|
4341
4299
|
}
|
|
4342
|
-
|
|
4343
|
-
|
|
4344
|
-
|
|
4345
|
-
|
|
4346
|
-
|
|
4347
|
-
|
|
4348
|
-
|
|
4349
|
-
|
|
4350
|
-
|
|
4351
|
-
|
|
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 */]: "0x4752ba5DBc23f44D87826276BF6Fd6b1C372aD24"
|
|
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 */]: "0x8909Dc15e40173Ff4699343b6eB8132c65e18eC6"
|
|
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"
|
|
4352
4430
|
}
|
|
4353
|
-
|
|
4354
|
-
|
|
4355
|
-
|
|
4356
|
-
|
|
4357
|
-
|
|
4358
|
-
|
|
4359
|
-
|
|
4360
|
-
|
|
4361
|
-
|
|
4362
|
-
|
|
4363
|
-
|
|
4364
|
-
|
|
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);
|
|
4365
4454
|
}
|
|
4366
|
-
|
|
4367
|
-
|
|
4368
|
-
|
|
4369
|
-
|
|
4370
|
-
|
|
4371
|
-
|
|
4372
|
-
const prefix = toHex(":child_storage:default:ISMP");
|
|
4373
|
-
const key = this.requestReceiptKey(commitment);
|
|
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;
|
|
4455
|
+
getChainConfig(chain) {
|
|
4456
|
+
return {
|
|
4457
|
+
chainId: chainIds[chain],
|
|
4458
|
+
rpcUrl: this.rpcUrls[chain],
|
|
4459
|
+
intentGatewayAddress: addresses.IntentGateway[chain]
|
|
4460
|
+
};
|
|
4378
4461
|
}
|
|
4379
|
-
|
|
4380
|
-
|
|
4381
|
-
* @returns {Promise<bigint>} The current timestamp.
|
|
4382
|
-
*/
|
|
4383
|
-
async timestamp() {
|
|
4384
|
-
if (!this.api) throw new Error("API not initialized");
|
|
4385
|
-
const now = await this.api.query.timestamp.now();
|
|
4386
|
-
return BigInt(now.toJSON()) / BigInt(1e3);
|
|
4462
|
+
getIntentGatewayAddress(chain) {
|
|
4463
|
+
return addresses.IntentGateway[chain];
|
|
4387
4464
|
}
|
|
4388
|
-
|
|
4389
|
-
|
|
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.
|
|
4394
|
-
*/
|
|
4395
|
-
async queryProof(message, counterparty, at) {
|
|
4396
|
-
const rpc = new RpcWebSocketClient();
|
|
4397
|
-
await rpc.connect(this.params.ws);
|
|
4398
|
-
if (isEvmChain(counterparty)) {
|
|
4399
|
-
const proof = await rpc.call("mmr_queryProof", [Number(at), message]);
|
|
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}`);
|
|
4465
|
+
getHostAddress(chain) {
|
|
4466
|
+
return addresses.Host[chain];
|
|
4419
4467
|
}
|
|
4420
|
-
|
|
4421
|
-
|
|
4422
|
-
|
|
4423
|
-
|
|
4424
|
-
|
|
4425
|
-
async submitUnsigned(message) {
|
|
4426
|
-
if (!this.api) throw new Error("API not initialized");
|
|
4427
|
-
const { api } = this;
|
|
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
|
-
});
|
|
4468
|
+
getWrappedNativeAssetWithDecimals(chain) {
|
|
4469
|
+
return {
|
|
4470
|
+
asset: assets[chain].WETH,
|
|
4471
|
+
decimals: WrappedNativeDecimals[chain]
|
|
4472
|
+
};
|
|
4455
4473
|
}
|
|
4456
|
-
|
|
4457
|
-
|
|
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.
|
|
4461
|
-
*/
|
|
4462
|
-
async queryStateProof(at, keys) {
|
|
4463
|
-
const rpc = new RpcWebSocketClient();
|
|
4464
|
-
await rpc.connect(this.params.ws);
|
|
4465
|
-
const encodedKeys = keys.map((key) => Array.from(hexToBytes(key)));
|
|
4466
|
-
const proof = await rpc.call("ismp_queryChildTrieProof", [Number(at), encodedKeys]);
|
|
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);
|
|
4474
|
+
getDaiAsset(chain) {
|
|
4475
|
+
return assets[chain].DAI;
|
|
4479
4476
|
}
|
|
4480
|
-
|
|
4481
|
-
|
|
4482
|
-
* @param {StateMachineIdParams} stateMachineId - The state machine ID.
|
|
4483
|
-
* @returns {Promise<bigint>} The latest state machine height.
|
|
4484
|
-
*/
|
|
4485
|
-
async latestStateMachineHeight(stateMachineId) {
|
|
4486
|
-
if (!this.api) throw new Error("API not initialized");
|
|
4487
|
-
const latestHeight = await this.api.query.ismp.latestStateMachineHeight(stateMachineId);
|
|
4488
|
-
return BigInt(latestHeight.toString());
|
|
4477
|
+
getUsdtAsset(chain) {
|
|
4478
|
+
return assets[chain].USDT;
|
|
4489
4479
|
}
|
|
4490
|
-
|
|
4491
|
-
|
|
4492
|
-
* @param {StateMachineHeight} stateMachineheight - The state machine height.
|
|
4493
|
-
* @returns {Promise<bigint>} The statemachine update time in seconds.
|
|
4494
|
-
*/
|
|
4495
|
-
async stateMachineUpdateTime(stateMachineHeight) {
|
|
4496
|
-
if (!this.api) throw new Error("API not initialized");
|
|
4497
|
-
const updateTime = await this.api.query.ismp.stateMachineUpdateTime(stateMachineHeight);
|
|
4498
|
-
return BigInt(updateTime.toString());
|
|
4480
|
+
getUsdcAsset(chain) {
|
|
4481
|
+
return assets[chain].USDC;
|
|
4499
4482
|
}
|
|
4500
|
-
|
|
4501
|
-
|
|
4502
|
-
* @param {StateMachineIdParams} stateMachineId - The state machine ID.
|
|
4503
|
-
* @returns {Promise<bigint>} The challenge period in seconds.
|
|
4504
|
-
*/
|
|
4505
|
-
async challengePeriod(stateMachineId) {
|
|
4506
|
-
if (!this.api) throw new Error("API not initialized");
|
|
4507
|
-
const challengePeriod = await this.api.query.ismp.challengePeriod(stateMachineId);
|
|
4508
|
-
return BigInt(challengePeriod.toString());
|
|
4483
|
+
getChainId(chain) {
|
|
4484
|
+
return chainIds[chain];
|
|
4509
4485
|
}
|
|
4510
|
-
|
|
4511
|
-
|
|
4512
|
-
* @param message The ISMP message to encode.
|
|
4513
|
-
* @returns The encoded message as a hexadecimal string.
|
|
4514
|
-
*/
|
|
4515
|
-
encode(message) {
|
|
4516
|
-
const palletIndex = this.getPalletIndex("Ismp");
|
|
4517
|
-
const args = encodeISMPMessage(message);
|
|
4518
|
-
const call = Vector(u8, 2).enc([palletIndex, 0]);
|
|
4519
|
-
return toHex(new Uint8Array([...call, ...args]));
|
|
4486
|
+
getConsensusStateId(chain) {
|
|
4487
|
+
return toHex(consensusStateIds[chain]);
|
|
4520
4488
|
}
|
|
4521
|
-
|
|
4522
|
-
|
|
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`);
|
|
4489
|
+
getHyperbridgeChainId() {
|
|
4490
|
+
return chainIds["KUSAMA-4009" /* HYPERBRIDGE_GARGANTUA */];
|
|
4536
4491
|
}
|
|
4537
|
-
|
|
4538
|
-
|
|
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));
|
|
4492
|
+
getRpcUrl(chain) {
|
|
4493
|
+
return this.rpcUrls[chain];
|
|
4555
4494
|
}
|
|
4556
|
-
|
|
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 });
|
|
4495
|
+
getUniswapRouterV2Address(chain) {
|
|
4496
|
+
return addresses.UniswapRouter02[chain];
|
|
4623
4497
|
}
|
|
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;
|
|
4498
|
+
getUniswapV2FactoryAddress(chain) {
|
|
4499
|
+
return addresses.UniswapV2Factory[chain];
|
|
4637
4500
|
}
|
|
4638
|
-
|
|
4639
|
-
|
|
4640
|
-
const substrateChain = new SubstrateChain({
|
|
4641
|
-
ws: config.wsUrl,
|
|
4642
|
-
hasher: config.hasher
|
|
4643
|
-
});
|
|
4644
|
-
await substrateChain.connect();
|
|
4645
|
-
return substrateChain;
|
|
4501
|
+
getBatchExecutorAddress(chain) {
|
|
4502
|
+
return addresses.BatchExecutor[chain];
|
|
4646
4503
|
}
|
|
4647
|
-
|
|
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);
|
|
4504
|
+
getUniversalRouterAddress(chain) {
|
|
4505
|
+
return addresses.UniversalRouter[chain];
|
|
4660
4506
|
}
|
|
4661
|
-
|
|
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;
|
|
4507
|
+
getUniswapV3RouterAddress(chain) {
|
|
4508
|
+
return addresses.UniswapV3Router[chain];
|
|
4673
4509
|
}
|
|
4674
|
-
|
|
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);
|
|
4510
|
+
getUniswapV3FactoryAddress(chain) {
|
|
4511
|
+
return addresses.UniswapV3Factory[chain];
|
|
4685
4512
|
}
|
|
4686
|
-
|
|
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);
|
|
4513
|
+
getUniswapV3QuoterAddress(chain) {
|
|
4514
|
+
return addresses.UniswapV3Quoter[chain];
|
|
4701
4515
|
}
|
|
4702
|
-
|
|
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;
|
|
4516
|
+
getUniswapV4PoolManagerAddress(chain) {
|
|
4517
|
+
return addresses.UniswapV4PoolManager[chain];
|
|
4716
4518
|
}
|
|
4717
|
-
|
|
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
|
-
}
|
|
4519
|
+
getUniswapV4QuoterAddress(chain) {
|
|
4520
|
+
return addresses.UniswapV4Quoter[chain];
|
|
4744
4521
|
}
|
|
4745
|
-
|
|
4746
|
-
|
|
4747
|
-
|
|
4748
|
-
|
|
4749
|
-
|
|
4750
|
-
|
|
4751
|
-
|
|
4752
|
-
|
|
4753
|
-
|
|
4754
|
-
|
|
4755
|
-
|
|
4756
|
-
|
|
4757
|
-
|
|
4758
|
-
|
|
4759
|
-
|
|
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();
|
|
4760
4549
|
}
|
|
4761
|
-
|
|
4762
|
-
|
|
4763
|
-
|
|
4764
|
-
|
|
4765
|
-
|
|
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;
|
|
4550
|
+
publicClient;
|
|
4551
|
+
chainConfigService;
|
|
4552
|
+
// Expose minimal getters for external helpers/classes
|
|
4553
|
+
get client() {
|
|
4554
|
+
return this.publicClient;
|
|
4776
4555
|
}
|
|
4777
|
-
|
|
4778
|
-
|
|
4779
|
-
|
|
4556
|
+
get host() {
|
|
4557
|
+
return this.params.host;
|
|
4558
|
+
}
|
|
4559
|
+
get config() {
|
|
4560
|
+
return this.chainConfigService;
|
|
4780
4561
|
}
|
|
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
4562
|
/**
|
|
4810
|
-
*
|
|
4811
|
-
|
|
4812
|
-
|
|
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.
|
|
4933
|
-
*/
|
|
4934
|
-
source: StateMachine,
|
|
4935
|
-
/*
|
|
4936
|
-
* The destination state machine of this request.
|
|
4937
|
-
*/
|
|
4938
|
-
dest: StateMachine,
|
|
4939
|
-
/*
|
|
4940
|
-
* The nonce of this request on the source chain
|
|
4941
|
-
*/
|
|
4942
|
-
nonce: u64,
|
|
4943
|
-
/*
|
|
4944
|
-
* Module identifier of the sending module
|
|
4945
|
-
*/
|
|
4946
|
-
from: Vector(u8),
|
|
4947
|
-
/*
|
|
4948
|
-
* Module identifier of the receiving module
|
|
4949
|
-
*/
|
|
4950
|
-
to: Vector(u8),
|
|
4951
|
-
/*
|
|
4952
|
-
* Timestamp which this request expires in seconds.
|
|
4953
|
-
*/
|
|
4954
|
-
timeoutTimestamp: u64,
|
|
4955
|
-
/*
|
|
4956
|
-
* Encoded request body
|
|
4957
|
-
*/
|
|
4958
|
-
body: Vector(u8)
|
|
4959
|
-
});
|
|
4960
|
-
var PostResponse = Struct({
|
|
4961
|
-
/*
|
|
4962
|
-
* The request that triggered this response.
|
|
4963
|
-
*/
|
|
4964
|
-
post: PostRequest,
|
|
4965
|
-
/*
|
|
4966
|
-
* The response message.
|
|
4967
|
-
*/
|
|
4968
|
-
response: Vector(u8),
|
|
4969
|
-
/*
|
|
4970
|
-
* Timestamp at which this response expires in seconds.
|
|
4971
|
-
*/
|
|
4972
|
-
timeoutTimestamp: u64
|
|
4973
|
-
});
|
|
4974
|
-
var GetRequest = Struct({
|
|
4975
|
-
/*
|
|
4976
|
-
* The source state machine of this request.
|
|
4977
|
-
*/
|
|
4978
|
-
source: StateMachine,
|
|
4979
|
-
/*
|
|
4980
|
-
* The destination state machine of this request.
|
|
4981
|
-
*/
|
|
4982
|
-
dest: StateMachine,
|
|
4983
|
-
/*
|
|
4984
|
-
* The nonce of this request on the source chain
|
|
4985
|
-
*/
|
|
4986
|
-
nonce: u64,
|
|
4987
|
-
/*
|
|
4988
|
-
* Module identifier of the sending module
|
|
4989
|
-
*/
|
|
4990
|
-
from: Vector(u8),
|
|
4991
|
-
/*
|
|
4992
|
-
* Raw Storage keys that would be used to fetch the values from the counterparty
|
|
4993
|
-
* For deriving storage keys for ink contract fields follow the guide in the link below
|
|
4994
|
-
* `<https://use.ink/datastructures/storage-in-metadata#a-full-example>`
|
|
4995
|
-
* Substrate Keys
|
|
4996
|
-
*/
|
|
4997
|
-
keys: Vector(Vector(u8)),
|
|
4998
|
-
/*
|
|
4999
|
-
* Some application-specific metadata relating to this request
|
|
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.
|
|
5000
4566
|
*/
|
|
5001
|
-
|
|
5002
|
-
|
|
5003
|
-
|
|
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.
|
|
5004
4574
|
*/
|
|
5005
|
-
|
|
5006
|
-
|
|
5007
|
-
|
|
5008
|
-
|
|
5009
|
-
|
|
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.
|
|
5010
4590
|
*/
|
|
5011
|
-
|
|
5012
|
-
|
|
5013
|
-
|
|
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.
|
|
5014
4617
|
*/
|
|
5015
|
-
|
|
5016
|
-
|
|
5017
|
-
|
|
5018
|
-
|
|
5019
|
-
|
|
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.
|
|
5020
4641
|
*/
|
|
5021
|
-
|
|
5022
|
-
|
|
5023
|
-
|
|
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.
|
|
5024
4654
|
*/
|
|
5025
|
-
|
|
5026
|
-
|
|
5027
|
-
|
|
5028
|
-
|
|
5029
|
-
|
|
5030
|
-
|
|
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.
|
|
5031
4674
|
*/
|
|
5032
|
-
|
|
5033
|
-
|
|
5034
|
-
|
|
5035
|
-
|
|
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.
|
|
5036
4691
|
*/
|
|
5037
|
-
|
|
5038
|
-
|
|
5039
|
-
|
|
5040
|
-
|
|
5041
|
-
|
|
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.
|
|
5042
4710
|
*/
|
|
5043
|
-
|
|
5044
|
-
|
|
5045
|
-
|
|
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
|
|
5046
4838
|
*/
|
|
5047
|
-
|
|
5048
|
-
|
|
5049
|
-
|
|
5050
|
-
|
|
5051
|
-
|
|
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 and the generated calldata
|
|
5052
4859
|
*/
|
|
5053
|
-
|
|
5054
|
-
|
|
5055
|
-
|
|
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 formattedRequest = {
|
|
4886
|
+
...request,
|
|
4887
|
+
source: toHex(request.source),
|
|
4888
|
+
dest: toHex(request.dest)
|
|
4889
|
+
};
|
|
4890
|
+
const contractArgs = [
|
|
4891
|
+
this.params.host,
|
|
4892
|
+
{
|
|
4893
|
+
proof: postParams,
|
|
4894
|
+
requests: [
|
|
4895
|
+
{
|
|
4896
|
+
request: formattedRequest,
|
|
4897
|
+
index,
|
|
4898
|
+
kIndex
|
|
4899
|
+
}
|
|
4900
|
+
]
|
|
4901
|
+
}
|
|
4902
|
+
];
|
|
4903
|
+
const postRequestCalldata = encodeFunctionData({
|
|
4904
|
+
abi: handler_default.ABI,
|
|
4905
|
+
functionName: "handlePostRequests",
|
|
4906
|
+
args: contractArgs
|
|
4907
|
+
});
|
|
4908
|
+
const gas = await this.publicClient.estimateContractGas({
|
|
4909
|
+
address: hostParams.handler,
|
|
4910
|
+
abi: handler_default.ABI,
|
|
4911
|
+
functionName: "handlePostRequests",
|
|
4912
|
+
args: contractArgs,
|
|
4913
|
+
stateOverride: [
|
|
4914
|
+
{
|
|
4915
|
+
address: this.params.host,
|
|
4916
|
+
stateDiff: [
|
|
4917
|
+
{
|
|
4918
|
+
slot: overlayRootSlot,
|
|
4919
|
+
value: root
|
|
4920
|
+
}
|
|
4921
|
+
]
|
|
4922
|
+
}
|
|
4923
|
+
]
|
|
4924
|
+
});
|
|
4925
|
+
return { gas, postRequestCalldata };
|
|
4926
|
+
}
|
|
4927
|
+
/**
|
|
4928
|
+
* Gets the fee token address and decimals for the chain.
|
|
4929
|
+
* This function gets the fee token address and decimals for the chain.
|
|
4930
|
+
*
|
|
4931
|
+
* @returns The fee token address and decimals
|
|
5056
4932
|
*/
|
|
5057
|
-
|
|
5058
|
-
|
|
5059
|
-
|
|
4933
|
+
async getFeeTokenWithDecimals() {
|
|
4934
|
+
const hostParams = await this.publicClient.readContract({
|
|
4935
|
+
abi: evmHost_default.ABI,
|
|
4936
|
+
address: this.params.host,
|
|
4937
|
+
functionName: "hostParams"
|
|
4938
|
+
});
|
|
4939
|
+
const feeTokenAddress = hostParams.feeToken;
|
|
4940
|
+
const feeTokenDecimals = await this.publicClient.readContract({
|
|
4941
|
+
address: feeTokenAddress,
|
|
4942
|
+
abi: erc20Abi,
|
|
4943
|
+
functionName: "decimals"
|
|
4944
|
+
});
|
|
4945
|
+
return { address: feeTokenAddress, decimals: feeTokenDecimals };
|
|
4946
|
+
}
|
|
4947
|
+
/**
|
|
4948
|
+
* Gets the nonce of the host.
|
|
4949
|
+
* This function gets the nonce of the host.
|
|
4950
|
+
*
|
|
4951
|
+
* @returns The nonce of the host
|
|
5060
4952
|
*/
|
|
5061
|
-
|
|
5062
|
-
|
|
5063
|
-
|
|
4953
|
+
async getHostNonce() {
|
|
4954
|
+
const nonce = await this.publicClient.readContract({
|
|
4955
|
+
abi: evmHost_default.ABI,
|
|
4956
|
+
address: this.params.host,
|
|
4957
|
+
functionName: "nonce"
|
|
4958
|
+
});
|
|
4959
|
+
return nonce;
|
|
4960
|
+
}
|
|
4961
|
+
};
|
|
4962
|
+
var REQUEST_COMMITMENTS_SLOT = 0n;
|
|
4963
|
+
var RESPONSE_COMMITMENTS_SLOT = 1n;
|
|
4964
|
+
var REQUEST_RECEIPTS_SLOT = 2n;
|
|
4965
|
+
var RESPONSE_RECEIPTS_SLOT = 3n;
|
|
4966
|
+
var STATE_COMMITMENTS_SLOT = 5n;
|
|
4967
|
+
function requestCommitmentKey(key) {
|
|
4968
|
+
const keyBytes = hexToBytes(key);
|
|
4969
|
+
const slot = REQUEST_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 responseCommitmentKey(key) {
|
|
4975
|
+
const keyBytes = hexToBytes(key);
|
|
4976
|
+
const slot = RESPONSE_COMMITMENTS_SLOT;
|
|
4977
|
+
const mappedKey = deriveMapKey(keyBytes, slot);
|
|
4978
|
+
const number = bytesToBigInt(hexToBytes(mappedKey)) + 1n;
|
|
4979
|
+
return pad(`0x${number.toString(16)}`, { size: 32 });
|
|
4980
|
+
}
|
|
4981
|
+
function deriveMapKey(key, slot) {
|
|
4982
|
+
const slotBytes = pad(`0x${slot.toString(16)}`, { size: 32 });
|
|
4983
|
+
const combined = new Uint8Array([...key, ...toBytes(slotBytes)]);
|
|
4984
|
+
return keccak256(combined);
|
|
4985
|
+
}
|
|
4986
|
+
function getStateCommitmentFieldSlot(stateMachineId, height, field) {
|
|
4987
|
+
const baseSlot = getStateCommitmentSlot(stateMachineId, height);
|
|
4988
|
+
const slotNumber = bytesToBigInt(toBytes(baseSlot)) + BigInt(field);
|
|
4989
|
+
return pad(`0x${slotNumber.toString(16)}`, { size: 32 });
|
|
4990
|
+
}
|
|
4991
|
+
function getStateCommitmentSlot(stateMachineId, height) {
|
|
4992
|
+
const firstLevelSlot = deriveFirstLevelSlot(stateMachineId, STATE_COMMITMENTS_SLOT);
|
|
4993
|
+
return deriveSecondLevelSlot(height, firstLevelSlot);
|
|
4994
|
+
}
|
|
4995
|
+
function deriveFirstLevelSlot(key, slot) {
|
|
4996
|
+
const keyHex = pad(`0x${key.toString(16)}`, { size: 32 });
|
|
4997
|
+
const keyBytes = toBytes(keyHex);
|
|
4998
|
+
const slotBytes = toBytes(pad(`0x${slot.toString(16)}`, { size: 32 }));
|
|
4999
|
+
const combined = new Uint8Array([...keyBytes, ...slotBytes]);
|
|
5000
|
+
return keccak256(combined);
|
|
5001
|
+
}
|
|
5002
|
+
function deriveSecondLevelSlot(key, firstLevelSlot) {
|
|
5003
|
+
const keyHex = pad(`0x${key.toString(16)}`, { size: 32 });
|
|
5004
|
+
const keyBytes = toBytes(keyHex);
|
|
5005
|
+
const slotBytes = toBytes(firstLevelSlot);
|
|
5006
|
+
const combined = new Uint8Array([...keyBytes, ...slotBytes]);
|
|
5007
|
+
return keccak256(combined);
|
|
5008
|
+
}
|
|
5009
|
+
var SubstrateChain = class {
|
|
5010
|
+
constructor(params) {
|
|
5011
|
+
this.params = params;
|
|
5012
|
+
}
|
|
5064
5013
|
/*
|
|
5065
|
-
*
|
|
5014
|
+
* api: The Polkadot API instance for the Substrate chain.
|
|
5066
5015
|
*/
|
|
5067
|
-
|
|
5016
|
+
api;
|
|
5068
5017
|
/*
|
|
5069
|
-
*
|
|
5018
|
+
* connect: Connects to the Substrate chain using the provided WebSocket URL.
|
|
5070
5019
|
*/
|
|
5071
|
-
|
|
5072
|
-
|
|
5073
|
-
|
|
5074
|
-
|
|
5075
|
-
|
|
5020
|
+
async connect() {
|
|
5021
|
+
const wsProvider = new WsProvider(this.params.ws);
|
|
5022
|
+
const typesBundle = this.params.hasher === "Keccak" ? {
|
|
5023
|
+
spec: {
|
|
5024
|
+
nexus: {
|
|
5025
|
+
hasher: keccakAsU8a
|
|
5026
|
+
},
|
|
5027
|
+
gargantua: {
|
|
5028
|
+
hasher: keccakAsU8a
|
|
5029
|
+
}
|
|
5030
|
+
}
|
|
5031
|
+
} : {};
|
|
5032
|
+
this.api = await ApiPromise.create({
|
|
5033
|
+
provider: wsProvider,
|
|
5034
|
+
typesBundle
|
|
5035
|
+
});
|
|
5036
|
+
}
|
|
5037
|
+
/**
|
|
5038
|
+
* Disconnects the Substrate chain connection.
|
|
5076
5039
|
*/
|
|
5077
|
-
|
|
5078
|
-
|
|
5079
|
-
|
|
5040
|
+
async disconnect() {
|
|
5041
|
+
if (this.api) {
|
|
5042
|
+
await this.api.disconnect();
|
|
5043
|
+
this.api = void 0;
|
|
5044
|
+
}
|
|
5045
|
+
}
|
|
5046
|
+
/**
|
|
5047
|
+
* Returns the storage key for a request receipt in the child trie
|
|
5048
|
+
* The request commitment is the key
|
|
5049
|
+
* @param key - The H256 hash key (as a 0x-prefixed hex string)
|
|
5050
|
+
* @returns The storage key as a hex string
|
|
5080
5051
|
*/
|
|
5081
|
-
|
|
5082
|
-
|
|
5083
|
-
|
|
5052
|
+
requestReceiptKey(key) {
|
|
5053
|
+
const prefix = new TextEncoder().encode("RequestReceipts");
|
|
5054
|
+
const keyBytes = hexToBytes(key);
|
|
5055
|
+
return bytesToHex(new Uint8Array([...prefix, ...keyBytes]));
|
|
5056
|
+
}
|
|
5057
|
+
/**
|
|
5058
|
+
* Returns the storage key for a request commitment in the child trie
|
|
5059
|
+
* The request commitment is the key
|
|
5060
|
+
* @param key - The H256 hash key (as a 0x-prefixed hex string)
|
|
5061
|
+
* @returns The storage key as a hex string
|
|
5084
5062
|
*/
|
|
5085
|
-
|
|
5086
|
-
|
|
5087
|
-
|
|
5088
|
-
|
|
5089
|
-
|
|
5063
|
+
requestCommitmentKey(key) {
|
|
5064
|
+
const prefix = new TextEncoder().encode("RequestCommitments");
|
|
5065
|
+
const keyBytes = hexToBytes(key);
|
|
5066
|
+
return bytesToHex(new Uint8Array([...prefix, ...keyBytes]));
|
|
5067
|
+
}
|
|
5068
|
+
/**
|
|
5069
|
+
* Queries a request commitment from the ISMP child trie storage.
|
|
5070
|
+
* @param {HexString} commitment - The commitment hash to look up.
|
|
5071
|
+
* @returns {Promise<HexString | undefined>} The commitment data if found, undefined otherwise.
|
|
5090
5072
|
*/
|
|
5091
|
-
|
|
5092
|
-
|
|
5093
|
-
|
|
5094
|
-
|
|
5095
|
-
|
|
5096
|
-
|
|
5097
|
-
|
|
5098
|
-
|
|
5099
|
-
|
|
5100
|
-
|
|
5101
|
-
|
|
5102
|
-
*
|
|
5073
|
+
async queryRequestCommitment(commitment) {
|
|
5074
|
+
const prefix = toHex(":child_storage:default:ISMP");
|
|
5075
|
+
const key = this.requestCommitmentKey(commitment);
|
|
5076
|
+
const rpc = new RpcWebSocketClient();
|
|
5077
|
+
await rpc.connect(this.params.ws);
|
|
5078
|
+
const item = await rpc.call("childstate_getStorage", [prefix, key]);
|
|
5079
|
+
return item;
|
|
5080
|
+
}
|
|
5081
|
+
/**
|
|
5082
|
+
* Queries the request receipt.
|
|
5083
|
+
* @param {HexString} commitment - The commitment to query.
|
|
5084
|
+
* @returns {Promise<HexString | undefined>} The relayer address responsible for delivering the request.
|
|
5103
5085
|
*/
|
|
5104
|
-
|
|
5105
|
-
|
|
5106
|
-
|
|
5107
|
-
|
|
5108
|
-
|
|
5109
|
-
|
|
5110
|
-
|
|
5111
|
-
|
|
5112
|
-
|
|
5113
|
-
|
|
5114
|
-
|
|
5115
|
-
* There are no proofs for Get timeouts
|
|
5086
|
+
async queryRequestReceipt(commitment) {
|
|
5087
|
+
const prefix = toHex(":child_storage:default:ISMP");
|
|
5088
|
+
const key = this.requestReceiptKey(commitment);
|
|
5089
|
+
const rpc = new RpcWebSocketClient();
|
|
5090
|
+
await rpc.connect(this.params.ws);
|
|
5091
|
+
const item = await rpc.call("childstate_getStorage", [prefix, key]);
|
|
5092
|
+
return item;
|
|
5093
|
+
}
|
|
5094
|
+
/**
|
|
5095
|
+
* Returns the current timestamp of the chain.
|
|
5096
|
+
* @returns {Promise<bigint>} The current timestamp.
|
|
5116
5097
|
*/
|
|
5117
|
-
|
|
5118
|
-
|
|
5119
|
-
|
|
5120
|
-
|
|
5121
|
-
|
|
5122
|
-
|
|
5123
|
-
|
|
5124
|
-
|
|
5125
|
-
|
|
5126
|
-
*
|
|
5098
|
+
async timestamp() {
|
|
5099
|
+
if (!this.api) throw new Error("API not initialized");
|
|
5100
|
+
const now = await this.api.query.timestamp.now();
|
|
5101
|
+
return BigInt(now.toJSON()) / BigInt(1e3);
|
|
5102
|
+
}
|
|
5103
|
+
/**
|
|
5104
|
+
* Queries the proof of the commitments.
|
|
5105
|
+
* @param {IMessage} message - The message to query.
|
|
5106
|
+
* @param {string} counterparty - The counterparty address.
|
|
5107
|
+
* @param {bigint} [at] - The block number to query at.
|
|
5108
|
+
* @returns {Promise<HexString>} The proof.
|
|
5127
5109
|
*/
|
|
5128
|
-
|
|
5129
|
-
|
|
5130
|
-
|
|
5110
|
+
async queryProof(message, counterparty, at) {
|
|
5111
|
+
const rpc = new RpcWebSocketClient();
|
|
5112
|
+
await rpc.connect(this.params.ws);
|
|
5113
|
+
if (isEvmChain(counterparty)) {
|
|
5114
|
+
const proof = await rpc.call("mmr_queryProof", [Number(at), message]);
|
|
5115
|
+
return toHex(proof.proof);
|
|
5116
|
+
}
|
|
5117
|
+
if (isSubstrateChain(counterparty)) {
|
|
5118
|
+
const childTrieKeys = "Requests" in message ? message.Requests.map(requestCommitmentStorageKey) : message.Responses.map(responseCommitmentStorageKey);
|
|
5119
|
+
const proof = await rpc.call("ismp_queryChildTrieProof", [Number(at), childTrieKeys]);
|
|
5120
|
+
const basicProof = BasicProof.dec(toHex(proof.proof));
|
|
5121
|
+
const encoded = SubstrateStateProof.enc({
|
|
5122
|
+
tag: "OverlayProof",
|
|
5123
|
+
value: {
|
|
5124
|
+
hasher: {
|
|
5125
|
+
tag: this.params.hasher,
|
|
5126
|
+
value: void 0
|
|
5127
|
+
},
|
|
5128
|
+
storageProof: basicProof
|
|
5129
|
+
}
|
|
5130
|
+
});
|
|
5131
|
+
return toHex(encoded);
|
|
5132
|
+
}
|
|
5133
|
+
throw new ExpectedError(`Unsupported chain type for counterparty: ${counterparty}`);
|
|
5134
|
+
}
|
|
5135
|
+
/**
|
|
5136
|
+
* Submit an unsigned ISMP transaction to the chain. Resolves when the transaction is finalized.
|
|
5137
|
+
* @param message - The message to be submitted.
|
|
5138
|
+
* @returns A promise that resolves to an object containing the transaction hash, block hash, and block number.
|
|
5131
5139
|
*/
|
|
5132
|
-
|
|
5133
|
-
|
|
5134
|
-
|
|
5140
|
+
async submitUnsigned(message) {
|
|
5141
|
+
if (!this.api) throw new Error("API not initialized");
|
|
5142
|
+
const { api } = this;
|
|
5143
|
+
const args = hexToBytes(this.encode(message)).slice(2);
|
|
5144
|
+
const tx = api.tx.ismp.handleUnsigned(args);
|
|
5145
|
+
return new Promise((resolve, reject) => {
|
|
5146
|
+
let unsub = () => {
|
|
5147
|
+
};
|
|
5148
|
+
tx.send(async ({ isInBlock, isFinalized, isError, dispatchError, txHash, status }) => {
|
|
5149
|
+
if (isFinalized || isInBlock) {
|
|
5150
|
+
unsub();
|
|
5151
|
+
const blockHash = isInBlock ? status.asInBlock.toHex() : status.asFinalized.toHex();
|
|
5152
|
+
const header = await api.rpc.chain.getHeader(blockHash);
|
|
5153
|
+
const apiAt = await api.at(blockHash);
|
|
5154
|
+
const timestamp = await apiAt.query.timestamp.now();
|
|
5155
|
+
resolve({
|
|
5156
|
+
transactionHash: txHash.toHex(),
|
|
5157
|
+
blockHash,
|
|
5158
|
+
blockNumber: header.number.toNumber(),
|
|
5159
|
+
timestamp: Number(timestamp.toJSON()) / 1e3
|
|
5160
|
+
});
|
|
5161
|
+
} else if (isError) {
|
|
5162
|
+
unsub();
|
|
5163
|
+
console.error("Unsigned transaction failed: ", dispatchError);
|
|
5164
|
+
reject(dispatchError);
|
|
5165
|
+
}
|
|
5166
|
+
}).then((unsubscribe) => {
|
|
5167
|
+
unsub = unsubscribe;
|
|
5168
|
+
}).catch(reject);
|
|
5169
|
+
});
|
|
5170
|
+
}
|
|
5171
|
+
/**
|
|
5172
|
+
* Query the state proof for a given set of keys at a specific block height.
|
|
5173
|
+
* @param at The block height to query the state proof at.
|
|
5174
|
+
* @param keys The keys to query the state proof for.
|
|
5175
|
+
* @returns The state proof as a hexadecimal string.
|
|
5135
5176
|
*/
|
|
5136
|
-
|
|
5137
|
-
|
|
5138
|
-
|
|
5177
|
+
async queryStateProof(at, keys) {
|
|
5178
|
+
const rpc = new RpcWebSocketClient();
|
|
5179
|
+
await rpc.connect(this.params.ws);
|
|
5180
|
+
const encodedKeys = keys.map((key) => Array.from(hexToBytes(key)));
|
|
5181
|
+
const proof = await rpc.call("ismp_queryChildTrieProof", [Number(at), encodedKeys]);
|
|
5182
|
+
const basicProof = BasicProof.dec(toHex(proof.proof));
|
|
5183
|
+
const encoded = SubstrateStateProof.enc({
|
|
5184
|
+
tag: "OverlayProof",
|
|
5185
|
+
value: {
|
|
5186
|
+
hasher: {
|
|
5187
|
+
tag: this.params.hasher,
|
|
5188
|
+
value: void 0
|
|
5189
|
+
},
|
|
5190
|
+
storageProof: basicProof
|
|
5191
|
+
}
|
|
5192
|
+
});
|
|
5193
|
+
return toHex(encoded);
|
|
5194
|
+
}
|
|
5195
|
+
/**
|
|
5196
|
+
* Get the latest state machine height for a given state machine ID.
|
|
5197
|
+
* @param {StateMachineIdParams} stateMachineId - The state machine ID.
|
|
5198
|
+
* @returns {Promise<bigint>} The latest state machine height.
|
|
5139
5199
|
*/
|
|
5140
|
-
|
|
5141
|
-
|
|
5142
|
-
|
|
5200
|
+
async latestStateMachineHeight(stateMachineId) {
|
|
5201
|
+
if (!this.api) throw new Error("API not initialized");
|
|
5202
|
+
const latestHeight = await this.api.query.ismp.latestStateMachineHeight(stateMachineId);
|
|
5203
|
+
return BigInt(latestHeight.toString());
|
|
5204
|
+
}
|
|
5205
|
+
/**
|
|
5206
|
+
* Get the state machine update time for a given state machine height.
|
|
5207
|
+
* @param {StateMachineHeight} stateMachineHeight - The state machine height.
|
|
5208
|
+
* @returns {Promise<bigint>} The statemachine update time in seconds.
|
|
5143
5209
|
*/
|
|
5144
|
-
|
|
5145
|
-
|
|
5146
|
-
|
|
5147
|
-
|
|
5148
|
-
var DEFAULT_POLL_INTERVAL = 5e3;
|
|
5149
|
-
var ADDRESS_ZERO2 = "0x0000000000000000000000000000000000000000";
|
|
5150
|
-
var MOCK_ADDRESS2 = "0x1234567890123456789012345678901234567890";
|
|
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;
|
|
5210
|
+
async stateMachineUpdateTime(stateMachineHeight) {
|
|
5211
|
+
if (!this.api) throw new Error("API not initialized");
|
|
5212
|
+
const updateTime = await this.api.query.ismp.stateMachineUpdateTime(stateMachineHeight);
|
|
5213
|
+
return BigInt(updateTime.toString());
|
|
5168
5214
|
}
|
|
5169
|
-
|
|
5170
|
-
|
|
5171
|
-
|
|
5172
|
-
}
|
|
5173
|
-
|
|
5174
|
-
|
|
5175
|
-
|
|
5176
|
-
|
|
5177
|
-
|
|
5178
|
-
|
|
5179
|
-
|
|
5180
|
-
|
|
5181
|
-
|
|
5215
|
+
/**
|
|
5216
|
+
* Get the challenge period for a given state machine id.
|
|
5217
|
+
* @param {StateMachineIdParams} stateMachineId - The state machine ID.
|
|
5218
|
+
* @returns {Promise<bigint>} The challenge period in seconds.
|
|
5219
|
+
*/
|
|
5220
|
+
async challengePeriod(stateMachineId) {
|
|
5221
|
+
if (!this.api) throw new Error("API not initialized");
|
|
5222
|
+
const challengePeriod = await this.api.query.ismp.challengePeriod(stateMachineId);
|
|
5223
|
+
return BigInt(challengePeriod.toString());
|
|
5224
|
+
}
|
|
5225
|
+
/**
|
|
5226
|
+
* Encode an ISMP calldata for a substrate chain.
|
|
5227
|
+
* @param message The ISMP message to encode.
|
|
5228
|
+
* @returns The encoded message as a hexadecimal string.
|
|
5229
|
+
*/
|
|
5230
|
+
encode(message) {
|
|
5231
|
+
const palletIndex = this.getPalletIndex("Ismp");
|
|
5232
|
+
const args = encodeISMPMessage(message);
|
|
5233
|
+
const call = Vector(u8, 2).enc([palletIndex, 0]);
|
|
5234
|
+
return toHex(new Uint8Array([...call, ...args]));
|
|
5182
5235
|
}
|
|
5183
|
-
|
|
5184
|
-
|
|
5185
|
-
|
|
5186
|
-
|
|
5187
|
-
|
|
5188
|
-
|
|
5189
|
-
|
|
5190
|
-
|
|
5191
|
-
|
|
5192
|
-
|
|
5193
|
-
|
|
5194
|
-
|
|
5195
|
-
stateId.Substrate = `0x${bytes.toString("hex")}`;
|
|
5196
|
-
break;
|
|
5197
|
-
}
|
|
5198
|
-
case "POLKADOT": {
|
|
5199
|
-
const polkadotChainId = Number.parseInt(value, 10);
|
|
5200
|
-
if (Number.isNaN(polkadotChainId)) {
|
|
5201
|
-
throw new Error(`Invalid Polkadot chain ID: ${value}. Expected a number.`);
|
|
5202
|
-
}
|
|
5203
|
-
stateId.Polkadot = polkadotChainId;
|
|
5204
|
-
break;
|
|
5205
|
-
}
|
|
5206
|
-
case "KUSAMA": {
|
|
5207
|
-
const kusamaChainId = Number.parseInt(value, 10);
|
|
5208
|
-
if (Number.isNaN(kusamaChainId)) {
|
|
5209
|
-
throw new Error(`Invalid Kusama chain ID: ${value}. Expected a number.`);
|
|
5236
|
+
/**
|
|
5237
|
+
* Returns the index of a pallet by its name, by looking up the pallets in the runtime metadata.
|
|
5238
|
+
* @param {string} name - The name of the pallet.
|
|
5239
|
+
* @returns {number} The index of the pallet.
|
|
5240
|
+
*/
|
|
5241
|
+
getPalletIndex(name) {
|
|
5242
|
+
if (!this.api) throw new Error("API not initialized");
|
|
5243
|
+
const pallets = this.api.runtimeMetadata.asLatest.pallets.entries();
|
|
5244
|
+
for (const p of pallets) {
|
|
5245
|
+
if (p[1].name.toString() === name) {
|
|
5246
|
+
const index = p[1].index.toNumber();
|
|
5247
|
+
return index;
|
|
5210
5248
|
}
|
|
5211
|
-
stateId.Kusama = kusamaChainId;
|
|
5212
|
-
break;
|
|
5213
5249
|
}
|
|
5214
|
-
|
|
5215
|
-
throw new Error(`Unsupported chain type: ${type}. Expected one of: EVM, SUBSTRATE, POLKADOT, KUSAMA.`);
|
|
5216
|
-
}
|
|
5217
|
-
return { stateId };
|
|
5218
|
-
}
|
|
5219
|
-
function postRequestCommitment(post) {
|
|
5220
|
-
const data = encodePacked(
|
|
5221
|
-
["bytes", "bytes", "uint64", "uint64", "bytes", "bytes", "bytes"],
|
|
5222
|
-
[toHex(post.source), toHex(post.dest), post.nonce, post.timeoutTimestamp, post.from, post.to, post.body]
|
|
5223
|
-
);
|
|
5224
|
-
return {
|
|
5225
|
-
commitment: keccak256(data),
|
|
5226
|
-
encodePacked: data
|
|
5227
|
-
};
|
|
5228
|
-
}
|
|
5229
|
-
function orderCommitment2(order) {
|
|
5230
|
-
const encodedOrder = encodeAbiParameters(
|
|
5231
|
-
[
|
|
5232
|
-
{
|
|
5233
|
-
name: "order",
|
|
5234
|
-
type: "tuple",
|
|
5235
|
-
components: [
|
|
5236
|
-
{ name: "user", type: "bytes32" },
|
|
5237
|
-
{ name: "sourceChain", type: "bytes" },
|
|
5238
|
-
{ name: "destChain", type: "bytes" },
|
|
5239
|
-
{ name: "deadline", type: "uint256" },
|
|
5240
|
-
{ name: "nonce", type: "uint256" },
|
|
5241
|
-
{ name: "fees", type: "uint256" },
|
|
5242
|
-
{
|
|
5243
|
-
name: "outputs",
|
|
5244
|
-
type: "tuple[]",
|
|
5245
|
-
components: [
|
|
5246
|
-
{ name: "token", type: "bytes32" },
|
|
5247
|
-
{ name: "amount", type: "uint256" },
|
|
5248
|
-
{ name: "beneficiary", type: "bytes32" }
|
|
5249
|
-
]
|
|
5250
|
-
},
|
|
5251
|
-
{
|
|
5252
|
-
name: "inputs",
|
|
5253
|
-
type: "tuple[]",
|
|
5254
|
-
components: [
|
|
5255
|
-
{ name: "token", type: "bytes32" },
|
|
5256
|
-
{ name: "amount", type: "uint256" }
|
|
5257
|
-
]
|
|
5258
|
-
},
|
|
5259
|
-
{ name: "callData", type: "bytes" }
|
|
5260
|
-
]
|
|
5261
|
-
}
|
|
5262
|
-
],
|
|
5263
|
-
[
|
|
5264
|
-
{
|
|
5265
|
-
user: order.user,
|
|
5266
|
-
sourceChain: order.sourceChain.startsWith("0x") ? order.sourceChain : toHex(order.sourceChain),
|
|
5267
|
-
destChain: order.destChain.startsWith("0x") ? order.destChain : toHex(order.destChain),
|
|
5268
|
-
deadline: order.deadline,
|
|
5269
|
-
nonce: order.nonce,
|
|
5270
|
-
fees: order.fees,
|
|
5271
|
-
outputs: order.outputs,
|
|
5272
|
-
inputs: order.inputs,
|
|
5273
|
-
callData: order.callData
|
|
5274
|
-
}
|
|
5275
|
-
]
|
|
5276
|
-
);
|
|
5277
|
-
return keccak256(encodedOrder);
|
|
5278
|
-
}
|
|
5279
|
-
function bytes32ToBytes202(bytes32Address) {
|
|
5280
|
-
if (bytes32Address === ADDRESS_ZERO2) {
|
|
5281
|
-
return ADDRESS_ZERO2;
|
|
5250
|
+
throw new Error(`${name} not found in runtime`);
|
|
5282
5251
|
}
|
|
5283
|
-
|
|
5284
|
-
|
|
5285
|
-
|
|
5252
|
+
};
|
|
5253
|
+
function requestCommitmentStorageKey(key) {
|
|
5254
|
+
const prefix = new TextEncoder().encode("RequestCommitments");
|
|
5255
|
+
const keyBytes = hexToBytes(key);
|
|
5256
|
+
return Array.from(new Uint8Array([...prefix, ...keyBytes]));
|
|
5286
5257
|
}
|
|
5287
|
-
function
|
|
5288
|
-
|
|
5258
|
+
function responseCommitmentStorageKey(key) {
|
|
5259
|
+
const prefix = new TextEncoder().encode("ResponseCommitments");
|
|
5260
|
+
const keyBytes = hexToBytes(key);
|
|
5261
|
+
return Array.from(new Uint8Array([...prefix, ...keyBytes]));
|
|
5289
5262
|
}
|
|
5290
|
-
function
|
|
5291
|
-
|
|
5292
|
-
|
|
5293
|
-
|
|
5294
|
-
|
|
5263
|
+
function convertStateMachineIdToEnum(id) {
|
|
5264
|
+
let [tag, value] = id.split("-");
|
|
5265
|
+
tag = capitalize(tag);
|
|
5266
|
+
if (["Evm", "Polkadot", "Kusama"].includes(tag)) {
|
|
5267
|
+
value = Number.parseInt(value);
|
|
5268
|
+
} else {
|
|
5269
|
+
value = Array.from(toBytes(value));
|
|
5295
5270
|
}
|
|
5296
|
-
return
|
|
5271
|
+
return { tag, value };
|
|
5297
5272
|
}
|
|
5298
|
-
|
|
5299
|
-
|
|
5300
|
-
|
|
5301
|
-
|
|
5302
|
-
|
|
5303
|
-
|
|
5304
|
-
|
|
5305
|
-
|
|
5306
|
-
|
|
5307
|
-
|
|
5308
|
-
|
|
5309
|
-
lastError = error;
|
|
5310
|
-
await new Promise((resolve) => setTimeout(resolve, retryConfig.backoffMs * 2 ** i));
|
|
5273
|
+
function convertIPostRequestToCodec(request) {
|
|
5274
|
+
return {
|
|
5275
|
+
tag: "Post",
|
|
5276
|
+
value: {
|
|
5277
|
+
source: convertStateMachineIdToEnum(request.source),
|
|
5278
|
+
dest: convertStateMachineIdToEnum(request.dest),
|
|
5279
|
+
from: Array.from(hexToBytes(request.from)),
|
|
5280
|
+
to: Array.from(hexToBytes(request.to)),
|
|
5281
|
+
nonce: request.nonce,
|
|
5282
|
+
body: Array.from(hexToBytes(request.body)),
|
|
5283
|
+
timeoutTimestamp: request.timeoutTimestamp
|
|
5311
5284
|
}
|
|
5312
|
-
}
|
|
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
|
-
};
|
|
5361
|
-
async function estimateGasForPost(params) {
|
|
5362
|
-
const hostParams = await params.sourceClient.readContract({
|
|
5363
|
-
address: params.hostAddress,
|
|
5364
|
-
abi: evmHost_default.ABI,
|
|
5365
|
-
functionName: "hostParams"
|
|
5366
|
-
});
|
|
5367
|
-
const { root, proof, index, kIndex, treeSize } = await generateRootWithProof(params.postRequest, 2n ** 10n);
|
|
5368
|
-
const latestStateMachineHeight = params.hostLatestStateMachineHeight;
|
|
5369
|
-
const overlayRootSlot = getStateCommitmentFieldSlot(
|
|
5370
|
-
BigInt(4009n),
|
|
5371
|
-
// Hyperbridge chain id
|
|
5372
|
-
latestStateMachineHeight,
|
|
5373
|
-
// Hyperbridge chain height
|
|
5374
|
-
1
|
|
5375
|
-
// For overlayRoot
|
|
5376
|
-
);
|
|
5377
|
-
const postParams = {
|
|
5378
|
-
height: {
|
|
5379
|
-
stateMachineId: BigInt(4009n),
|
|
5380
|
-
height: latestStateMachineHeight
|
|
5381
|
-
},
|
|
5382
|
-
multiproof: proof,
|
|
5383
|
-
leafCount: treeSize
|
|
5384
5285
|
};
|
|
5385
|
-
|
|
5386
|
-
|
|
5387
|
-
|
|
5388
|
-
|
|
5389
|
-
|
|
5390
|
-
|
|
5391
|
-
|
|
5392
|
-
|
|
5393
|
-
|
|
5394
|
-
|
|
5395
|
-
|
|
5396
|
-
|
|
5397
|
-
|
|
5398
|
-
|
|
5286
|
+
}
|
|
5287
|
+
function encodeISMPMessage(message) {
|
|
5288
|
+
try {
|
|
5289
|
+
return match(message).with({ kind: "PostRequest" }, (message2) => {
|
|
5290
|
+
return Vector(Message).enc([
|
|
5291
|
+
{
|
|
5292
|
+
tag: "RequestMessage",
|
|
5293
|
+
value: {
|
|
5294
|
+
requests: message2.requests.map(
|
|
5295
|
+
(post_request) => convertIPostRequestToCodec(post_request).value
|
|
5296
|
+
),
|
|
5297
|
+
proof: {
|
|
5298
|
+
height: {
|
|
5299
|
+
height: message2.proof.height,
|
|
5300
|
+
id: {
|
|
5301
|
+
consensusStateId: Array.from(toBytes(message2.proof.consensusStateId)),
|
|
5302
|
+
id: convertStateMachineIdToEnum(message2.proof.stateMachine)
|
|
5303
|
+
}
|
|
5304
|
+
},
|
|
5305
|
+
proof: Array.from(hexToBytes(message2.proof.proof))
|
|
5399
5306
|
},
|
|
5400
|
-
|
|
5401
|
-
kIndex
|
|
5402
|
-
}
|
|
5403
|
-
]
|
|
5404
|
-
}
|
|
5405
|
-
],
|
|
5406
|
-
stateOverride: [
|
|
5407
|
-
{
|
|
5408
|
-
address: params.hostAddress,
|
|
5409
|
-
stateDiff: [
|
|
5410
|
-
{
|
|
5411
|
-
slot: overlayRootSlot,
|
|
5412
|
-
value: root
|
|
5307
|
+
signer: Array.from(hexToBytes(message2.signer))
|
|
5413
5308
|
}
|
|
5414
|
-
|
|
5415
|
-
|
|
5416
|
-
|
|
5417
|
-
|
|
5418
|
-
|
|
5419
|
-
|
|
5420
|
-
|
|
5421
|
-
|
|
5422
|
-
|
|
5423
|
-
|
|
5424
|
-
|
|
5425
|
-
|
|
5426
|
-
|
|
5427
|
-
|
|
5428
|
-
|
|
5429
|
-
|
|
5430
|
-
|
|
5431
|
-
|
|
5432
|
-
|
|
5433
|
-
|
|
5434
|
-
|
|
5435
|
-
|
|
5436
|
-
|
|
5437
|
-
{
|
|
5438
|
-
name: "tokens",
|
|
5439
|
-
type: "tuple[]",
|
|
5440
|
-
components: [
|
|
5441
|
-
{ name: "token", type: "bytes32" },
|
|
5442
|
-
{ name: "amount", type: "uint256" }
|
|
5443
|
-
]
|
|
5309
|
+
}
|
|
5310
|
+
]);
|
|
5311
|
+
}).with({ kind: "GetResponse" }, (message2) => {
|
|
5312
|
+
throw new Error("GetResponse is not yet supported on Substrate chains");
|
|
5313
|
+
}).with({ kind: "TimeoutPostRequest" }, (message2) => {
|
|
5314
|
+
return Vector(Message).enc([
|
|
5315
|
+
{
|
|
5316
|
+
tag: "TimeoutMessage",
|
|
5317
|
+
value: {
|
|
5318
|
+
tag: "Post",
|
|
5319
|
+
value: {
|
|
5320
|
+
requests: message2.requests.map((r) => convertIPostRequestToCodec(r)),
|
|
5321
|
+
proof: {
|
|
5322
|
+
height: {
|
|
5323
|
+
height: message2.proof.height,
|
|
5324
|
+
id: {
|
|
5325
|
+
consensusStateId: Array.from(toBytes(message2.proof.consensusStateId)),
|
|
5326
|
+
id: convertStateMachineIdToEnum(message2.proof.stateMachine)
|
|
5327
|
+
}
|
|
5328
|
+
},
|
|
5329
|
+
proof: Array.from(hexToBytes(message2.proof.proof))
|
|
5330
|
+
}
|
|
5331
|
+
}
|
|
5444
5332
|
}
|
|
5445
|
-
|
|
5446
|
-
|
|
5447
|
-
|
|
5448
|
-
|
|
5449
|
-
|
|
5450
|
-
|
|
5333
|
+
}
|
|
5334
|
+
]);
|
|
5335
|
+
}).exhaustive();
|
|
5336
|
+
} catch (error) {
|
|
5337
|
+
throw new Error("Failed to encode ISMP message", { cause: error });
|
|
5338
|
+
}
|
|
5451
5339
|
}
|
|
5452
|
-
|
|
5453
|
-
|
|
5454
|
-
|
|
5340
|
+
|
|
5341
|
+
// src/chain.ts
|
|
5342
|
+
async function getChain(chainConfig) {
|
|
5343
|
+
if (isEvmChain(chainConfig.stateMachineId)) {
|
|
5344
|
+
const config = chainConfig;
|
|
5345
|
+
const chainId = Number.parseInt(chainConfig.stateMachineId.split("-")[1]);
|
|
5346
|
+
const evmChain = new EvmChain({
|
|
5347
|
+
chainId,
|
|
5348
|
+
url: config.rpcUrl,
|
|
5349
|
+
host: config.host
|
|
5350
|
+
});
|
|
5351
|
+
return evmChain;
|
|
5455
5352
|
}
|
|
5456
|
-
|
|
5457
|
-
|
|
5458
|
-
|
|
5459
|
-
|
|
5460
|
-
|
|
5461
|
-
|
|
5462
|
-
|
|
5463
|
-
|
|
5464
|
-
return "weth";
|
|
5465
|
-
case "tbnb":
|
|
5466
|
-
return "wbnb";
|
|
5467
|
-
case "0xc043f483373072f7f27420d6e7d7ad269c018e18".toLowerCase():
|
|
5468
|
-
return "dai";
|
|
5469
|
-
case "0xae13d989dac2f0debff460ac112a837c89baa7cd".toLowerCase():
|
|
5470
|
-
return "wbnb";
|
|
5471
|
-
case "0x1938165569A5463327fb206bE06d8D9253aa06b7".toLowerCase():
|
|
5472
|
-
return "dai";
|
|
5473
|
-
case "0xC625ec7D30A4b1AAEfb1304610CdAcD0d606aC92".toLowerCase():
|
|
5474
|
-
return "dai";
|
|
5475
|
-
case "0x50B1d3c7c073c9caa1Ef207365A2c9C976bD70b9".toLowerCase():
|
|
5476
|
-
return "dai";
|
|
5477
|
-
case "0xa801da100bf16d07f668f4a49e1f71fc54d05177".toLowerCase():
|
|
5478
|
-
return "dai";
|
|
5479
|
-
default:
|
|
5480
|
-
return identifier;
|
|
5353
|
+
if (isSubstrateChain(chainConfig.stateMachineId)) {
|
|
5354
|
+
const config = chainConfig;
|
|
5355
|
+
const substrateChain = new SubstrateChain({
|
|
5356
|
+
ws: config.wsUrl,
|
|
5357
|
+
hasher: config.hasher
|
|
5358
|
+
});
|
|
5359
|
+
await substrateChain.connect();
|
|
5360
|
+
return substrateChain;
|
|
5481
5361
|
}
|
|
5362
|
+
throw new ExpectedError(`Unsupported chain: ${chainConfig.stateMachineId}`);
|
|
5482
5363
|
}
|
|
5483
|
-
|
|
5484
|
-
|
|
5485
|
-
|
|
5486
|
-
|
|
5487
|
-
|
|
5488
|
-
|
|
5489
|
-
|
|
5490
|
-
|
|
5491
|
-
|
|
5492
|
-
|
|
5493
|
-
|
|
5494
|
-
|
|
5495
|
-
|
|
5364
|
+
|
|
5365
|
+
// src/queries.ts
|
|
5366
|
+
var POST_REQUEST_STATUS = `
|
|
5367
|
+
query RequestStatusM($hash: String!) {
|
|
5368
|
+
requests(
|
|
5369
|
+
filter: { commitment: { equalTo: $hash } }
|
|
5370
|
+
) {
|
|
5371
|
+
nodes {
|
|
5372
|
+
commitment
|
|
5373
|
+
timeoutTimestamp
|
|
5374
|
+
source
|
|
5375
|
+
dest
|
|
5376
|
+
to
|
|
5377
|
+
from
|
|
5378
|
+
nonce
|
|
5379
|
+
body
|
|
5380
|
+
statusMetadata {
|
|
5381
|
+
nodes {
|
|
5382
|
+
blockHash
|
|
5383
|
+
blockNumber
|
|
5384
|
+
timestamp
|
|
5385
|
+
chain
|
|
5386
|
+
status
|
|
5387
|
+
transactionHash
|
|
5388
|
+
}
|
|
5389
|
+
}
|
|
5496
5390
|
}
|
|
5497
5391
|
}
|
|
5498
5392
|
}
|
|
5499
|
-
|
|
5500
|
-
|
|
5501
|
-
|
|
5502
|
-
|
|
5503
|
-
|
|
5504
|
-
|
|
5393
|
+
`;
|
|
5394
|
+
var GET_REQUEST_STATUS = `
|
|
5395
|
+
query GetRequestDetails($commitment: String!) {
|
|
5396
|
+
getRequests(
|
|
5397
|
+
filter: { commitment: { equalTo: $commitment } }
|
|
5398
|
+
) {
|
|
5399
|
+
nodes {
|
|
5400
|
+
id
|
|
5401
|
+
source
|
|
5402
|
+
dest
|
|
5403
|
+
from
|
|
5404
|
+
keys
|
|
5405
|
+
nonce
|
|
5406
|
+
height
|
|
5407
|
+
context
|
|
5408
|
+
timeoutTimestamp
|
|
5409
|
+
fee
|
|
5410
|
+
blockNumber
|
|
5411
|
+
blockHash
|
|
5412
|
+
transactionHash
|
|
5413
|
+
blockTimestamp
|
|
5414
|
+
status
|
|
5415
|
+
chain
|
|
5416
|
+
commitment
|
|
5417
|
+
statusMetadata {
|
|
5418
|
+
nodes {
|
|
5419
|
+
status
|
|
5420
|
+
chain
|
|
5421
|
+
timestamp
|
|
5422
|
+
blockNumber
|
|
5423
|
+
blockHash
|
|
5424
|
+
transactionHash
|
|
5425
|
+
}
|
|
5426
|
+
}
|
|
5427
|
+
}
|
|
5428
|
+
}
|
|
5429
|
+
}`;
|
|
5430
|
+
var STATE_MACHINE_UPDATES_BY_HEIGHT = `
|
|
5431
|
+
query StateMachineUpdatesByHeight($statemachineId: String!, $height: Int!, $chain: String!) {
|
|
5432
|
+
stateMachineUpdateEvents(
|
|
5433
|
+
filter: {
|
|
5434
|
+
and: [
|
|
5435
|
+
{ stateMachineId: { equalTo: $statemachineId } }
|
|
5436
|
+
{ height: { greaterThanOrEqualTo: $height } }
|
|
5437
|
+
{ chain: { equalTo: $chain } }
|
|
5438
|
+
]
|
|
5439
|
+
}
|
|
5440
|
+
orderBy: HEIGHT_ASC
|
|
5441
|
+
first: 1
|
|
5442
|
+
) {
|
|
5443
|
+
nodes {
|
|
5444
|
+
height
|
|
5445
|
+
stateMachineId
|
|
5446
|
+
chain
|
|
5447
|
+
blockHash
|
|
5448
|
+
blockNumber
|
|
5449
|
+
transactionHash
|
|
5450
|
+
createdAt
|
|
5451
|
+
}
|
|
5452
|
+
}
|
|
5453
|
+
}
|
|
5454
|
+
`;
|
|
5455
|
+
var STATE_MACHINE_UPDATES_BY_TIMESTAMP = `
|
|
5456
|
+
query StateMachineUpdatesByTimestamp($statemachineId: String!, $commitmentTimestamp: BigFloat!, $chain: String!) {
|
|
5457
|
+
stateMachineUpdateEvents(
|
|
5458
|
+
filter: {
|
|
5459
|
+
and: [
|
|
5460
|
+
{ stateMachineId: { equalTo: $statemachineId } }
|
|
5461
|
+
{ commitmentTimestamp: { greaterThanOrEqualTo: $commitmentTimestamp } }
|
|
5462
|
+
{ chain: { equalTo: $chain } }
|
|
5463
|
+
]
|
|
5464
|
+
}
|
|
5465
|
+
orderBy: COMMITMENT_TIMESTAMP_DESC
|
|
5466
|
+
first: 1
|
|
5467
|
+
) {
|
|
5468
|
+
nodes {
|
|
5469
|
+
height
|
|
5470
|
+
stateMachineId
|
|
5471
|
+
chain
|
|
5472
|
+
blockHash
|
|
5473
|
+
blockNumber
|
|
5474
|
+
transactionHash
|
|
5475
|
+
commitmentTimestamp
|
|
5476
|
+
createdAt
|
|
5477
|
+
}
|
|
5478
|
+
}
|
|
5505
5479
|
}
|
|
5506
|
-
|
|
5507
|
-
|
|
5508
|
-
|
|
5509
|
-
|
|
5480
|
+
`;
|
|
5481
|
+
var ASSET_TELEPORTED_BY_PARAMS = `
|
|
5482
|
+
query AssetTeleportedByParams($from: String!, $to: String!, $dest: String!, $blockNumber: Int!) {
|
|
5483
|
+
assetTeleporteds(
|
|
5484
|
+
filter: {
|
|
5485
|
+
and: [
|
|
5486
|
+
{ from: { equalTo: $from } }
|
|
5487
|
+
{ to: { equalTo: $to } }
|
|
5488
|
+
{ dest: { includes: $dest } }
|
|
5489
|
+
{ blockNumber: { greaterThanOrEqualTo: $blockNumber } }
|
|
5490
|
+
]
|
|
5491
|
+
}
|
|
5492
|
+
orderBy: CREATED_AT_DESC
|
|
5493
|
+
first: 1
|
|
5494
|
+
) {
|
|
5495
|
+
nodes {
|
|
5496
|
+
id
|
|
5497
|
+
from
|
|
5498
|
+
to
|
|
5499
|
+
amount
|
|
5500
|
+
dest
|
|
5501
|
+
commitment
|
|
5502
|
+
createdAt
|
|
5503
|
+
blockNumber
|
|
5504
|
+
}
|
|
5510
5505
|
}
|
|
5511
|
-
return data[key].usd;
|
|
5512
5506
|
}
|
|
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}`);
|
|
5507
|
+
`;
|
|
5508
|
+
var GET_RESPONSE_BY_REQUEST_ID = `
|
|
5509
|
+
query GetResponseByRequestId($requestId: String!) {
|
|
5510
|
+
getResponses(filter: {requestId: {equalTo: $requestId}}) {
|
|
5511
|
+
nodes {
|
|
5512
|
+
id
|
|
5513
|
+
commitment
|
|
5514
|
+
responseMessage
|
|
5515
|
+
}
|
|
5525
5516
|
}
|
|
5526
|
-
return price;
|
|
5527
5517
|
}
|
|
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
|
-
|
|
5518
|
+
`;
|
|
5519
|
+
var ORDER_STATUS = `
|
|
5520
|
+
query OrderStatus($commitment: String!) {
|
|
5521
|
+
orderPlaceds(
|
|
5522
|
+
filter: { commitment: { equalTo: $commitment } }
|
|
5523
|
+
) {
|
|
5524
|
+
nodes {
|
|
5525
|
+
id
|
|
5526
|
+
user
|
|
5527
|
+
sourceChain
|
|
5528
|
+
destChain
|
|
5529
|
+
commitment
|
|
5530
|
+
deadline
|
|
5531
|
+
nonce
|
|
5532
|
+
fees
|
|
5533
|
+
inputTokens
|
|
5534
|
+
inputAmounts
|
|
5535
|
+
inputValuesUSD
|
|
5536
|
+
inputUSD
|
|
5537
|
+
outputTokens
|
|
5538
|
+
outputAmounts
|
|
5539
|
+
outputBeneficiaries
|
|
5540
|
+
calldata
|
|
5541
|
+
status
|
|
5542
|
+
createdAt
|
|
5543
|
+
blockNumber
|
|
5544
|
+
blockTimestamp
|
|
5545
|
+
transactionHash
|
|
5546
|
+
statusMetadata {
|
|
5547
|
+
nodes {
|
|
5548
|
+
status
|
|
5549
|
+
chain
|
|
5550
|
+
timestamp
|
|
5551
|
+
blockNumber
|
|
5552
|
+
transactionHash
|
|
5553
|
+
filler
|
|
5554
|
+
}
|
|
5557
5555
|
}
|
|
5558
5556
|
}
|
|
5559
5557
|
}
|
|
5560
|
-
|
|
5561
|
-
|
|
5562
|
-
|
|
5563
|
-
|
|
5564
|
-
|
|
5565
|
-
|
|
5566
|
-
|
|
5567
|
-
|
|
5568
|
-
|
|
5569
|
-
|
|
5558
|
+
}`;
|
|
5559
|
+
var TOKEN_GATEWAY_ASSET_TELEPORTED_STATUS = `
|
|
5560
|
+
query TokenGatewayAssetTeleportedStatus($commitment: String!) {
|
|
5561
|
+
tokenGatewayAssetTeleporteds(
|
|
5562
|
+
filter: { commitment: { equalTo: $commitment } }
|
|
5563
|
+
) {
|
|
5564
|
+
nodes {
|
|
5565
|
+
id
|
|
5566
|
+
from
|
|
5567
|
+
to
|
|
5568
|
+
sourceChain
|
|
5569
|
+
destChain
|
|
5570
|
+
commitment
|
|
5571
|
+
amount
|
|
5572
|
+
usdValue
|
|
5573
|
+
assetId
|
|
5574
|
+
redeem
|
|
5575
|
+
status
|
|
5576
|
+
createdAt
|
|
5577
|
+
blockNumber
|
|
5578
|
+
blockTimestamp
|
|
5579
|
+
transactionHash
|
|
5580
|
+
statusMetadata {
|
|
5581
|
+
nodes {
|
|
5582
|
+
status
|
|
5583
|
+
chain
|
|
5584
|
+
timestamp
|
|
5585
|
+
blockNumber
|
|
5586
|
+
transactionHash
|
|
5587
|
+
}
|
|
5588
|
+
}
|
|
5589
|
+
}
|
|
5570
5590
|
}
|
|
5571
|
-
}
|
|
5591
|
+
}`;
|
|
5572
5592
|
function createQueryClient(config) {
|
|
5573
5593
|
return new GraphQLClient(config.url);
|
|
5574
5594
|
}
|
|
@@ -6204,7 +6224,7 @@ var IndexerClient = class {
|
|
|
6204
6224
|
switch (status) {
|
|
6205
6225
|
// request has been dispatched from source chain
|
|
6206
6226
|
case RequestStatus.SOURCE: {
|
|
6207
|
-
|
|
6227
|
+
const sourceUpdate = await this.waitOrAbort({
|
|
6208
6228
|
signal,
|
|
6209
6229
|
promise: () => this.queryStateMachineUpdateByHeight({
|
|
6210
6230
|
statemachineId: request.source,
|
|
@@ -6246,7 +6266,7 @@ var IndexerClient = class {
|
|
|
6246
6266
|
}
|
|
6247
6267
|
// the request has been verified and aggregated on Hyperbridge
|
|
6248
6268
|
case RequestStatus.HYPERBRIDGE_DELIVERED: {
|
|
6249
|
-
|
|
6269
|
+
const hyperbridgeFinalized = await this.waitOrAbort({
|
|
6250
6270
|
signal,
|
|
6251
6271
|
promise: () => {
|
|
6252
6272
|
const stateMachineId = this.config.hyperbridge.stateMachineId;
|
|
@@ -6263,17 +6283,36 @@ var IndexerClient = class {
|
|
|
6263
6283
|
...this.config.hyperbridge,
|
|
6264
6284
|
hasher: "Keccak"
|
|
6265
6285
|
});
|
|
6266
|
-
const
|
|
6267
|
-
{
|
|
6268
|
-
|
|
6269
|
-
|
|
6270
|
-
|
|
6286
|
+
const safeFetchProof = async () => {
|
|
6287
|
+
try {
|
|
6288
|
+
const proof_hex = await hyperbridge.queryProof(
|
|
6289
|
+
{ Requests: [postRequestCommitment(request).commitment] },
|
|
6290
|
+
request.dest,
|
|
6291
|
+
BigInt(hyperbridgeFinalized.height)
|
|
6292
|
+
);
|
|
6293
|
+
return { data: proof_hex, error: null };
|
|
6294
|
+
} catch (err) {
|
|
6295
|
+
return { error: err, data: null };
|
|
6296
|
+
}
|
|
6297
|
+
};
|
|
6298
|
+
const proof = await this.waitOrAbort({
|
|
6299
|
+
signal,
|
|
6300
|
+
promise: () => this.withRetry(safeFetchProof, {
|
|
6301
|
+
backoffMs: 2e3,
|
|
6302
|
+
maxRetries: 6
|
|
6303
|
+
// <-- should fail after 2mins
|
|
6304
|
+
})
|
|
6305
|
+
});
|
|
6306
|
+
if (proof.data === null) {
|
|
6307
|
+
this.logger.error("Failed to fetch proof:", proof.error);
|
|
6308
|
+
throw proof.error;
|
|
6309
|
+
}
|
|
6271
6310
|
const calldata = destChain.encode({
|
|
6272
6311
|
kind: "PostRequest",
|
|
6273
6312
|
proof: {
|
|
6274
6313
|
stateMachine: this.config.hyperbridge.stateMachineId,
|
|
6275
6314
|
consensusStateId: this.config.hyperbridge.consensusStateId,
|
|
6276
|
-
proof,
|
|
6315
|
+
proof: proof.data,
|
|
6277
6316
|
height: BigInt(hyperbridgeFinalized.height)
|
|
6278
6317
|
},
|
|
6279
6318
|
requests: [request],
|
|
@@ -6362,7 +6401,7 @@ var IndexerClient = class {
|
|
|
6362
6401
|
async *getRequestStatusStream(hash) {
|
|
6363
6402
|
const controller = new AbortController();
|
|
6364
6403
|
try {
|
|
6365
|
-
|
|
6404
|
+
const request = await this.waitOrAbort({
|
|
6366
6405
|
signal: controller.signal,
|
|
6367
6406
|
promise: () => this.queryGetRequest(hash)
|
|
6368
6407
|
});
|
|
@@ -6398,7 +6437,7 @@ var IndexerClient = class {
|
|
|
6398
6437
|
switch (status) {
|
|
6399
6438
|
// request has been dispatched from source chain
|
|
6400
6439
|
case RequestStatus.SOURCE: {
|
|
6401
|
-
|
|
6440
|
+
const sourceUpdate = await this.waitOrAbort({
|
|
6402
6441
|
signal,
|
|
6403
6442
|
promise: () => this.queryStateMachineUpdateByHeight({
|
|
6404
6443
|
statemachineId: request.source,
|
|
@@ -6443,7 +6482,7 @@ var IndexerClient = class {
|
|
|
6443
6482
|
if (request.source === this.config.hyperbridge.stateMachineId) {
|
|
6444
6483
|
return;
|
|
6445
6484
|
}
|
|
6446
|
-
|
|
6485
|
+
const hyperbridgeFinalized = await this.waitOrAbort({
|
|
6447
6486
|
signal,
|
|
6448
6487
|
promise: () => this.queryStateMachineUpdateByHeight({
|
|
6449
6488
|
statemachineId: this.config.hyperbridge.stateMachineId,
|
|
@@ -6694,7 +6733,7 @@ var IndexerClient = class {
|
|
|
6694
6733
|
})
|
|
6695
6734
|
});
|
|
6696
6735
|
} else {
|
|
6697
|
-
|
|
6736
|
+
const timeout = await this.waitOrAbort({
|
|
6698
6737
|
signal,
|
|
6699
6738
|
promise: async () => {
|
|
6700
6739
|
const req = await this.queryPostRequest(hash);
|
|
@@ -11364,21 +11403,21 @@ var IntentGateway = class {
|
|
|
11364
11403
|
* protocol fees, and swap operations.
|
|
11365
11404
|
*
|
|
11366
11405
|
* @param order - The order to estimate fill costs for
|
|
11367
|
-
* @returns
|
|
11406
|
+
* @returns An object containing the estimated cost in both fee token and native token, plus the post request calldata
|
|
11368
11407
|
*/
|
|
11369
11408
|
async estimateFillOrder(order) {
|
|
11370
11409
|
const postRequest = {
|
|
11371
11410
|
source: order.destChain,
|
|
11372
11411
|
dest: order.sourceChain,
|
|
11373
|
-
body:
|
|
11412
|
+
body: constructRedeemEscrowRequestBody(order, MOCK_ADDRESS),
|
|
11374
11413
|
timeoutTimestamp: 0n,
|
|
11375
11414
|
nonce: await this.source.getHostNonce(),
|
|
11376
11415
|
from: this.source.config.getIntentGatewayAddress(order.destChain),
|
|
11377
11416
|
to: this.source.config.getIntentGatewayAddress(order.sourceChain)
|
|
11378
11417
|
};
|
|
11379
|
-
const { decimals: sourceChainFeeTokenDecimals } = await this.source.getFeeTokenWithDecimals();
|
|
11418
|
+
const { decimals: sourceChainFeeTokenDecimals, address: sourceChainFeeTokenAddress } = await this.source.getFeeTokenWithDecimals();
|
|
11380
11419
|
const { address: destChainFeeTokenAddress, decimals: destChainFeeTokenDecimals } = await this.dest.getFeeTokenWithDecimals();
|
|
11381
|
-
const postGasEstimate = await this.source.estimateGas(postRequest);
|
|
11420
|
+
const { gas: postGasEstimate, postRequestCalldata } = await this.source.estimateGas(postRequest);
|
|
11382
11421
|
const postGasEstimateInSourceFeeToken = await this.convertGasToFeeToken(
|
|
11383
11422
|
postGasEstimate,
|
|
11384
11423
|
this.source.client,
|
|
@@ -11394,23 +11433,23 @@ var IntentGateway = class {
|
|
|
11394
11433
|
const fillOptions = {
|
|
11395
11434
|
relayerFee: relayerFeeInDestFeeToken
|
|
11396
11435
|
};
|
|
11397
|
-
const totalEthValue = order.outputs.filter((output) =>
|
|
11436
|
+
const totalEthValue = order.outputs.filter((output) => bytes32ToBytes20(output.token) === ADDRESS_ZERO).reduce((sum, output) => sum + output.amount, 0n);
|
|
11398
11437
|
const intentGatewayAddress = this.source.config.getIntentGatewayAddress(order.destChain);
|
|
11399
11438
|
const testValue = toHex(maxUint256 / 2n);
|
|
11400
11439
|
const orderOverrides = await Promise.all(
|
|
11401
11440
|
order.outputs.map(async (output) => {
|
|
11402
|
-
const tokenAddress =
|
|
11403
|
-
if (tokenAddress ===
|
|
11441
|
+
const tokenAddress = bytes32ToBytes20(output.token);
|
|
11442
|
+
if (tokenAddress === ADDRESS_ZERO) {
|
|
11404
11443
|
return null;
|
|
11405
11444
|
}
|
|
11406
11445
|
try {
|
|
11407
11446
|
const stateDiffs = [];
|
|
11408
|
-
const balanceData = "0x70a08231" /* BALANCE_OF */ + bytes20ToBytes32(
|
|
11409
|
-
const balanceSlot = await
|
|
11447
|
+
const balanceData = "0x70a08231" /* BALANCE_OF */ + bytes20ToBytes32(MOCK_ADDRESS).slice(2);
|
|
11448
|
+
const balanceSlot = await getStorageSlot(this.dest.client, tokenAddress, balanceData);
|
|
11410
11449
|
stateDiffs.push({ slot: balanceSlot, value: testValue });
|
|
11411
11450
|
try {
|
|
11412
|
-
const allowanceData = "0xdd62ed3e" /* ALLOWANCE */ + bytes20ToBytes32(
|
|
11413
|
-
const allowanceSlot = await
|
|
11451
|
+
const allowanceData = "0xdd62ed3e" /* ALLOWANCE */ + bytes20ToBytes32(MOCK_ADDRESS).slice(2) + bytes20ToBytes32(intentGatewayAddress).slice(2);
|
|
11452
|
+
const allowanceSlot = await getStorageSlot(
|
|
11414
11453
|
this.dest.client,
|
|
11415
11454
|
tokenAddress,
|
|
11416
11455
|
allowanceData
|
|
@@ -11426,31 +11465,11 @@ var IntentGateway = class {
|
|
|
11426
11465
|
}
|
|
11427
11466
|
})
|
|
11428
11467
|
).then((results) => results.filter(Boolean));
|
|
11429
|
-
|
|
11430
|
-
const destFeeTokenBalanceSlot = await getStorageSlot2(
|
|
11431
|
-
this.dest.client,
|
|
11432
|
-
destChainFeeTokenAddress,
|
|
11433
|
-
destFeeTokenBalanceData
|
|
11434
|
-
);
|
|
11435
|
-
const destFeeTokenAllowanceData = "0xdd62ed3e" /* ALLOWANCE */ + bytes20ToBytes32(MOCK_ADDRESS2).slice(2) + bytes20ToBytes32(intentGatewayAddress).slice(2);
|
|
11436
|
-
const destFeeTokenAllowanceSlot = await getStorageSlot2(
|
|
11437
|
-
this.dest.client,
|
|
11438
|
-
destChainFeeTokenAddress,
|
|
11439
|
-
destFeeTokenAllowanceData
|
|
11440
|
-
);
|
|
11441
|
-
const feeTokenStateDiffs = [
|
|
11442
|
-
{ slot: destFeeTokenBalanceSlot, value: testValue },
|
|
11443
|
-
{ slot: destFeeTokenAllowanceSlot, value: testValue }
|
|
11444
|
-
];
|
|
11445
|
-
orderOverrides.push({
|
|
11446
|
-
address: destChainFeeTokenAddress,
|
|
11447
|
-
stateDiff: feeTokenStateDiffs
|
|
11448
|
-
});
|
|
11449
|
-
const stateOverride = [
|
|
11468
|
+
let stateOverrides = [
|
|
11450
11469
|
// Mock address with ETH balance so that any chain estimation runs
|
|
11451
11470
|
// even when the address doesn't hold any native token in that chain
|
|
11452
11471
|
{
|
|
11453
|
-
address:
|
|
11472
|
+
address: MOCK_ADDRESS,
|
|
11454
11473
|
balance: maxUint256
|
|
11455
11474
|
},
|
|
11456
11475
|
...orderOverrides.map((override) => ({
|
|
@@ -11458,15 +11477,52 @@ var IntentGateway = class {
|
|
|
11458
11477
|
stateDiff: override.stateDiff
|
|
11459
11478
|
}))
|
|
11460
11479
|
];
|
|
11461
|
-
|
|
11462
|
-
|
|
11463
|
-
|
|
11464
|
-
|
|
11465
|
-
|
|
11466
|
-
|
|
11467
|
-
|
|
11468
|
-
|
|
11469
|
-
|
|
11480
|
+
let destChainFillGas = 0n;
|
|
11481
|
+
try {
|
|
11482
|
+
const protocolFeeInNativeToken = await this.quoteNative(postRequest, relayerFeeInDestFeeToken);
|
|
11483
|
+
destChainFillGas = await this.dest.client.estimateContractGas({
|
|
11484
|
+
abi: IntentGateway_default.ABI,
|
|
11485
|
+
address: intentGatewayAddress,
|
|
11486
|
+
functionName: "fillOrder",
|
|
11487
|
+
args: [transformOrderForContract(order), fillOptions],
|
|
11488
|
+
account: MOCK_ADDRESS,
|
|
11489
|
+
value: totalEthValue + protocolFeeInNativeToken,
|
|
11490
|
+
stateOverride: stateOverrides
|
|
11491
|
+
});
|
|
11492
|
+
} catch {
|
|
11493
|
+
console.warn(
|
|
11494
|
+
`Could not estimate gas for fill order with native token as fees for chain ${order.destChain}, now trying with fee token as fees`
|
|
11495
|
+
);
|
|
11496
|
+
const destFeeTokenBalanceData = "0x70a08231" /* BALANCE_OF */ + bytes20ToBytes32(MOCK_ADDRESS).slice(2);
|
|
11497
|
+
const destFeeTokenBalanceSlot = await getStorageSlot(
|
|
11498
|
+
this.dest.client,
|
|
11499
|
+
destChainFeeTokenAddress,
|
|
11500
|
+
destFeeTokenBalanceData
|
|
11501
|
+
);
|
|
11502
|
+
const destFeeTokenAllowanceData = "0xdd62ed3e" /* ALLOWANCE */ + bytes20ToBytes32(MOCK_ADDRESS).slice(2) + bytes20ToBytes32(intentGatewayAddress).slice(2);
|
|
11503
|
+
const destFeeTokenAllowanceSlot = await getStorageSlot(
|
|
11504
|
+
this.dest.client,
|
|
11505
|
+
destChainFeeTokenAddress,
|
|
11506
|
+
destFeeTokenAllowanceData
|
|
11507
|
+
);
|
|
11508
|
+
const feeTokenStateDiffs = [
|
|
11509
|
+
{ slot: destFeeTokenBalanceSlot, value: testValue },
|
|
11510
|
+
{ slot: destFeeTokenAllowanceSlot, value: testValue }
|
|
11511
|
+
];
|
|
11512
|
+
stateOverrides.push({
|
|
11513
|
+
address: destChainFeeTokenAddress,
|
|
11514
|
+
stateDiff: feeTokenStateDiffs
|
|
11515
|
+
});
|
|
11516
|
+
destChainFillGas = await this.dest.client.estimateContractGas({
|
|
11517
|
+
abi: IntentGateway_default.ABI,
|
|
11518
|
+
address: intentGatewayAddress,
|
|
11519
|
+
functionName: "fillOrder",
|
|
11520
|
+
args: [transformOrderForContract(order), fillOptions],
|
|
11521
|
+
account: MOCK_ADDRESS,
|
|
11522
|
+
value: totalEthValue,
|
|
11523
|
+
stateOverride: stateOverrides
|
|
11524
|
+
});
|
|
11525
|
+
}
|
|
11470
11526
|
const fillGasInSourceFeeToken = await this.convertGasToFeeToken(
|
|
11471
11527
|
destChainFillGas,
|
|
11472
11528
|
this.dest.client,
|
|
@@ -11481,17 +11537,88 @@ var IntentGateway = class {
|
|
|
11481
11537
|
const totalEstimate = fillGasInSourceFeeToken + protocolFeeInSourceFeeToken + relayerFeeInSourceFeeToken;
|
|
11482
11538
|
const SWAP_OPERATIONS_BPS = 2500n;
|
|
11483
11539
|
const swapOperationsInFeeToken = totalEstimate * SWAP_OPERATIONS_BPS / 10000n;
|
|
11484
|
-
|
|
11540
|
+
const totalFeeTokenAmount = totalEstimate + swapOperationsInFeeToken;
|
|
11541
|
+
const totalNativeTokenAmount = await this.convertFeeTokenToNative(
|
|
11542
|
+
totalFeeTokenAmount,
|
|
11543
|
+
this.source.client,
|
|
11544
|
+
sourceChainFeeTokenDecimals
|
|
11545
|
+
);
|
|
11546
|
+
return {
|
|
11547
|
+
feeTokenAmount: totalFeeTokenAmount,
|
|
11548
|
+
nativeTokenAmount: totalNativeTokenAmount,
|
|
11549
|
+
postRequestCalldata
|
|
11550
|
+
};
|
|
11551
|
+
}
|
|
11552
|
+
/**
|
|
11553
|
+
* Converts fee token amounts back to the equivalent amount in native token.
|
|
11554
|
+
* Uses USD pricing to convert between fee token amounts and native token costs.
|
|
11555
|
+
*
|
|
11556
|
+
* @param feeTokenAmount - The amount in fee token (DAI)
|
|
11557
|
+
* @param publicClient - The client for the chain to get native token info
|
|
11558
|
+
* @param feeTokenDecimals - The decimal places of the fee token
|
|
11559
|
+
* @returns The fee token amount converted to native token amount
|
|
11560
|
+
* @private
|
|
11561
|
+
*/
|
|
11562
|
+
async convertFeeTokenToNative(feeTokenAmount, publicClient, feeTokenDecimals) {
|
|
11563
|
+
const nativeToken = publicClient.chain?.nativeCurrency;
|
|
11564
|
+
if (!nativeToken?.symbol || !nativeToken?.decimals) {
|
|
11565
|
+
throw new Error("Chain native currency information not available");
|
|
11566
|
+
}
|
|
11567
|
+
const feeTokenAmountNumber = Number(feeTokenAmount) / Math.pow(10, feeTokenDecimals);
|
|
11568
|
+
const nativeTokenPriceUsd = await fetchTokenUsdPrice(nativeToken.symbol);
|
|
11569
|
+
const totalCostInNativeToken = feeTokenAmountNumber / nativeTokenPriceUsd;
|
|
11570
|
+
return BigInt(Math.floor(totalCostInNativeToken * Math.pow(10, nativeToken.decimals)));
|
|
11571
|
+
}
|
|
11572
|
+
/**
|
|
11573
|
+
* Converts gas costs to the equivalent amount in the fee token (DAI).
|
|
11574
|
+
* Uses USD pricing to convert between native token gas costs and fee token amounts.
|
|
11575
|
+
*
|
|
11576
|
+
* @param gasEstimate - The estimated gas units
|
|
11577
|
+
* @param publicClient - The client for the chain to get gas prices
|
|
11578
|
+
* @param targetDecimals - The decimal places of the target fee token
|
|
11579
|
+
* @returns The gas cost converted to fee token amount
|
|
11580
|
+
* @private
|
|
11581
|
+
*/
|
|
11582
|
+
async convertGasToFeeToken(gasEstimate, publicClient, targetDecimals) {
|
|
11583
|
+
const gasPrice = await publicClient.getGasPrice();
|
|
11584
|
+
const gasCostInWei = gasEstimate * gasPrice;
|
|
11585
|
+
const nativeToken = publicClient.chain?.nativeCurrency;
|
|
11586
|
+
if (!nativeToken?.symbol || !nativeToken?.decimals) {
|
|
11587
|
+
throw new Error("Chain native currency information not available");
|
|
11588
|
+
}
|
|
11589
|
+
const gasCostInToken = Number(gasCostInWei) / Math.pow(10, nativeToken.decimals);
|
|
11590
|
+
const tokenPriceUsd = await fetchTokenUsdPrice(nativeToken.symbol);
|
|
11591
|
+
const gasCostUsd = gasCostInToken * tokenPriceUsd;
|
|
11592
|
+
const feeTokenPriceUsd = await fetchTokenUsdPrice("DAI");
|
|
11593
|
+
const gasCostInFeeToken = gasCostUsd / feeTokenPriceUsd;
|
|
11594
|
+
return BigInt(Math.floor(gasCostInFeeToken * Math.pow(10, targetDecimals)));
|
|
11595
|
+
}
|
|
11596
|
+
async quoteNative(postRequest, fee) {
|
|
11597
|
+
const dispatchPost = {
|
|
11598
|
+
dest: toHex(postRequest.dest),
|
|
11599
|
+
to: postRequest.to,
|
|
11600
|
+
body: postRequest.body,
|
|
11601
|
+
timeout: postRequest.timeoutTimestamp,
|
|
11602
|
+
fee,
|
|
11603
|
+
payer: postRequest.from
|
|
11604
|
+
};
|
|
11605
|
+
const quoteNative = await this.dest.client.readContract({
|
|
11606
|
+
address: this.dest.config.getIntentGatewayAddress(postRequest.dest),
|
|
11607
|
+
abi: IntentGateway_default.ABI,
|
|
11608
|
+
functionName: "quoteNative",
|
|
11609
|
+
args: [dispatchPost]
|
|
11610
|
+
});
|
|
11611
|
+
return quoteNative;
|
|
11485
11612
|
}
|
|
11486
11613
|
/**
|
|
11487
|
-
* Finds the best Uniswap protocol (V2 or
|
|
11614
|
+
* Finds the best Uniswap protocol (V2, V3, or V4) for swapping tokens given a desired output amount.
|
|
11488
11615
|
* Compares liquidity and pricing across different protocols and fee tiers.
|
|
11489
11616
|
*
|
|
11490
11617
|
* @param chain - The chain identifier where the swap will occur
|
|
11491
11618
|
* @param tokenIn - The address of the input token
|
|
11492
11619
|
* @param tokenOut - The address of the output token
|
|
11493
11620
|
* @param amountOut - The desired output amount
|
|
11494
|
-
* @returns Object containing the best protocol, required input amount, and fee tier (for V3)
|
|
11621
|
+
* @returns Object containing the best protocol, required input amount, and fee tier (for V3/V4)
|
|
11495
11622
|
*/
|
|
11496
11623
|
async findBestProtocolWithAmountOut(chain, tokenIn, tokenOut, amountOut) {
|
|
11497
11624
|
const destClient = this.dest.client;
|
|
@@ -11507,8 +11634,8 @@ var IntentGateway = class {
|
|
|
11507
11634
|
const v3Quoter = this.source.config.getUniswapV3QuoterAddress(chain);
|
|
11508
11635
|
const v4Quoter = this.source.config.getUniswapV4QuoterAddress(chain);
|
|
11509
11636
|
const wethAsset = this.source.config.getWrappedNativeAssetWithDecimals(chain).asset;
|
|
11510
|
-
const tokenInForQuote = tokenIn ===
|
|
11511
|
-
const tokenOutForQuote = tokenOut ===
|
|
11637
|
+
const tokenInForQuote = tokenIn === ADDRESS_ZERO ? wethAsset : tokenIn;
|
|
11638
|
+
const tokenOutForQuote = tokenOut === ADDRESS_ZERO ? wethAsset : tokenOut;
|
|
11512
11639
|
try {
|
|
11513
11640
|
const v2PairExists = await destClient.readContract({
|
|
11514
11641
|
address: v2Factory,
|
|
@@ -11516,7 +11643,7 @@ var IntentGateway = class {
|
|
|
11516
11643
|
functionName: "getPair",
|
|
11517
11644
|
args: [tokenInForQuote, tokenOutForQuote]
|
|
11518
11645
|
});
|
|
11519
|
-
if (v2PairExists !==
|
|
11646
|
+
if (v2PairExists !== ADDRESS_ZERO) {
|
|
11520
11647
|
const v2AmountIn = await destClient.readContract({
|
|
11521
11648
|
address: v2Router,
|
|
11522
11649
|
abi: uniswapRouterV2_default.ABI,
|
|
@@ -11537,7 +11664,7 @@ var IntentGateway = class {
|
|
|
11537
11664
|
functionName: "getPool",
|
|
11538
11665
|
args: [tokenInForQuote, tokenOutForQuote, fee]
|
|
11539
11666
|
});
|
|
11540
|
-
if (pool !==
|
|
11667
|
+
if (pool !== ADDRESS_ZERO) {
|
|
11541
11668
|
const liquidity = await destClient.readContract({
|
|
11542
11669
|
address: pool,
|
|
11543
11670
|
abi: uniswapV3Pool_default.ABI,
|
|
@@ -11581,7 +11708,7 @@ var IntentGateway = class {
|
|
|
11581
11708
|
currency1,
|
|
11582
11709
|
fee,
|
|
11583
11710
|
tickSpacing: this.getTickSpacing(fee),
|
|
11584
|
-
hooks:
|
|
11711
|
+
hooks: ADDRESS_ZERO
|
|
11585
11712
|
// No hooks
|
|
11586
11713
|
};
|
|
11587
11714
|
const quoteResult = (await destClient.simulateContract({
|
|
@@ -11648,14 +11775,14 @@ var IntentGateway = class {
|
|
|
11648
11775
|
}
|
|
11649
11776
|
}
|
|
11650
11777
|
/**
|
|
11651
|
-
* Finds the best Uniswap protocol (V2 or
|
|
11778
|
+
* Finds the best Uniswap protocol (V2, V3, or V4) for swapping tokens given an input amount.
|
|
11652
11779
|
* Compares liquidity and pricing across different protocols and fee tiers.
|
|
11653
11780
|
*
|
|
11654
11781
|
* @param chain - The chain identifier where the swap will occur
|
|
11655
11782
|
* @param tokenIn - The address of the input token
|
|
11656
11783
|
* @param tokenOut - The address of the output token
|
|
11657
11784
|
* @param amountIn - The input amount to swap
|
|
11658
|
-
* @returns Object containing the best protocol, expected output amount, and fee tier (for V3)
|
|
11785
|
+
* @returns Object containing the best protocol, expected output amount, and fee tier (for V3/V4)
|
|
11659
11786
|
*/
|
|
11660
11787
|
async findBestProtocolWithAmountIn(chain, tokenIn, tokenOut, amountIn) {
|
|
11661
11788
|
const destClient = this.dest.client;
|
|
@@ -11671,8 +11798,8 @@ var IntentGateway = class {
|
|
|
11671
11798
|
const v3Quoter = this.source.config.getUniswapV3QuoterAddress(chain);
|
|
11672
11799
|
const v4Quoter = this.source.config.getUniswapV4QuoterAddress(chain);
|
|
11673
11800
|
const wethAsset = this.source.config.getWrappedNativeAssetWithDecimals(chain).asset;
|
|
11674
|
-
const tokenInForQuote = tokenIn ===
|
|
11675
|
-
const tokenOutForQuote = tokenOut ===
|
|
11801
|
+
const tokenInForQuote = tokenIn === ADDRESS_ZERO ? wethAsset : tokenIn;
|
|
11802
|
+
const tokenOutForQuote = tokenOut === ADDRESS_ZERO ? wethAsset : tokenOut;
|
|
11676
11803
|
try {
|
|
11677
11804
|
const v2PairExists = await destClient.readContract({
|
|
11678
11805
|
address: v2Factory,
|
|
@@ -11680,7 +11807,7 @@ var IntentGateway = class {
|
|
|
11680
11807
|
functionName: "getPair",
|
|
11681
11808
|
args: [tokenInForQuote, tokenOutForQuote]
|
|
11682
11809
|
});
|
|
11683
|
-
if (v2PairExists !==
|
|
11810
|
+
if (v2PairExists !== ADDRESS_ZERO) {
|
|
11684
11811
|
const v2AmountOut = await destClient.readContract({
|
|
11685
11812
|
address: v2Router,
|
|
11686
11813
|
abi: uniswapRouterV2_default.ABI,
|
|
@@ -11701,7 +11828,7 @@ var IntentGateway = class {
|
|
|
11701
11828
|
functionName: "getPool",
|
|
11702
11829
|
args: [tokenInForQuote, tokenOutForQuote, fee]
|
|
11703
11830
|
});
|
|
11704
|
-
if (pool !==
|
|
11831
|
+
if (pool !== ADDRESS_ZERO) {
|
|
11705
11832
|
const liquidity = await destClient.readContract({
|
|
11706
11833
|
address: pool,
|
|
11707
11834
|
abi: uniswapV3Pool_default.ABI,
|
|
@@ -11745,7 +11872,7 @@ var IntentGateway = class {
|
|
|
11745
11872
|
currency1,
|
|
11746
11873
|
fee,
|
|
11747
11874
|
tickSpacing: this.getTickSpacing(fee),
|
|
11748
|
-
hooks:
|
|
11875
|
+
hooks: ADDRESS_ZERO
|
|
11749
11876
|
// No hooks
|
|
11750
11877
|
};
|
|
11751
11878
|
const quoteResult = (await destClient.simulateContract({
|
|
@@ -11811,30 +11938,6 @@ var IntentGateway = class {
|
|
|
11811
11938
|
};
|
|
11812
11939
|
}
|
|
11813
11940
|
}
|
|
11814
|
-
/**
|
|
11815
|
-
* Converts gas costs to the equivalent amount in the fee token (DAI).
|
|
11816
|
-
* Uses USD pricing to convert between native token gas costs and fee token amounts.
|
|
11817
|
-
*
|
|
11818
|
-
* @param gasEstimate - The estimated gas units
|
|
11819
|
-
* @param publicClient - The client for the chain to get gas prices
|
|
11820
|
-
* @param targetDecimals - The decimal places of the target fee token
|
|
11821
|
-
* @returns The gas cost converted to fee token amount
|
|
11822
|
-
* @private
|
|
11823
|
-
*/
|
|
11824
|
-
async convertGasToFeeToken(gasEstimate, publicClient, targetDecimals) {
|
|
11825
|
-
const gasPrice = await publicClient.getGasPrice();
|
|
11826
|
-
const gasCostInWei = gasEstimate * gasPrice;
|
|
11827
|
-
const nativeToken = publicClient.chain?.nativeCurrency;
|
|
11828
|
-
if (!nativeToken?.symbol || !nativeToken?.decimals) {
|
|
11829
|
-
throw new Error("Chain native currency information not available");
|
|
11830
|
-
}
|
|
11831
|
-
const gasCostInToken = Number(gasCostInWei) / Math.pow(10, nativeToken.decimals);
|
|
11832
|
-
const tokenPriceUsd = await fetchTokenUsdPrice2(nativeToken.symbol);
|
|
11833
|
-
const gasCostUsd = gasCostInToken * tokenPriceUsd;
|
|
11834
|
-
const feeTokenPriceUsd = await fetchTokenUsdPrice2("DAI");
|
|
11835
|
-
const gasCostInFeeToken = gasCostUsd / feeTokenPriceUsd;
|
|
11836
|
-
return BigInt(Math.floor(gasCostInFeeToken * Math.pow(10, targetDecimals)));
|
|
11837
|
-
}
|
|
11838
11941
|
/**
|
|
11839
11942
|
* Checks if an order has been filled by verifying the commitment status on-chain.
|
|
11840
11943
|
* Reads the storage slot corresponding to the order's commitment hash.
|
|
@@ -12199,6 +12302,6 @@ async function teleportDot(param_) {
|
|
|
12199
12302
|
return stream;
|
|
12200
12303
|
}
|
|
12201
12304
|
|
|
12202
|
-
export {
|
|
12305
|
+
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
12306
|
//# sourceMappingURL=index.js.map
|
|
12204
12307
|
//# sourceMappingURL=index.js.map
|