@hyperbridge/sdk 2.8.12 → 2.8.16
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 +807 -906
- package/dist/browser/index.js +1487 -2099
- package/dist/browser/index.js.map +1 -1
- package/dist/node/index.cjs +1510 -2117
- package/dist/node/index.cjs.map +1 -1
- package/dist/node/index.d.cts +405 -179
- package/dist/node/index.d.ts +405 -179
- package/dist/node/index.js +1487 -2099
- package/dist/node/index.js.map +1 -1
- package/dist/node/{intents-helpers-C9PJp8rx.d.cts → intents-helpers-BHl2If1T.d.cts} +909 -2908
- package/dist/node/{intents-helpers-C9PJp8rx.d.ts → intents-helpers-BHl2If1T.d.ts} +909 -2908
- package/dist/node/intents-helpers.cjs +499 -1229
- package/dist/node/intents-helpers.cjs.map +1 -1
- package/dist/node/intents-helpers.d.cts +1 -3
- package/dist/node/intents-helpers.d.ts +1 -3
- package/dist/node/intents-helpers.js +498 -1214
- package/dist/node/intents-helpers.js.map +1 -1
- package/package.json +1 -1
package/dist/node/index.js
CHANGED
|
@@ -2,16 +2,16 @@ import { readFileSync } from 'fs';
|
|
|
2
2
|
import { join } from 'path';
|
|
3
3
|
import { TextDecoder as TextDecoder$1, TextEncoder as TextEncoder$1 } from 'util';
|
|
4
4
|
import { createConsola, LogLevels } from 'consola';
|
|
5
|
-
import { defineChain, keccak256, toHex, createPublicClient, http, hexToBytes, toFunctionSelector, bytesToHex, encodeFunctionData, erc20Abi, bytesToBigInt, pad, toBytes, numberToBytes,
|
|
5
|
+
import { defineChain, keccak256, toHex, parseAbi, createPublicClient, http, hexToBytes, toFunctionSelector, bytesToHex, encodeFunctionData, erc20Abi, bytesToBigInt, pad, toBytes, numberToBytes, getAddress, encodeAbiParameters, isHex, isAddress, maxUint256, parseAbiParameters, encodePacked, parseAbiItem, concat, decodeFunctionData, decodeAbiParameters, hexToString as hexToString$1, decodeEventLog, parseEventLogs, parseUnits, concatHex, formatUnits, toEventSelector } from 'viem';
|
|
6
6
|
import { baseSepolia, optimismSepolia, arbitrumSepolia, soneium, gnosis, optimism, polygonAmoy, polygon, base, arbitrum, bsc, mainnet, sepolia, gnosisChiado, bscTestnet, tron, unichain } from 'viem/chains';
|
|
7
|
-
import {
|
|
7
|
+
import { base58Decode, keccakAsU8a, decodeAddress, keccakAsHex, xxhashAsU8a, blake2AsU8a } from '@polkadot/util-crypto';
|
|
8
8
|
import { flatten, zip, capitalize, maxBy, isNil } from 'lodash-es';
|
|
9
9
|
import { match } from 'ts-pattern';
|
|
10
10
|
import { WsProvider, ApiPromise, Keyring, HttpProvider } from '@polkadot/api';
|
|
11
11
|
import { Struct, Vector, u8, Bytes, Enum, Tuple, _void, u64, u32, Option, bool, u128 } from 'scale-ts';
|
|
12
|
-
import {
|
|
13
|
-
import { u8aToHex, u8aConcat, hexToU8a, stringToU8a, isHex as isHex$1, u8aToString } from '@polkadot/util';
|
|
12
|
+
import { hexToU8a, u8aToHex, u8aConcat, isHex as isHex$1 } from '@polkadot/util';
|
|
14
13
|
import PQueue from 'p-queue';
|
|
14
|
+
import { TronWeb } from 'tronweb';
|
|
15
15
|
import { hasWindow, isNode, env } from 'std-env';
|
|
16
16
|
import mergeRace from '@async-generator/merge-race';
|
|
17
17
|
import { GraphQLClient } from 'graphql-request';
|
|
@@ -269,6 +269,7 @@ var OrderStatus = /* @__PURE__ */ ((OrderStatus2) => {
|
|
|
269
269
|
OrderStatus2["FILLED"] = "FILLED";
|
|
270
270
|
OrderStatus2["REDEEMED"] = "REDEEMED";
|
|
271
271
|
OrderStatus2["REFUNDED"] = "REFUNDED";
|
|
272
|
+
OrderStatus2["CANCELLED"] = "CANCELLED";
|
|
272
273
|
return OrderStatus2;
|
|
273
274
|
})(OrderStatus || {});
|
|
274
275
|
var TeleportStatus = /* @__PURE__ */ ((TeleportStatus2) => {
|
|
@@ -283,6 +284,8 @@ var RequestKind = /* @__PURE__ */ ((RequestKind2) => {
|
|
|
283
284
|
RequestKind2[RequestKind2["UpdateParams"] = 2] = "UpdateParams";
|
|
284
285
|
RequestKind2[RequestKind2["SweepDust"] = 3] = "SweepDust";
|
|
285
286
|
RequestKind2[RequestKind2["RefundEscrow"] = 4] = "RefundEscrow";
|
|
287
|
+
RequestKind2[RequestKind2["Execute"] = 5] = "Execute";
|
|
288
|
+
RequestKind2[RequestKind2["RedeemEscrowPartial"] = 6] = "RedeemEscrowPartial";
|
|
286
289
|
return RequestKind2;
|
|
287
290
|
})(RequestKind || {});
|
|
288
291
|
var IntentOrderStatus = Object.freeze({
|
|
@@ -295,6 +298,7 @@ var IntentOrderStatus = Object.freeze({
|
|
|
295
298
|
BID_SELECTED: "BID_SELECTED",
|
|
296
299
|
FILLED: "FILLED",
|
|
297
300
|
PARTIAL_FILL: "PARTIAL_FILL",
|
|
301
|
+
CANCELLED: "CANCELLED",
|
|
298
302
|
EXPIRED: "EXPIRED",
|
|
299
303
|
FAILED: "FAILED"
|
|
300
304
|
});
|
|
@@ -2477,7 +2481,12 @@ var ABI2 = [
|
|
|
2477
2481
|
];
|
|
2478
2482
|
var handlerV2_default = { ABI: ABI2 };
|
|
2479
2483
|
function tronAddress(base58) {
|
|
2480
|
-
|
|
2484
|
+
const decoded = base58Decode(base58);
|
|
2485
|
+
if (decoded.length !== 25 || decoded[0] !== 65) {
|
|
2486
|
+
throw new Error(`Not a Tron base58 address: ${base58}`);
|
|
2487
|
+
}
|
|
2488
|
+
const hex = Array.from(decoded.slice(1, 21), (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
2489
|
+
return `0x${hex}`;
|
|
2481
2490
|
}
|
|
2482
2491
|
var Chains = /* @__PURE__ */ ((Chains2) => {
|
|
2483
2492
|
Chains2["BSC_CHAPEL"] = "EVM-97";
|
|
@@ -2564,11 +2573,13 @@ var chainConfigs = {
|
|
|
2564
2573
|
WETH: "0xae13d989dac2f0debff460ac112a837c89baa7cd",
|
|
2565
2574
|
DAI: "0x1938165569a5463327fb206be06d8d9253aa06b7",
|
|
2566
2575
|
USDC: "0xA801da100bF16D07F668F4A49E1f71fc54D05177",
|
|
2567
|
-
USDT: "0xc043f483373072f7f27420d6e7d7ad269c018e18"
|
|
2576
|
+
USDT: "0xc043f483373072f7f27420d6e7d7ad269c018e18",
|
|
2577
|
+
cNGN: "0x2bbbd701cfc25d37f18127e51df0933566d5778a"
|
|
2568
2578
|
},
|
|
2569
2579
|
tokenDecimals: {
|
|
2570
2580
|
USDC: 18,
|
|
2571
|
-
USDT: 18
|
|
2581
|
+
USDT: 18,
|
|
2582
|
+
cNGN: 6
|
|
2572
2583
|
},
|
|
2573
2584
|
tokenStorageSlots: {
|
|
2574
2585
|
USDC: { balanceSlot: 1, allowanceSlot: 2 },
|
|
@@ -2585,7 +2596,7 @@ var chainConfigs = {
|
|
|
2585
2596
|
UniswapV3Quoter: "0x0000000000000000000000000000000000000000",
|
|
2586
2597
|
UniswapV4Quoter: "0x0000000000000000000000000000000000000000",
|
|
2587
2598
|
EntryPointV08: "0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108",
|
|
2588
|
-
SolverAccount: "
|
|
2599
|
+
SolverAccount: "0x153DB990FE3b761B54ad71D0f1A0987dF11740DB"
|
|
2589
2600
|
},
|
|
2590
2601
|
rpcEnvKey: "BSC_CHAPEL",
|
|
2591
2602
|
defaultRpcUrl: "https://bnb-testnet.api.onfinality.io/public",
|
|
@@ -2711,7 +2722,7 @@ var chainConfigs = {
|
|
|
2711
2722
|
},
|
|
2712
2723
|
addresses: {
|
|
2713
2724
|
IntentGateway: "0xAe041F7B0CB581876832830baeB6a2Aa2a3C9716",
|
|
2714
|
-
SolverAccount: "
|
|
2725
|
+
SolverAccount: "0xd5535d4DeB17F050e52B6efda2fDe00435f39279",
|
|
2715
2726
|
TokenGateway: "0xFd413e3AFe560182C4471F4d143A96d3e259B6dE",
|
|
2716
2727
|
Host: "0x620128E2B19193d6Bd244a3AC8D3bBa0541B19c3",
|
|
2717
2728
|
UniswapRouter02: "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D",
|
|
@@ -2778,7 +2789,7 @@ var chainConfigs = {
|
|
|
2778
2789
|
},
|
|
2779
2790
|
addresses: {
|
|
2780
2791
|
IntentGateway: "0xAe041F7B0CB581876832830baeB6a2Aa2a3C9716",
|
|
2781
|
-
SolverAccount: "
|
|
2792
|
+
SolverAccount: "0xd5535d4DeB17F050e52B6efda2fDe00435f39279",
|
|
2782
2793
|
TokenGateway: "0xFd413e3AFe560182C4471F4d143A96d3e259B6dE",
|
|
2783
2794
|
Host: "0x620128E2B19193d6Bd244a3AC8D3bBa0541B19c3",
|
|
2784
2795
|
UniswapRouter02: "0x10ED43C718714eb63d5aA57B78B54704E256024E",
|
|
@@ -2839,7 +2850,7 @@ var chainConfigs = {
|
|
|
2839
2850
|
},
|
|
2840
2851
|
addresses: {
|
|
2841
2852
|
IntentGateway: "0xAe041F7B0CB581876832830baeB6a2Aa2a3C9716",
|
|
2842
|
-
SolverAccount: "
|
|
2853
|
+
SolverAccount: "0xd5535d4DeB17F050e52B6efda2fDe00435f39279",
|
|
2843
2854
|
TokenGateway: "0xFd413e3AFe560182C4471F4d143A96d3e259B6dE",
|
|
2844
2855
|
Host: "0x620128E2B19193d6Bd244a3AC8D3bBa0541B19c3",
|
|
2845
2856
|
UniswapRouter02: "0x4752ba5DBc23f44D87826276BF6Fd6b1C372aD24",
|
|
@@ -2913,7 +2924,7 @@ var chainConfigs = {
|
|
|
2913
2924
|
},
|
|
2914
2925
|
addresses: {
|
|
2915
2926
|
IntentGateway: "0xAe041F7B0CB581876832830baeB6a2Aa2a3C9716",
|
|
2916
|
-
SolverAccount: "
|
|
2927
|
+
SolverAccount: "0xd5535d4DeB17F050e52B6efda2fDe00435f39279",
|
|
2917
2928
|
TokenGateway: "0xFd413e3AFe560182C4471F4d143A96d3e259B6dE",
|
|
2918
2929
|
Host: "0x620128E2B19193d6Bd244a3AC8D3bBa0541B19c3",
|
|
2919
2930
|
UniswapRouter02: "0x4752ba5DBc23f44D87826276BF6Fd6b1C372aD24",
|
|
@@ -2938,7 +2949,6 @@ var chainConfigs = {
|
|
|
2938
2949
|
consensusStateId: "ETH0",
|
|
2939
2950
|
coingeckoId: "base",
|
|
2940
2951
|
layerZeroEid: 30184,
|
|
2941
|
-
uniswapV4Pools: [{ tokens: ["USDC", "cNGN"], fee: 1500, tickSpacing: 30 }],
|
|
2942
2952
|
erc4626Vaults: [
|
|
2943
2953
|
{ label: "Aave stataUSDC", address: "0xC768c589647798a6EE01A91FdE98EF2ed046DBD6", asset: "USDC" },
|
|
2944
2954
|
{ label: "Yield Bearing cNGN", address: "0xa82A3531021317240Fb32E67f9c7bC091F737D3b", asset: "cNGN" }
|
|
@@ -2988,7 +2998,7 @@ var chainConfigs = {
|
|
|
2988
2998
|
},
|
|
2989
2999
|
addresses: {
|
|
2990
3000
|
IntentGateway: "0xAe041F7B0CB581876832830baeB6a2Aa2a3C9716",
|
|
2991
|
-
SolverAccount: "
|
|
3001
|
+
SolverAccount: "0xd5535d4DeB17F050e52B6efda2fDe00435f39279",
|
|
2992
3002
|
TokenGateway: "0x8b536105b6Fae2aE9199f5146D3C57Dfe53b614E",
|
|
2993
3003
|
Host: "0x620128E2B19193d6Bd244a3AC8D3bBa0541B19c3",
|
|
2994
3004
|
UniswapRouter02: "0xd2f9496824951D5237cC71245D659E48d0d5f9E8",
|
|
@@ -3063,11 +3073,13 @@ var chainConfigs = {
|
|
|
3063
3073
|
//wmatic, change it to wpol
|
|
3064
3074
|
DAI: "0x0000000000000000000000000000000000000000",
|
|
3065
3075
|
USDC: "0xBE97E73126D66188d72fbF99029126D0340a7f18",
|
|
3066
|
-
USDT: "0x0000000000000000000000000000000000000000"
|
|
3076
|
+
USDT: "0x0000000000000000000000000000000000000000",
|
|
3077
|
+
cNGN: "0xe4ff5d2ae65c10f530c000215029919961e8a758"
|
|
3067
3078
|
},
|
|
3068
3079
|
tokenDecimals: {
|
|
3069
3080
|
USDC: 18,
|
|
3070
|
-
USDT: 18
|
|
3081
|
+
USDT: 18,
|
|
3082
|
+
cNGN: 6
|
|
3071
3083
|
},
|
|
3072
3084
|
tokenStorageSlots: {
|
|
3073
3085
|
USDT: { balanceSlot: 0, allowanceSlot: 1 },
|
|
@@ -3080,7 +3092,7 @@ var chainConfigs = {
|
|
|
3080
3092
|
Calldispatcher: "0x876F1891982E260026630c233A4897160A281Fb8",
|
|
3081
3093
|
Permit2: "0x000000000022D473030F116dDEE9F6B43aC78BA3",
|
|
3082
3094
|
EntryPointV08: "0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108",
|
|
3083
|
-
SolverAccount: "
|
|
3095
|
+
SolverAccount: "0x153DB990FE3b761B54ad71D0f1A0987dF11740DB"
|
|
3084
3096
|
},
|
|
3085
3097
|
rpcEnvKey: "POLYGON_AMOY",
|
|
3086
3098
|
defaultRpcUrl: "https://rpc-amoy.polygon.technology",
|
|
@@ -3104,7 +3116,7 @@ var chainConfigs = {
|
|
|
3104
3116
|
},
|
|
3105
3117
|
addresses: {
|
|
3106
3118
|
IntentGateway: "0xAe041F7B0CB581876832830baeB6a2Aa2a3C9716",
|
|
3107
|
-
SolverAccount: "
|
|
3119
|
+
SolverAccount: "0xd5535d4DeB17F050e52B6efda2fDe00435f39279",
|
|
3108
3120
|
TokenGateway: "0xFd413e3AFe560182C4471F4d143A96d3e259B6dE",
|
|
3109
3121
|
Host: "0x620128E2B19193d6Bd244a3AC8D3bBa0541B19c3",
|
|
3110
3122
|
UniswapRouter02: "0x4A7b5Da61326A6379179b40d00F57E5bbDC962c2",
|
|
@@ -3139,7 +3151,7 @@ var chainConfigs = {
|
|
|
3139
3151
|
},
|
|
3140
3152
|
addresses: {
|
|
3141
3153
|
IntentGateway: "0xAe041F7B0CB581876832830baeB6a2Aa2a3C9716",
|
|
3142
|
-
SolverAccount: "
|
|
3154
|
+
SolverAccount: "0xd5535d4DeB17F050e52B6efda2fDe00435f39279",
|
|
3143
3155
|
TokenGateway: "0xFd413e3AFe560182C4471F4d143A96d3e259B6dE",
|
|
3144
3156
|
Host: "0x620128E2B19193d6Bd244a3AC8D3bBa0541B19c3",
|
|
3145
3157
|
UniswapRouter02: "0xB2e26652e4BAd1e56055A051f922E06760cA0BFE",
|
|
@@ -3295,7 +3307,7 @@ var chainConfigs = {
|
|
|
3295
3307
|
},
|
|
3296
3308
|
addresses: {
|
|
3297
3309
|
IntentGateway: "0xAe041F7B0CB581876832830baeB6a2Aa2a3C9716",
|
|
3298
|
-
SolverAccount: "
|
|
3310
|
+
SolverAccount: "0xd5535d4DeB17F050e52B6efda2fDe00435f39279",
|
|
3299
3311
|
Host: "0x620128E2B19193d6Bd244a3AC8D3bBa0541B19c3",
|
|
3300
3312
|
Calldispatcher: "0xE2C7e576E26E0bE7aC97c6fE925bcDAbD87c4bEd"
|
|
3301
3313
|
},
|
|
@@ -3342,7 +3354,12 @@ var ABI3 = [
|
|
|
3342
3354
|
type: "constructor",
|
|
3343
3355
|
inputs: [
|
|
3344
3356
|
{
|
|
3345
|
-
name: "
|
|
3357
|
+
name: "intrinsic",
|
|
3358
|
+
type: "address",
|
|
3359
|
+
internalType: "address"
|
|
3360
|
+
},
|
|
3361
|
+
{
|
|
3362
|
+
name: "extrinsic",
|
|
3346
3363
|
type: "address",
|
|
3347
3364
|
internalType: "address"
|
|
3348
3365
|
}
|
|
@@ -3441,8 +3458,8 @@ var ABI3 = [
|
|
|
3441
3458
|
},
|
|
3442
3459
|
{
|
|
3443
3460
|
name: "",
|
|
3444
|
-
type: "
|
|
3445
|
-
internalType: "
|
|
3461
|
+
type: "uint256",
|
|
3462
|
+
internalType: "uint256"
|
|
3446
3463
|
}
|
|
3447
3464
|
],
|
|
3448
3465
|
outputs: [
|
|
@@ -3456,20 +3473,31 @@ var ABI3 = [
|
|
|
3456
3473
|
},
|
|
3457
3474
|
{
|
|
3458
3475
|
type: "function",
|
|
3459
|
-
name: "
|
|
3460
|
-
inputs: [
|
|
3476
|
+
name: "_partialFills",
|
|
3477
|
+
inputs: [
|
|
3478
|
+
{
|
|
3479
|
+
name: "",
|
|
3480
|
+
type: "bytes32",
|
|
3481
|
+
internalType: "bytes32"
|
|
3482
|
+
},
|
|
3483
|
+
{
|
|
3484
|
+
name: "",
|
|
3485
|
+
type: "uint256",
|
|
3486
|
+
internalType: "uint256"
|
|
3487
|
+
}
|
|
3488
|
+
],
|
|
3461
3489
|
outputs: [
|
|
3462
3490
|
{
|
|
3463
3491
|
name: "",
|
|
3464
|
-
type: "
|
|
3465
|
-
internalType: "
|
|
3492
|
+
type: "uint256",
|
|
3493
|
+
internalType: "uint256"
|
|
3466
3494
|
}
|
|
3467
3495
|
],
|
|
3468
3496
|
stateMutability: "view"
|
|
3469
3497
|
},
|
|
3470
3498
|
{
|
|
3471
3499
|
type: "function",
|
|
3472
|
-
name: "
|
|
3500
|
+
name: "_protocolFees",
|
|
3473
3501
|
inputs: [
|
|
3474
3502
|
{
|
|
3475
3503
|
name: "",
|
|
@@ -3478,19 +3506,31 @@ var ABI3 = [
|
|
|
3478
3506
|
},
|
|
3479
3507
|
{
|
|
3480
3508
|
name: "",
|
|
3481
|
-
type: "
|
|
3482
|
-
internalType: "
|
|
3509
|
+
type: "uint256",
|
|
3510
|
+
internalType: "uint256"
|
|
3483
3511
|
}
|
|
3484
3512
|
],
|
|
3485
3513
|
outputs: [
|
|
3486
3514
|
{
|
|
3487
|
-
name: "",
|
|
3515
|
+
name: "amount",
|
|
3516
|
+
type: "uint256",
|
|
3517
|
+
internalType: "uint256"
|
|
3518
|
+
},
|
|
3519
|
+
{
|
|
3520
|
+
name: "committed",
|
|
3488
3521
|
type: "uint256",
|
|
3489
3522
|
internalType: "uint256"
|
|
3490
3523
|
}
|
|
3491
3524
|
],
|
|
3492
3525
|
stateMutability: "view"
|
|
3493
3526
|
},
|
|
3527
|
+
{
|
|
3528
|
+
type: "function",
|
|
3529
|
+
name: "acceptOwnership",
|
|
3530
|
+
inputs: [],
|
|
3531
|
+
outputs: [],
|
|
3532
|
+
stateMutability: "nonpayable"
|
|
3533
|
+
},
|
|
3494
3534
|
{
|
|
3495
3535
|
type: "function",
|
|
3496
3536
|
name: "calculateCommitmentSlotHash",
|
|
@@ -3700,6 +3740,19 @@ var ABI3 = [
|
|
|
3700
3740
|
],
|
|
3701
3741
|
stateMutability: "view"
|
|
3702
3742
|
},
|
|
3743
|
+
{
|
|
3744
|
+
type: "function",
|
|
3745
|
+
name: "extrinsicModule",
|
|
3746
|
+
inputs: [],
|
|
3747
|
+
outputs: [
|
|
3748
|
+
{
|
|
3749
|
+
name: "",
|
|
3750
|
+
type: "address",
|
|
3751
|
+
internalType: "address"
|
|
3752
|
+
}
|
|
3753
|
+
],
|
|
3754
|
+
stateMutability: "view"
|
|
3755
|
+
},
|
|
3703
3756
|
{
|
|
3704
3757
|
type: "function",
|
|
3705
3758
|
name: "fillOrder",
|
|
@@ -3862,6 +3915,23 @@ var ABI3 = [
|
|
|
3862
3915
|
internalType: "uint256"
|
|
3863
3916
|
}
|
|
3864
3917
|
]
|
|
3918
|
+
},
|
|
3919
|
+
{
|
|
3920
|
+
name: "inputs",
|
|
3921
|
+
type: "tuple[]",
|
|
3922
|
+
internalType: "struct TokenInfo[]",
|
|
3923
|
+
components: [
|
|
3924
|
+
{
|
|
3925
|
+
name: "token",
|
|
3926
|
+
type: "bytes32",
|
|
3927
|
+
internalType: "bytes32"
|
|
3928
|
+
},
|
|
3929
|
+
{
|
|
3930
|
+
name: "amount",
|
|
3931
|
+
type: "uint256",
|
|
3932
|
+
internalType: "uint256"
|
|
3933
|
+
}
|
|
3934
|
+
]
|
|
3865
3935
|
}
|
|
3866
3936
|
]
|
|
3867
3937
|
}
|
|
@@ -3887,51 +3957,63 @@ var ABI3 = [
|
|
|
3887
3957
|
name: "initialize",
|
|
3888
3958
|
inputs: [
|
|
3889
3959
|
{
|
|
3890
|
-
name: "
|
|
3960
|
+
name: "init",
|
|
3891
3961
|
type: "tuple",
|
|
3892
|
-
internalType: "struct
|
|
3962
|
+
internalType: "struct InitParams",
|
|
3893
3963
|
components: [
|
|
3894
3964
|
{
|
|
3895
|
-
name: "
|
|
3896
|
-
type: "
|
|
3897
|
-
internalType: "
|
|
3898
|
-
|
|
3899
|
-
|
|
3900
|
-
|
|
3901
|
-
|
|
3902
|
-
|
|
3903
|
-
|
|
3904
|
-
|
|
3905
|
-
|
|
3906
|
-
|
|
3907
|
-
|
|
3965
|
+
name: "params",
|
|
3966
|
+
type: "tuple",
|
|
3967
|
+
internalType: "struct Params",
|
|
3968
|
+
components: [
|
|
3969
|
+
{
|
|
3970
|
+
name: "host",
|
|
3971
|
+
type: "address",
|
|
3972
|
+
internalType: "address"
|
|
3973
|
+
},
|
|
3974
|
+
{
|
|
3975
|
+
name: "dispatcher",
|
|
3976
|
+
type: "address",
|
|
3977
|
+
internalType: "address"
|
|
3978
|
+
},
|
|
3979
|
+
{
|
|
3980
|
+
name: "solverSelection",
|
|
3981
|
+
type: "bool",
|
|
3982
|
+
internalType: "bool"
|
|
3983
|
+
},
|
|
3984
|
+
{
|
|
3985
|
+
name: "surplusShareBps",
|
|
3986
|
+
type: "uint256",
|
|
3987
|
+
internalType: "uint256"
|
|
3988
|
+
},
|
|
3989
|
+
{
|
|
3990
|
+
name: "protocolFeeBps",
|
|
3991
|
+
type: "uint256",
|
|
3992
|
+
internalType: "uint256"
|
|
3993
|
+
},
|
|
3994
|
+
{
|
|
3995
|
+
name: "priceOracle",
|
|
3996
|
+
type: "address",
|
|
3997
|
+
internalType: "address"
|
|
3998
|
+
}
|
|
3999
|
+
]
|
|
3908
4000
|
},
|
|
3909
4001
|
{
|
|
3910
|
-
name: "
|
|
3911
|
-
type: "
|
|
3912
|
-
internalType: "
|
|
4002
|
+
name: "peerChains",
|
|
4003
|
+
type: "bytes[]",
|
|
4004
|
+
internalType: "bytes[]"
|
|
3913
4005
|
},
|
|
3914
4006
|
{
|
|
3915
|
-
name: "
|
|
3916
|
-
type: "
|
|
3917
|
-
internalType: "
|
|
4007
|
+
name: "relayer",
|
|
4008
|
+
type: "address",
|
|
4009
|
+
internalType: "address"
|
|
3918
4010
|
},
|
|
3919
4011
|
{
|
|
3920
|
-
name: "
|
|
4012
|
+
name: "owner",
|
|
3921
4013
|
type: "address",
|
|
3922
4014
|
internalType: "address"
|
|
3923
4015
|
}
|
|
3924
4016
|
]
|
|
3925
|
-
},
|
|
3926
|
-
{
|
|
3927
|
-
name: "peerChains",
|
|
3928
|
-
type: "bytes[]",
|
|
3929
|
-
internalType: "bytes[]"
|
|
3930
|
-
},
|
|
3931
|
-
{
|
|
3932
|
-
name: "relayer",
|
|
3933
|
-
type: "address",
|
|
3934
|
-
internalType: "address"
|
|
3935
4017
|
}
|
|
3936
4018
|
],
|
|
3937
4019
|
outputs: [],
|
|
@@ -3956,12 +4038,25 @@ var ABI3 = [
|
|
|
3956
4038
|
],
|
|
3957
4039
|
stateMutability: "view"
|
|
3958
4040
|
},
|
|
4041
|
+
{
|
|
4042
|
+
type: "function",
|
|
4043
|
+
name: "intrinsicModule",
|
|
4044
|
+
inputs: [],
|
|
4045
|
+
outputs: [
|
|
4046
|
+
{
|
|
4047
|
+
name: "",
|
|
4048
|
+
type: "address",
|
|
4049
|
+
internalType: "address"
|
|
4050
|
+
}
|
|
4051
|
+
],
|
|
4052
|
+
stateMutability: "view"
|
|
4053
|
+
},
|
|
3959
4054
|
{
|
|
3960
4055
|
type: "function",
|
|
3961
4056
|
name: "migrate",
|
|
3962
4057
|
inputs: [
|
|
3963
4058
|
{
|
|
3964
|
-
name: "
|
|
4059
|
+
name: "owner_",
|
|
3965
4060
|
type: "address",
|
|
3966
4061
|
internalType: "address"
|
|
3967
4062
|
}
|
|
@@ -4036,7 +4131,7 @@ var ABI3 = [
|
|
|
4036
4131
|
name: "onGetResponse",
|
|
4037
4132
|
inputs: [
|
|
4038
4133
|
{
|
|
4039
|
-
name: "
|
|
4134
|
+
name: "",
|
|
4040
4135
|
type: "tuple",
|
|
4041
4136
|
internalType: "struct IncomingGetResponse",
|
|
4042
4137
|
components: [
|
|
@@ -4251,6 +4346,19 @@ var ABI3 = [
|
|
|
4251
4346
|
outputs: [],
|
|
4252
4347
|
stateMutability: "nonpayable"
|
|
4253
4348
|
},
|
|
4349
|
+
{
|
|
4350
|
+
type: "function",
|
|
4351
|
+
name: "owner",
|
|
4352
|
+
inputs: [],
|
|
4353
|
+
outputs: [
|
|
4354
|
+
{
|
|
4355
|
+
name: "",
|
|
4356
|
+
type: "address",
|
|
4357
|
+
internalType: "address"
|
|
4358
|
+
}
|
|
4359
|
+
],
|
|
4360
|
+
stateMutability: "view"
|
|
4361
|
+
},
|
|
4254
4362
|
{
|
|
4255
4363
|
type: "function",
|
|
4256
4364
|
name: "params",
|
|
@@ -4296,6 +4404,39 @@ var ABI3 = [
|
|
|
4296
4404
|
],
|
|
4297
4405
|
stateMutability: "view"
|
|
4298
4406
|
},
|
|
4407
|
+
{
|
|
4408
|
+
type: "function",
|
|
4409
|
+
name: "pause",
|
|
4410
|
+
inputs: [],
|
|
4411
|
+
outputs: [],
|
|
4412
|
+
stateMutability: "nonpayable"
|
|
4413
|
+
},
|
|
4414
|
+
{
|
|
4415
|
+
type: "function",
|
|
4416
|
+
name: "paused",
|
|
4417
|
+
inputs: [],
|
|
4418
|
+
outputs: [
|
|
4419
|
+
{
|
|
4420
|
+
name: "",
|
|
4421
|
+
type: "bool",
|
|
4422
|
+
internalType: "bool"
|
|
4423
|
+
}
|
|
4424
|
+
],
|
|
4425
|
+
stateMutability: "view"
|
|
4426
|
+
},
|
|
4427
|
+
{
|
|
4428
|
+
type: "function",
|
|
4429
|
+
name: "pendingOwner",
|
|
4430
|
+
inputs: [],
|
|
4431
|
+
outputs: [
|
|
4432
|
+
{
|
|
4433
|
+
name: "",
|
|
4434
|
+
type: "address",
|
|
4435
|
+
internalType: "address"
|
|
4436
|
+
}
|
|
4437
|
+
],
|
|
4438
|
+
stateMutability: "view"
|
|
4439
|
+
},
|
|
4299
4440
|
{
|
|
4300
4441
|
type: "function",
|
|
4301
4442
|
name: "placeOrder",
|
|
@@ -4551,6 +4692,13 @@ var ABI3 = [
|
|
|
4551
4692
|
],
|
|
4552
4693
|
stateMutability: "view"
|
|
4553
4694
|
},
|
|
4695
|
+
{
|
|
4696
|
+
type: "function",
|
|
4697
|
+
name: "renounceOwnership",
|
|
4698
|
+
inputs: [],
|
|
4699
|
+
outputs: [],
|
|
4700
|
+
stateMutability: "nonpayable"
|
|
4701
|
+
},
|
|
4554
4702
|
{
|
|
4555
4703
|
type: "function",
|
|
4556
4704
|
name: "select",
|
|
@@ -4589,10 +4737,10 @@ var ABI3 = [
|
|
|
4589
4737
|
},
|
|
4590
4738
|
{
|
|
4591
4739
|
type: "function",
|
|
4592
|
-
name: "
|
|
4740
|
+
name: "transferOwnership",
|
|
4593
4741
|
inputs: [
|
|
4594
4742
|
{
|
|
4595
|
-
name: "
|
|
4743
|
+
name: "newOwner",
|
|
4596
4744
|
type: "address",
|
|
4597
4745
|
internalType: "address"
|
|
4598
4746
|
}
|
|
@@ -4602,19 +4750,8 @@ var ABI3 = [
|
|
|
4602
4750
|
},
|
|
4603
4751
|
{
|
|
4604
4752
|
type: "function",
|
|
4605
|
-
name: "
|
|
4606
|
-
inputs: [
|
|
4607
|
-
{
|
|
4608
|
-
name: "newImplementation",
|
|
4609
|
-
type: "address",
|
|
4610
|
-
internalType: "address"
|
|
4611
|
-
},
|
|
4612
|
-
{
|
|
4613
|
-
name: "data",
|
|
4614
|
-
type: "bytes",
|
|
4615
|
-
internalType: "bytes"
|
|
4616
|
-
}
|
|
4617
|
-
],
|
|
4753
|
+
name: "unpause",
|
|
4754
|
+
inputs: [],
|
|
4618
4755
|
outputs: [],
|
|
4619
4756
|
stateMutability: "nonpayable"
|
|
4620
4757
|
},
|
|
@@ -4760,6 +4897,12 @@ var ABI3 = [
|
|
|
4760
4897
|
indexed: true,
|
|
4761
4898
|
internalType: "bytes32"
|
|
4762
4899
|
},
|
|
4900
|
+
{
|
|
4901
|
+
name: "solver",
|
|
4902
|
+
type: "address",
|
|
4903
|
+
indexed: false,
|
|
4904
|
+
internalType: "address"
|
|
4905
|
+
},
|
|
4763
4906
|
{
|
|
4764
4907
|
name: "tokens",
|
|
4765
4908
|
type: "tuple[]",
|
|
@@ -4997,39 +5140,77 @@ var ABI3 = [
|
|
|
4997
5140
|
},
|
|
4998
5141
|
{
|
|
4999
5142
|
type: "event",
|
|
5000
|
-
name: "
|
|
5143
|
+
name: "OwnershipTransferStarted",
|
|
5001
5144
|
inputs: [
|
|
5002
5145
|
{
|
|
5003
|
-
name: "
|
|
5004
|
-
type: "
|
|
5005
|
-
indexed:
|
|
5006
|
-
internalType: "
|
|
5007
|
-
|
|
5008
|
-
|
|
5009
|
-
|
|
5010
|
-
|
|
5011
|
-
|
|
5012
|
-
|
|
5013
|
-
|
|
5014
|
-
|
|
5015
|
-
|
|
5016
|
-
|
|
5017
|
-
|
|
5018
|
-
|
|
5019
|
-
|
|
5020
|
-
|
|
5021
|
-
|
|
5022
|
-
|
|
5023
|
-
|
|
5024
|
-
|
|
5025
|
-
|
|
5026
|
-
|
|
5027
|
-
|
|
5028
|
-
|
|
5029
|
-
|
|
5030
|
-
|
|
5031
|
-
|
|
5032
|
-
|
|
5146
|
+
name: "previousOwner",
|
|
5147
|
+
type: "address",
|
|
5148
|
+
indexed: true,
|
|
5149
|
+
internalType: "address"
|
|
5150
|
+
},
|
|
5151
|
+
{
|
|
5152
|
+
name: "newOwner",
|
|
5153
|
+
type: "address",
|
|
5154
|
+
indexed: true,
|
|
5155
|
+
internalType: "address"
|
|
5156
|
+
}
|
|
5157
|
+
],
|
|
5158
|
+
anonymous: false
|
|
5159
|
+
},
|
|
5160
|
+
{
|
|
5161
|
+
type: "event",
|
|
5162
|
+
name: "OwnershipTransferred",
|
|
5163
|
+
inputs: [
|
|
5164
|
+
{
|
|
5165
|
+
name: "previousOwner",
|
|
5166
|
+
type: "address",
|
|
5167
|
+
indexed: true,
|
|
5168
|
+
internalType: "address"
|
|
5169
|
+
},
|
|
5170
|
+
{
|
|
5171
|
+
name: "newOwner",
|
|
5172
|
+
type: "address",
|
|
5173
|
+
indexed: true,
|
|
5174
|
+
internalType: "address"
|
|
5175
|
+
}
|
|
5176
|
+
],
|
|
5177
|
+
anonymous: false
|
|
5178
|
+
},
|
|
5179
|
+
{
|
|
5180
|
+
type: "event",
|
|
5181
|
+
name: "ParamsUpdated",
|
|
5182
|
+
inputs: [
|
|
5183
|
+
{
|
|
5184
|
+
name: "previous",
|
|
5185
|
+
type: "tuple",
|
|
5186
|
+
indexed: false,
|
|
5187
|
+
internalType: "struct Params",
|
|
5188
|
+
components: [
|
|
5189
|
+
{
|
|
5190
|
+
name: "host",
|
|
5191
|
+
type: "address",
|
|
5192
|
+
internalType: "address"
|
|
5193
|
+
},
|
|
5194
|
+
{
|
|
5195
|
+
name: "dispatcher",
|
|
5196
|
+
type: "address",
|
|
5197
|
+
internalType: "address"
|
|
5198
|
+
},
|
|
5199
|
+
{
|
|
5200
|
+
name: "solverSelection",
|
|
5201
|
+
type: "bool",
|
|
5202
|
+
internalType: "bool"
|
|
5203
|
+
},
|
|
5204
|
+
{
|
|
5205
|
+
name: "surplusShareBps",
|
|
5206
|
+
type: "uint256",
|
|
5207
|
+
internalType: "uint256"
|
|
5208
|
+
},
|
|
5209
|
+
{
|
|
5210
|
+
name: "protocolFeeBps",
|
|
5211
|
+
type: "uint256",
|
|
5212
|
+
internalType: "uint256"
|
|
5213
|
+
},
|
|
5033
5214
|
{
|
|
5034
5215
|
name: "priceOracle",
|
|
5035
5216
|
type: "address",
|
|
@@ -5135,46 +5316,73 @@ var ABI3 = [
|
|
|
5135
5316
|
},
|
|
5136
5317
|
{
|
|
5137
5318
|
type: "event",
|
|
5138
|
-
name: "
|
|
5319
|
+
name: "Paused",
|
|
5139
5320
|
inputs: [
|
|
5140
5321
|
{
|
|
5141
|
-
name: "
|
|
5322
|
+
name: "account",
|
|
5142
5323
|
type: "address",
|
|
5143
5324
|
indexed: false,
|
|
5144
5325
|
internalType: "address"
|
|
5326
|
+
}
|
|
5327
|
+
],
|
|
5328
|
+
anonymous: false
|
|
5329
|
+
},
|
|
5330
|
+
{
|
|
5331
|
+
type: "event",
|
|
5332
|
+
name: "ProtocolFeeRefunded",
|
|
5333
|
+
inputs: [
|
|
5334
|
+
{
|
|
5335
|
+
name: "commitment",
|
|
5336
|
+
type: "bytes32",
|
|
5337
|
+
indexed: true,
|
|
5338
|
+
internalType: "bytes32"
|
|
5145
5339
|
},
|
|
5146
5340
|
{
|
|
5147
|
-
name: "
|
|
5341
|
+
name: "token",
|
|
5148
5342
|
type: "address",
|
|
5149
|
-
indexed:
|
|
5343
|
+
indexed: true,
|
|
5150
5344
|
internalType: "address"
|
|
5345
|
+
},
|
|
5346
|
+
{
|
|
5347
|
+
name: "amount",
|
|
5348
|
+
type: "uint256",
|
|
5349
|
+
indexed: false,
|
|
5350
|
+
internalType: "uint256"
|
|
5151
5351
|
}
|
|
5152
5352
|
],
|
|
5153
5353
|
anonymous: false
|
|
5154
5354
|
},
|
|
5155
5355
|
{
|
|
5156
5356
|
type: "event",
|
|
5157
|
-
name: "
|
|
5357
|
+
name: "RelayerUpdated",
|
|
5158
5358
|
inputs: [
|
|
5159
5359
|
{
|
|
5160
|
-
name: "
|
|
5360
|
+
name: "previous",
|
|
5361
|
+
type: "address",
|
|
5362
|
+
indexed: false,
|
|
5363
|
+
internalType: "address"
|
|
5364
|
+
},
|
|
5365
|
+
{
|
|
5366
|
+
name: "current",
|
|
5161
5367
|
type: "address",
|
|
5162
|
-
indexed:
|
|
5368
|
+
indexed: false,
|
|
5163
5369
|
internalType: "address"
|
|
5164
5370
|
}
|
|
5165
5371
|
],
|
|
5166
5372
|
anonymous: false
|
|
5167
5373
|
},
|
|
5168
5374
|
{
|
|
5169
|
-
type: "
|
|
5170
|
-
name: "
|
|
5375
|
+
type: "event",
|
|
5376
|
+
name: "Unpaused",
|
|
5171
5377
|
inputs: [
|
|
5172
5378
|
{
|
|
5173
|
-
name: "
|
|
5379
|
+
name: "account",
|
|
5174
5380
|
type: "address",
|
|
5381
|
+
indexed: false,
|
|
5175
5382
|
internalType: "address"
|
|
5176
5383
|
}
|
|
5177
|
-
]
|
|
5384
|
+
],
|
|
5385
|
+
anonymous: false
|
|
5178
5386
|
},
|
|
5179
5387
|
{
|
|
5180
5388
|
type: "error",
|
|
@@ -5210,28 +5418,17 @@ var ABI3 = [
|
|
|
5210
5418
|
},
|
|
5211
5419
|
{
|
|
5212
5420
|
type: "error",
|
|
5213
|
-
name: "
|
|
5214
|
-
inputs: [
|
|
5215
|
-
{
|
|
5216
|
-
name: "implementation",
|
|
5217
|
-
type: "address",
|
|
5218
|
-
internalType: "address"
|
|
5219
|
-
}
|
|
5220
|
-
]
|
|
5221
|
-
},
|
|
5222
|
-
{
|
|
5223
|
-
type: "error",
|
|
5224
|
-
name: "ERC1967NonPayable",
|
|
5421
|
+
name: "EnforcedPause",
|
|
5225
5422
|
inputs: []
|
|
5226
5423
|
},
|
|
5227
5424
|
{
|
|
5228
5425
|
type: "error",
|
|
5229
|
-
name: "
|
|
5426
|
+
name: "ExpectedPause",
|
|
5230
5427
|
inputs: []
|
|
5231
5428
|
},
|
|
5232
5429
|
{
|
|
5233
5430
|
type: "error",
|
|
5234
|
-
name: "
|
|
5431
|
+
name: "Expired",
|
|
5235
5432
|
inputs: []
|
|
5236
5433
|
},
|
|
5237
5434
|
{
|
|
@@ -5274,11 +5471,43 @@ var ABI3 = [
|
|
|
5274
5471
|
name: "NotInitializing",
|
|
5275
5472
|
inputs: []
|
|
5276
5473
|
},
|
|
5474
|
+
{
|
|
5475
|
+
type: "error",
|
|
5476
|
+
name: "OwnableInvalidOwner",
|
|
5477
|
+
inputs: [
|
|
5478
|
+
{
|
|
5479
|
+
name: "owner",
|
|
5480
|
+
type: "address",
|
|
5481
|
+
internalType: "address"
|
|
5482
|
+
}
|
|
5483
|
+
]
|
|
5484
|
+
},
|
|
5485
|
+
{
|
|
5486
|
+
type: "error",
|
|
5487
|
+
name: "OwnableUnauthorizedAccount",
|
|
5488
|
+
inputs: [
|
|
5489
|
+
{
|
|
5490
|
+
name: "account",
|
|
5491
|
+
type: "address",
|
|
5492
|
+
internalType: "address"
|
|
5493
|
+
}
|
|
5494
|
+
]
|
|
5495
|
+
},
|
|
5277
5496
|
{
|
|
5278
5497
|
type: "error",
|
|
5279
5498
|
name: "PartialFillNotAllowed",
|
|
5280
5499
|
inputs: []
|
|
5281
5500
|
},
|
|
5501
|
+
{
|
|
5502
|
+
type: "error",
|
|
5503
|
+
name: "RateBelowOrder",
|
|
5504
|
+
inputs: []
|
|
5505
|
+
},
|
|
5506
|
+
{
|
|
5507
|
+
type: "error",
|
|
5508
|
+
name: "RateFillTooSmall",
|
|
5509
|
+
inputs: []
|
|
5510
|
+
},
|
|
5282
5511
|
{
|
|
5283
5512
|
type: "error",
|
|
5284
5513
|
name: "ReentrancyGuardReentrantCall",
|
|
@@ -5506,9 +5735,6 @@ var ChainConfigService = class {
|
|
|
5506
5735
|
getUniswapV4StateViewAddress(chain) {
|
|
5507
5736
|
return this.getConfig(chain)?.addresses.UniswapV4StateView ?? "0x";
|
|
5508
5737
|
}
|
|
5509
|
-
getUniswapV4PoolConfigs(chain) {
|
|
5510
|
-
return this.getConfig(chain)?.uniswapV4Pools ?? [];
|
|
5511
|
-
}
|
|
5512
5738
|
getPermit2Address(chain) {
|
|
5513
5739
|
return this.getConfig(chain)?.addresses.Permit2 ?? "0x";
|
|
5514
5740
|
}
|
|
@@ -8245,9 +8471,7 @@ Failed HTTP Request: ${JSON.stringify(
|
|
|
8245
8471
|
};
|
|
8246
8472
|
|
|
8247
8473
|
// src/chains/intentsCoprocessor.ts
|
|
8248
|
-
var SYSTEM_EVENTS_KEY = u8aToHex(u8aConcat(xxhashAsU8a("System", 128), xxhashAsU8a("Events", 128)));
|
|
8249
8474
|
var OFFCHAIN_BID_PREFIX = new TextEncoder().encode("intents::bid::");
|
|
8250
|
-
var OFFCHAIN_PHANTOM_PREFIX = new TextEncoder().encode("intents::phantom::order::");
|
|
8251
8475
|
var HYPERBRIDGE_TYPES_BUNDLE = {
|
|
8252
8476
|
spec: {
|
|
8253
8477
|
nexus: { hasher: keccakAsU8a },
|
|
@@ -8257,11 +8481,7 @@ var HYPERBRIDGE_TYPES_BUNDLE = {
|
|
|
8257
8481
|
var BASE_TIP = 1000000000n;
|
|
8258
8482
|
var HTTP_CONNECT_TIMEOUT_MS = 2e4;
|
|
8259
8483
|
var INCLUSION_TIMEOUT_MS = 2e4;
|
|
8260
|
-
var PHANTOM_POLL_INTERVAL_MS = 15e3;
|
|
8261
|
-
var GARGANTUA_PHANTOM_POLL_INTERVAL_MS = 6e3;
|
|
8262
8484
|
var DEFAULT_RPC_MAX_RPS = 8;
|
|
8263
|
-
var DEFAULT_MAX_BLOCKS_PER_POLL = 10;
|
|
8264
|
-
var MAX_RATE_LIMIT_BACKOFF_TICKS = 8;
|
|
8265
8485
|
var rpcLimiters = /* @__PURE__ */ new Map();
|
|
8266
8486
|
function limiterFor(httpUrl) {
|
|
8267
8487
|
const key = new URL(httpUrl).origin;
|
|
@@ -8277,45 +8497,6 @@ function configuredRpcMaxRps() {
|
|
|
8277
8497
|
const parsed = raw === void 0 ? Number.NaN : Number(raw);
|
|
8278
8498
|
return Number.isFinite(parsed) && parsed > 0 ? parsed : DEFAULT_RPC_MAX_RPS;
|
|
8279
8499
|
}
|
|
8280
|
-
function isRateLimited(err) {
|
|
8281
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
8282
|
-
return message.includes("[429]") || /too many requests/i.test(message);
|
|
8283
|
-
}
|
|
8284
|
-
function isMethodUnavailable(err) {
|
|
8285
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
8286
|
-
const code = err?.code;
|
|
8287
|
-
return code === -32601 || /method not found|unsafe to be called externally/i.test(message);
|
|
8288
|
-
}
|
|
8289
|
-
var EventDecodeError = class extends Error {
|
|
8290
|
-
};
|
|
8291
|
-
function phantomOrdersFrom(records) {
|
|
8292
|
-
if (records == null || typeof records[Symbol.iterator] !== "function") {
|
|
8293
|
-
throw new EventDecodeError(`Expected a decoded event vector, got ${typeof records}`);
|
|
8294
|
-
}
|
|
8295
|
-
const orders = [];
|
|
8296
|
-
for (const record of records) {
|
|
8297
|
-
if (typeof record !== "object" || record === null || !("event" in record)) {
|
|
8298
|
-
throw new EventDecodeError(
|
|
8299
|
-
"system.events did not decode to event records \u2014 the storage entry's metadata was probably not carried through, leaving the value as raw bytes"
|
|
8300
|
-
);
|
|
8301
|
-
}
|
|
8302
|
-
const { event } = record;
|
|
8303
|
-
if (event.section !== "intentsCoprocessor" || event.method !== "PhantomOrderRegistered") continue;
|
|
8304
|
-
const [commitment, chain, createdAt, legs] = event.data;
|
|
8305
|
-
orders.push({
|
|
8306
|
-
commitment: commitment.toHex(),
|
|
8307
|
-
chain: new TextDecoder().decode(hexToU8a(chain.toHex())),
|
|
8308
|
-
createdAt: createdAt.toNumber(),
|
|
8309
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
8310
|
-
legs: legs.map((leg) => ({
|
|
8311
|
-
tokenA: leg.tokenA.toHex(),
|
|
8312
|
-
tokenB: leg.tokenB.toHex(),
|
|
8313
|
-
standardAmount: BigInt(leg.standardAmount.toString())
|
|
8314
|
-
}))
|
|
8315
|
-
});
|
|
8316
|
-
}
|
|
8317
|
-
return orders;
|
|
8318
|
-
}
|
|
8319
8500
|
function rejectAfter(ms, message) {
|
|
8320
8501
|
return new Promise((_resolve, reject) => {
|
|
8321
8502
|
const timer = setTimeout(() => reject(new Error(message)), ms);
|
|
@@ -8387,19 +8568,16 @@ var IntentsCoprocessor = class _IntentsCoprocessor {
|
|
|
8387
8568
|
ownsConnection;
|
|
8388
8569
|
/** Cached result of whether the node exposes intents_* RPC methods */
|
|
8389
8570
|
hasIntentsRpc = null;
|
|
8390
|
-
/** The pallet's phantom timings, read once. Cleared on failure so the read retries. */
|
|
8391
|
-
phantomTimingsRead = null;
|
|
8392
8571
|
/** The HTTP-backed api, connected on first use. Cleared after a failed attempt so it retries. */
|
|
8393
8572
|
httpApi = null;
|
|
8394
|
-
/** Last runtime version read from the node, for {@link confirmedRuntimeVersion} to compare against. */
|
|
8395
|
-
lastRuntimeVersion;
|
|
8396
|
-
/** Set once the node refuses `state_queryStorage`, so the poll stops asking for it. */
|
|
8397
|
-
rangeQueryUnavailable = false;
|
|
8398
8573
|
// Serialises every extrinsic submission on this instance's substrate account. All submit/retract
|
|
8399
|
-
// methods funnel through signAndSendExtrinsic
|
|
8400
|
-
//
|
|
8401
|
-
//
|
|
8574
|
+
// methods funnel through signAndSendExtrinsic; fired in parallel (bids for orders on different
|
|
8575
|
+
// chains, or several bids on one order) they would grab the same nonce and all but one would
|
|
8576
|
+
// fail. Concurrency 1 sequences them, and {@link nextNonce} keeps consecutive submissions off
|
|
8577
|
+
// each other's nonce even while the first is still in the pool.
|
|
8402
8578
|
submissionQueue = new PQueue({ concurrency: 1 });
|
|
8579
|
+
/** The highest nonce this instance has put into the pool, so the next submission clears it. */
|
|
8580
|
+
lastPooledNonce;
|
|
8403
8581
|
/**
|
|
8404
8582
|
* Creates and connects an IntentsCoprocessor to a Hyperbridge node.
|
|
8405
8583
|
* This creates and manages its own API connection.
|
|
@@ -8461,10 +8639,10 @@ var IntentsCoprocessor = class _IntentsCoprocessor {
|
|
|
8461
8639
|
* The HTTP api is always created here, so it is always ours to close.
|
|
8462
8640
|
*/
|
|
8463
8641
|
async disconnect() {
|
|
8464
|
-
const
|
|
8642
|
+
const http3 = this.httpApi;
|
|
8465
8643
|
this.httpApi = null;
|
|
8466
|
-
if (
|
|
8467
|
-
await
|
|
8644
|
+
if (http3) {
|
|
8645
|
+
await http3.then((api) => api.disconnect()).catch(() => {
|
|
8468
8646
|
});
|
|
8469
8647
|
}
|
|
8470
8648
|
if (this.ownsConnection) {
|
|
@@ -8478,9 +8656,8 @@ var IntentsCoprocessor = class _IntentsCoprocessor {
|
|
|
8478
8656
|
*
|
|
8479
8657
|
* The connection attempt is bounded on both sides. `isReadyOrError` rejects on a failed
|
|
8480
8658
|
* handshake, where plain `isReady` would simply never resolve, and the timeout covers an
|
|
8481
|
-
* endpoint that accepts the request and then goes quiet
|
|
8482
|
-
*
|
|
8483
|
-
* failed attempt is not cached, so the next call tries again.
|
|
8659
|
+
* endpoint that accepts the request and then goes quiet, so a caller awaiting it never hangs
|
|
8660
|
+
* silently. A failed attempt is not cached, so the next call tries again.
|
|
8484
8661
|
*/
|
|
8485
8662
|
async http() {
|
|
8486
8663
|
if (!this.httpApi) {
|
|
@@ -8489,11 +8666,9 @@ var IntentsCoprocessor = class _IntentsCoprocessor {
|
|
|
8489
8666
|
// Response cache off (third argument, capacity 0). polkadot-js caches every request that
|
|
8490
8667
|
// names a block hash — `chain_getHeader(hash)`, `state_getRuntimeVersion(hash)`, storage
|
|
8491
8668
|
// reads at a hash — by storing the request promise itself, a rejected one included, for a
|
|
8492
|
-
// 30s TTL that every hit refreshes.
|
|
8493
|
-
//
|
|
8494
|
-
//
|
|
8495
|
-
// saw a second request. The cache bought nothing here anyway: the poll reads each block
|
|
8496
|
-
// once, and `api.at(hash)` reuses registries at the api layer regardless.
|
|
8669
|
+
// 30s TTL that every hit refreshes. A caller retrying a failed read with identical
|
|
8670
|
+
// parameters would get the same rejection replayed from memory for as long as it kept
|
|
8671
|
+
// retrying inside the TTL, and the node would never see a second request.
|
|
8497
8672
|
// Concurrent calls are coalesced into one JSON-RPC batch request, and every request
|
|
8498
8673
|
// to this endpoint is paced by a bucket shared with any other coprocessor in this
|
|
8499
8674
|
// process pointed at the same host — the limit is the server's, and it counts
|
|
@@ -8568,7 +8743,12 @@ var IntentsCoprocessor = class _IntentsCoprocessor {
|
|
|
8568
8743
|
return { success: false, error: err instanceof Error ? err.message : String(err) };
|
|
8569
8744
|
}
|
|
8570
8745
|
}
|
|
8571
|
-
return await this.sendExtrinsicWithRetries(
|
|
8746
|
+
return await this.sendExtrinsicWithRetries(
|
|
8747
|
+
build(this.api),
|
|
8748
|
+
maxRetries,
|
|
8749
|
+
timeoutMs,
|
|
8750
|
+
await this.nextNonce(this.api)
|
|
8751
|
+
);
|
|
8572
8752
|
});
|
|
8573
8753
|
return result ?? { success: false, error: "Submission queue returned no result" };
|
|
8574
8754
|
}
|
|
@@ -8587,7 +8767,10 @@ var IntentsCoprocessor = class _IntentsCoprocessor {
|
|
|
8587
8767
|
*/
|
|
8588
8768
|
async sendViaHttp(api, build) {
|
|
8589
8769
|
try {
|
|
8590
|
-
const
|
|
8770
|
+
const nonce = await this.nextNonce(api);
|
|
8771
|
+
const options = nonce === void 0 ? { tip: BASE_TIP } : { tip: BASE_TIP, nonce };
|
|
8772
|
+
const hash = await build(api).signAndSend(this.getKeyPair(), options);
|
|
8773
|
+
if (nonce !== void 0) this.lastPooledNonce = nonce;
|
|
8591
8774
|
return { success: false, pending: true, extrinsicHash: hash.toHex() };
|
|
8592
8775
|
} catch (err) {
|
|
8593
8776
|
return this.classifySubmissionError(err instanceof Error ? err : new Error(String(err)));
|
|
@@ -8600,7 +8783,7 @@ var IntentsCoprocessor = class _IntentsCoprocessor {
|
|
|
8600
8783
|
* Two kinds of failure are retried, and the difference is the nonce.
|
|
8601
8784
|
*
|
|
8602
8785
|
* An attempt that verifiably went nowhere (rejected before the pool, dropped, invalid) leaves
|
|
8603
|
-
* the account nonce free, so the next attempt simply re-signs with the
|
|
8786
|
+
* the account nonce free, so the next attempt simply re-signs with the pool-aware nonce.
|
|
8604
8787
|
*
|
|
8605
8788
|
* An attempt that reached the pool and was still there when the watch timed out (`stalled`) is
|
|
8606
8789
|
* retried as a *replacement*: the same nonce it was signed with, and double the tip. Substrate's
|
|
@@ -8619,16 +8802,19 @@ var IntentsCoprocessor = class _IntentsCoprocessor {
|
|
|
8619
8802
|
* copy is in flight and its outcome is unknown here, so the `pending` result goes back to the
|
|
8620
8803
|
* caller to confirm later.
|
|
8621
8804
|
*/
|
|
8622
|
-
async sendExtrinsicWithRetries(extrinsic, maxRetries, timeoutMs) {
|
|
8805
|
+
async sendExtrinsicWithRetries(extrinsic, maxRetries, timeoutMs, initialNonce) {
|
|
8623
8806
|
const keyPair = this.getKeyPair();
|
|
8624
8807
|
let attempt = 0;
|
|
8625
|
-
let nonce;
|
|
8808
|
+
let nonce = initialNonce;
|
|
8626
8809
|
let stalled;
|
|
8627
8810
|
while (attempt < maxRetries) {
|
|
8628
8811
|
const currentTip = BASE_TIP * BigInt(2 ** attempt);
|
|
8629
8812
|
attempt++;
|
|
8630
8813
|
try {
|
|
8631
8814
|
const result = await this.sendWithTimeout(extrinsic, keyPair, currentTip, timeoutMs, nonce);
|
|
8815
|
+
if (nonce !== void 0 && (result.success || result.pending || result.stalled)) {
|
|
8816
|
+
this.lastPooledNonce = Math.max(nonce, this.lastPooledNonce ?? nonce);
|
|
8817
|
+
}
|
|
8632
8818
|
if (result.success || result.error?.includes("Dispatch error")) {
|
|
8633
8819
|
return result;
|
|
8634
8820
|
}
|
|
@@ -8688,6 +8874,35 @@ var IntentsCoprocessor = class _IntentsCoprocessor {
|
|
|
8688
8874
|
* replacement rather than a second extrinsic queued behind the first. Left undefined on the
|
|
8689
8875
|
* first attempt, where the api's auto-nonce is correct.
|
|
8690
8876
|
*/
|
|
8877
|
+
/**
|
|
8878
|
+
* The nonce the next submission signs with, or undefined when the node cannot be asked.
|
|
8879
|
+
*
|
|
8880
|
+
* Submissions are serialised, but a watch gives up while its extrinsic is still in the pool
|
|
8881
|
+
* (`stalled`, reported as `pending`), and a pooled extrinsic does not advance the account's
|
|
8882
|
+
* on-chain nonce. An extrinsic signed against on-chain state would then take the nonce of the
|
|
8883
|
+
* one ahead of it and bounce off it (1013/1014) instead of queueing behind it.
|
|
8884
|
+
*
|
|
8885
|
+
* `system_accountNextIndex` is the only pool-aware source here. `signAndSend`'s own `nonce: -1`
|
|
8886
|
+
* is not: on a runtime carrying `AccountNonceApi`, which Hyperbridge does, polkadot-js reads the
|
|
8887
|
+
* nonce through that runtime call and never sees the pool.
|
|
8888
|
+
*
|
|
8889
|
+
* The RPC covers the ready queue, so anything of this instance's that has left it — retried,
|
|
8890
|
+
* queued as future, or simply not counted yet — is covered by `lastPooledNonce` instead, which
|
|
8891
|
+
* is the highest nonce this instance has put into the pool. The two are combined rather than
|
|
8892
|
+
* trusted separately, so a burst never reuses a nonce and a restart still picks up the chain's.
|
|
8893
|
+
*/
|
|
8894
|
+
async nextNonce(api) {
|
|
8895
|
+
try {
|
|
8896
|
+
const accountNextIndex = api.rpc?.system?.accountNextIndex;
|
|
8897
|
+
if (!accountNextIndex) return void 0;
|
|
8898
|
+
const next = await accountNextIndex(this.getKeyPair().address);
|
|
8899
|
+
const fromPool = Number(next.toString());
|
|
8900
|
+
if (!Number.isFinite(fromPool)) return void 0;
|
|
8901
|
+
return this.lastPooledNonce === void 0 ? fromPool : Math.max(fromPool, this.lastPooledNonce + 1);
|
|
8902
|
+
} catch {
|
|
8903
|
+
return void 0;
|
|
8904
|
+
}
|
|
8905
|
+
}
|
|
8691
8906
|
async sendWithTimeout(extrinsic, keyPair, tip, timeoutMs, nonce) {
|
|
8692
8907
|
return new Promise((resolve) => {
|
|
8693
8908
|
let resolved = false;
|
|
@@ -8730,25 +8945,10 @@ var IntentsCoprocessor = class _IntentsCoprocessor {
|
|
|
8730
8945
|
} else if (result.status.isInBlock || result.status.isFinalized) {
|
|
8731
8946
|
resolved = true;
|
|
8732
8947
|
clearTimeout(timeoutId);
|
|
8733
|
-
const interrupted = result.events.find(
|
|
8734
|
-
({ event }) => event.section === "utility" && event.method === "BatchInterrupted"
|
|
8735
|
-
);
|
|
8736
|
-
if (interrupted) {
|
|
8737
|
-
const [indexCodec, dispatchError] = interrupted.event.data;
|
|
8738
|
-
if (Number(indexCodec.toString()) === 0) {
|
|
8739
|
-
resolve({
|
|
8740
|
-
success: false,
|
|
8741
|
-
error: `Dispatch error: ${this.describeDispatchError(dispatchError)}`
|
|
8742
|
-
});
|
|
8743
|
-
return;
|
|
8744
|
-
}
|
|
8745
|
-
}
|
|
8746
8948
|
resolve({
|
|
8747
8949
|
success: true,
|
|
8748
8950
|
blockHash: (result.status.isInBlock ? result.status.asInBlock : result.status.asFinalized).toHex(),
|
|
8749
|
-
extrinsicHash: extrinsic.hash.toHex()
|
|
8750
|
-
// Carried so a batch caller can attribute each item's outcome.
|
|
8751
|
-
events: result.events
|
|
8951
|
+
extrinsicHash: extrinsic.hash.toHex()
|
|
8752
8952
|
});
|
|
8753
8953
|
}
|
|
8754
8954
|
}).then((unsub) => {
|
|
@@ -8769,13 +8969,19 @@ var IntentsCoprocessor = class _IntentsCoprocessor {
|
|
|
8769
8969
|
/**
|
|
8770
8970
|
* Submits a bid to Hyperbridge's pallet-intents
|
|
8771
8971
|
*
|
|
8972
|
+
* A filler can hold several bids on one order, one per price it offers, and `bid` tells them
|
|
8973
|
+
* apart: submitting again under an identifier the filler already holds replaces that bid alone.
|
|
8974
|
+
* By convention it is `keccak256` of the UserOp's `callData`, which is also what gives each bid
|
|
8975
|
+
* its own nonce key on the `SolverAccount` (see `CryptoUtils.bidId`).
|
|
8976
|
+
*
|
|
8772
8977
|
* @param commitment - The order commitment hash (bytes32)
|
|
8773
8978
|
* @param userOp - The encoded PackedUserOperation as hex string
|
|
8979
|
+
* @param bid - Identifies this bid among the filler's bids on the order (bytes32)
|
|
8774
8980
|
* @returns BidSubmissionResult with success status and block/extrinsic hash
|
|
8775
8981
|
*/
|
|
8776
|
-
async submitBid(commitment, userOp) {
|
|
8982
|
+
async submitBid(commitment, userOp, bid) {
|
|
8777
8983
|
try {
|
|
8778
|
-
return await this.signAndSendExtrinsic((api) => api.tx.intentsCoprocessor.placeBid(commitment, userOp));
|
|
8984
|
+
return await this.signAndSendExtrinsic((api) => api.tx.intentsCoprocessor.placeBid(commitment, bid, userOp));
|
|
8779
8985
|
} catch (error) {
|
|
8780
8986
|
return {
|
|
8781
8987
|
success: false,
|
|
@@ -8789,46 +8995,12 @@ var IntentsCoprocessor = class _IntentsCoprocessor {
|
|
|
8789
8995
|
* Use this to remove unused quotes and claim back deposited BRIDGE tokens.
|
|
8790
8996
|
*
|
|
8791
8997
|
* @param commitment - The order commitment hash (bytes32)
|
|
8998
|
+
* @param bid - Which of the filler's bids on the order to retract (bytes32)
|
|
8792
8999
|
* @returns BidSubmissionResult with success status and block/extrinsic hash
|
|
8793
9000
|
*/
|
|
8794
|
-
async retractBid(commitment) {
|
|
8795
|
-
try {
|
|
8796
|
-
return await this.signAndSendExtrinsic((api) => api.tx.intentsCoprocessor.retractBid(commitment));
|
|
8797
|
-
} catch (error) {
|
|
8798
|
-
return {
|
|
8799
|
-
success: false,
|
|
8800
|
-
error: error instanceof Error ? error.message : "Unknown error"
|
|
8801
|
-
};
|
|
8802
|
-
}
|
|
8803
|
-
}
|
|
8804
|
-
/**
|
|
8805
|
-
* Places a new bid and retracts a previous one in a single transaction via utility.batch.
|
|
8806
|
-
*
|
|
8807
|
-
* The new bid is the primary operation, so `placeBid` MUST run first. `utility.batch` is
|
|
8808
|
-
* non-atomic: a failing call interrupts the batch (via a BatchInterrupted event) without
|
|
8809
|
-
* reverting the calls that already succeeded. Placing first guarantees the new bid lands even
|
|
8810
|
-
* when the retraction then fails — which it routinely does, because a previous commitment's bid
|
|
8811
|
-
* may already be gone (or was itself never placed), making `retractBid` return `BidNotFound`.
|
|
8812
|
-
*
|
|
8813
|
-
* Ordering retraction first (the previous behaviour) caused a self-sustaining cascade: a
|
|
8814
|
-
* `BidNotFound` on the leading retract skipped the trailing `placeBid`, so the current bid never
|
|
8815
|
-
* landed, so the *next* interval's retract of that never-placed commitment also failed, and so
|
|
8816
|
-
* on — silently, because the batch extrinsic itself reports success. The deposit reclaim is
|
|
8817
|
-
* best-effort; landing the bid is not.
|
|
8818
|
-
*
|
|
8819
|
-
* @param retractCommitment - The order commitment of the bid to retract (bytes32)
|
|
8820
|
-
* @param bidCommitment - The order commitment of the new bid (bytes32)
|
|
8821
|
-
* @param userOp - The encoded PackedUserOperation as hex string
|
|
8822
|
-
* @returns BidSubmissionResult with success status and block/extrinsic hash
|
|
8823
|
-
*/
|
|
8824
|
-
async submitBidWithRetraction(retractCommitment, bidCommitment, userOp) {
|
|
9001
|
+
async retractBid(commitment, bid) {
|
|
8825
9002
|
try {
|
|
8826
|
-
return await this.signAndSendExtrinsic(
|
|
8827
|
-
(api) => api.tx.utility.batch([
|
|
8828
|
-
api.tx.intentsCoprocessor.placeBid(bidCommitment, userOp),
|
|
8829
|
-
api.tx.intentsCoprocessor.retractBid(retractCommitment)
|
|
8830
|
-
])
|
|
8831
|
-
);
|
|
9003
|
+
return await this.signAndSendExtrinsic((api) => api.tx.intentsCoprocessor.retractBid(commitment, bid));
|
|
8832
9004
|
} catch (error) {
|
|
8833
9005
|
return {
|
|
8834
9006
|
success: false,
|
|
@@ -8836,89 +9008,6 @@ var IntentsCoprocessor = class _IntentsCoprocessor {
|
|
|
8836
9008
|
};
|
|
8837
9009
|
}
|
|
8838
9010
|
}
|
|
8839
|
-
/**
|
|
8840
|
-
* Places every phantom bid of one interval in a single extrinsic, retracting each chain's
|
|
8841
|
-
* previous bid alongside it.
|
|
8842
|
-
*
|
|
8843
|
-
* The pallet registers one phantom order per configured chain in the same block, so this is the
|
|
8844
|
-
* whole interval's set. Submitting them one at a time costs a block per chain: submissions are
|
|
8845
|
-
* serialised on the account nonce and each waits for inclusion, so the last chain's bid is many
|
|
8846
|
-
* blocks behind the first, against a bid window measured in tens of blocks. Batched, every bid
|
|
8847
|
-
* lands in the same block.
|
|
8848
|
-
*
|
|
8849
|
-
* Uses `utility.force_batch`, not `utility.batch`. `batch` stops at the first failing call, so
|
|
8850
|
-
* one rejected bid — a closed window, a duplicate, an insufficient deposit — would silently
|
|
8851
|
-
* drop every bid after it. `force_batch` runs them all and reports each outcome. It needs no
|
|
8852
|
-
* special origin: any signed account may call it, exactly like `batch`.
|
|
8853
|
-
*
|
|
8854
|
-
* @param bids - The bids to place; an empty list is a no-op
|
|
8855
|
-
* @returns Per-bid outcomes, in the order given
|
|
8856
|
-
*/
|
|
8857
|
-
async submitPhantomBids(bids) {
|
|
8858
|
-
if (bids.length === 0) return { bids: [] };
|
|
8859
|
-
const placeIndexByBid = [];
|
|
8860
|
-
let callCount = 0;
|
|
8861
|
-
for (const bid of bids) {
|
|
8862
|
-
placeIndexByBid.push(callCount);
|
|
8863
|
-
callCount += bid.retractCommitment ? 2 : 1;
|
|
8864
|
-
}
|
|
8865
|
-
const outcome = await this.signAndSendExtrinsic(
|
|
8866
|
-
(api) => api.tx.utility.forceBatch(
|
|
8867
|
-
bids.flatMap((bid) => {
|
|
8868
|
-
const calls = [api.tx.intentsCoprocessor.placeBid(bid.commitment, bid.userOp)];
|
|
8869
|
-
if (bid.retractCommitment) {
|
|
8870
|
-
calls.push(api.tx.intentsCoprocessor.retractBid(bid.retractCommitment));
|
|
8871
|
-
}
|
|
8872
|
-
return calls;
|
|
8873
|
-
})
|
|
8874
|
-
)
|
|
8875
|
-
);
|
|
8876
|
-
if (!outcome.success) {
|
|
8877
|
-
return {
|
|
8878
|
-
bids: bids.map((bid) => ({ commitment: bid.commitment, success: false, error: outcome.error })),
|
|
8879
|
-
pending: outcome.pending,
|
|
8880
|
-
extrinsicHash: outcome.extrinsicHash,
|
|
8881
|
-
error: outcome.error
|
|
8882
|
-
};
|
|
8883
|
-
}
|
|
8884
|
-
const items = this.readForceBatchItems(outcome.events ?? [], callCount);
|
|
8885
|
-
return {
|
|
8886
|
-
bids: bids.map((bid, index) => {
|
|
8887
|
-
const error = items.errors[placeIndexByBid[index]];
|
|
8888
|
-
return { commitment: bid.commitment, success: !error, error };
|
|
8889
|
-
}),
|
|
8890
|
-
blockHash: outcome.blockHash,
|
|
8891
|
-
extrinsicHash: outcome.extrinsicHash,
|
|
8892
|
-
error: items.error
|
|
8893
|
-
};
|
|
8894
|
-
}
|
|
8895
|
-
/**
|
|
8896
|
-
* Reads one outcome per call out of a force_batch's events.
|
|
8897
|
-
*
|
|
8898
|
-
* `ItemFailed` carries no index — pallet-utility emits exactly one `ItemCompleted` or
|
|
8899
|
-
* `ItemFailed` per call, in call order, so the k-th item event belongs to call k.
|
|
8900
|
-
*
|
|
8901
|
-
* A count that does not match the calls submitted means the events are not the ones assumed
|
|
8902
|
-
* here, and every attribution after the discrepancy would be off by one. The bids are then
|
|
8903
|
-
* reported as placed: a bid wrongly recorded as landed is retracted next interval and the
|
|
8904
|
-
* retraction harmlessly fails with `BidNotFound`, whereas one wrongly recorded as failed is
|
|
8905
|
-
* never retracted at all and leaves its deposit reserved.
|
|
8906
|
-
*/
|
|
8907
|
-
readForceBatchItems(events, callCount) {
|
|
8908
|
-
const errors = [];
|
|
8909
|
-
for (const { event } of events) {
|
|
8910
|
-
if (event.section !== "utility") continue;
|
|
8911
|
-
if (event.method === "ItemCompleted") errors.push(void 0);
|
|
8912
|
-
else if (event.method === "ItemFailed") errors.push(this.describeDispatchError(event.data[0]));
|
|
8913
|
-
}
|
|
8914
|
-
if (errors.length !== callCount) {
|
|
8915
|
-
return {
|
|
8916
|
-
errors: new Array(callCount).fill(void 0),
|
|
8917
|
-
error: `force_batch reported ${errors.length} item events for ${callCount} calls; outcomes not attributed`
|
|
8918
|
-
};
|
|
8919
|
-
}
|
|
8920
|
-
return { errors };
|
|
8921
|
-
}
|
|
8922
9011
|
/** Renders a DispatchError as `pallet::Error`, falling back to its raw form. */
|
|
8923
9012
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
8924
9013
|
describeDispatchError(dispatchError) {
|
|
@@ -8937,10 +9026,11 @@ var IntentsCoprocessor = class _IntentsCoprocessor {
|
|
|
8937
9026
|
*/
|
|
8938
9027
|
async getBidStorageEntries(commitment) {
|
|
8939
9028
|
const api = await this.http();
|
|
8940
|
-
const entries = await api.query.intentsCoprocessor.
|
|
9029
|
+
const entries = await api.query.intentsCoprocessor.orderBids.entries(commitment);
|
|
8941
9030
|
return entries.map(([storageKey, depositValue]) => ({
|
|
8942
9031
|
commitment,
|
|
8943
9032
|
filler: storageKey.args[1].toString(),
|
|
9033
|
+
bid: storageKey.args[2].toHex(),
|
|
8944
9034
|
deposit: BigInt(depositValue.toString())
|
|
8945
9035
|
}));
|
|
8946
9036
|
}
|
|
@@ -8972,7 +9062,7 @@ var IntentsCoprocessor = class _IntentsCoprocessor {
|
|
|
8972
9062
|
return result.map((entry) => {
|
|
8973
9063
|
const userOp = decodeUserOpScale(entry.user_op);
|
|
8974
9064
|
const filler = new Keyring({ type: "sr25519" }).encodeAddress(hexToU8a(entry.filler));
|
|
8975
|
-
return { filler, userOp, deposit: 0n };
|
|
9065
|
+
return { filler, bid: entry.bid, userOp, deposit: 0n };
|
|
8976
9066
|
});
|
|
8977
9067
|
}
|
|
8978
9068
|
/**
|
|
@@ -8981,19 +9071,20 @@ var IntentsCoprocessor = class _IntentsCoprocessor {
|
|
|
8981
9071
|
*/
|
|
8982
9072
|
async getBidsViaStorage(commitment) {
|
|
8983
9073
|
const api = await this.http();
|
|
8984
|
-
const entries = await api.query.intentsCoprocessor.
|
|
9074
|
+
const entries = await api.query.intentsCoprocessor.orderBids.entries(commitment);
|
|
8985
9075
|
if (entries.length === 0) return [];
|
|
8986
9076
|
const bidPromises = entries.map(async ([storageKey, depositValue]) => {
|
|
8987
9077
|
try {
|
|
8988
9078
|
const filler = storageKey.args[1].toString();
|
|
9079
|
+
const bid = storageKey.args[2].toHex();
|
|
8989
9080
|
const deposit = BigInt(depositValue.toString());
|
|
8990
|
-
const offchainKey = this.buildOffchainBidKey(commitment, filler);
|
|
9081
|
+
const offchainKey = this.buildOffchainBidKey(commitment, filler, bid);
|
|
8991
9082
|
const offchainKeyHex = u8aToHex(offchainKey);
|
|
8992
9083
|
const offchainResult = await api.rpc.offchain.localStorageGet("PERSISTENT", offchainKeyHex);
|
|
8993
9084
|
if (!offchainResult || offchainResult.isNone) return null;
|
|
8994
9085
|
const bidData = offchainResult.unwrap().toHex();
|
|
8995
9086
|
const decoded = this.decodeBid(bidData);
|
|
8996
|
-
return { filler: decoded.filler, userOp: decoded.userOp, deposit };
|
|
9087
|
+
return { filler: decoded.filler, bid, userOp: decoded.userOp, deposit };
|
|
8997
9088
|
} catch {
|
|
8998
9089
|
return null;
|
|
8999
9090
|
}
|
|
@@ -9009,411 +9100,31 @@ var IntentsCoprocessor = class _IntentsCoprocessor {
|
|
|
9009
9100
|
const userOp = decodeUserOpScale(userOpHex);
|
|
9010
9101
|
return { filler, userOp };
|
|
9011
9102
|
}
|
|
9012
|
-
/** Builds offchain storage key: "intents::bid::" + commitment + filler */
|
|
9013
|
-
buildOffchainBidKey(commitment, filler) {
|
|
9014
|
-
return u8aConcat(OFFCHAIN_BID_PREFIX, hexToU8a(commitment), decodeAddress(filler));
|
|
9103
|
+
/** Builds offchain storage key: "intents::bid::" + commitment + filler + bid */
|
|
9104
|
+
buildOffchainBidKey(commitment, filler, bid) {
|
|
9105
|
+
return u8aConcat(OFFCHAIN_BID_PREFIX, hexToU8a(commitment), decodeAddress(filler), hexToU8a(bid));
|
|
9015
9106
|
}
|
|
9016
|
-
|
|
9017
|
-
|
|
9018
|
-
|
|
9019
|
-
|
|
9020
|
-
|
|
9021
|
-
|
|
9022
|
-
* or the commitment has expired and been cleared).
|
|
9023
|
-
*/
|
|
9024
|
-
async fetchPhantomOrder(commitment) {
|
|
9025
|
-
const key = u8aConcat(OFFCHAIN_PHANTOM_PREFIX, hexToU8a(commitment));
|
|
9026
|
-
const api = await this.http();
|
|
9027
|
-
const result = await api.rpc.offchain.localStorageGet("PERSISTENT", u8aToHex(key));
|
|
9028
|
-
if (!result || result.isNone) return null;
|
|
9029
|
-
const rawHex = result.unwrap().toHex();
|
|
9030
|
-
if (rawHex === "0x" || rawHex === "0x00") return null;
|
|
9031
|
-
const placeOrderAbi = IntentGatewayV2_default.ABI.find((item) => item.type === "function" && item.name === "placeOrder");
|
|
9032
|
-
const orderType = placeOrderAbi?.inputs?.[0];
|
|
9033
|
-
if (!orderType) return null;
|
|
9034
|
-
const [decoded] = decodeAbiParameters([orderType], rawHex);
|
|
9035
|
-
const d = decoded;
|
|
9036
|
-
const textDecoder = new TextDecoder();
|
|
9037
|
-
return {
|
|
9038
|
-
id: commitment,
|
|
9039
|
-
user: d.user,
|
|
9040
|
-
source: textDecoder.decode(hexToBytes(d.source)),
|
|
9041
|
-
destination: textDecoder.decode(hexToBytes(d.destination)),
|
|
9042
|
-
deadline: d.deadline,
|
|
9043
|
-
nonce: d.nonce,
|
|
9044
|
-
fees: d.fees,
|
|
9045
|
-
session: d.session,
|
|
9046
|
-
predispatch: {
|
|
9047
|
-
assets: d.predispatch.assets.map((a) => ({
|
|
9048
|
-
token: a.token,
|
|
9049
|
-
amount: a.amount
|
|
9050
|
-
})),
|
|
9051
|
-
call: d.predispatch.call
|
|
9052
|
-
},
|
|
9053
|
-
inputs: d.inputs.map((i) => ({
|
|
9054
|
-
token: i.token,
|
|
9055
|
-
amount: i.amount
|
|
9056
|
-
})),
|
|
9057
|
-
output: {
|
|
9058
|
-
beneficiary: d.output.beneficiary,
|
|
9059
|
-
assets: d.output.assets.map((a) => ({
|
|
9060
|
-
token: a.token,
|
|
9061
|
-
amount: a.amount
|
|
9062
|
-
})),
|
|
9063
|
-
call: d.output.call
|
|
9064
|
-
}
|
|
9065
|
-
};
|
|
9107
|
+
};
|
|
9108
|
+
var TronChain = class _TronChain {
|
|
9109
|
+
constructor(params, evm) {
|
|
9110
|
+
this.params = params;
|
|
9111
|
+
this.evm = evm;
|
|
9112
|
+
this.tronWebInstance = new TronWeb({ fullHost: params.rpcUrl });
|
|
9066
9113
|
}
|
|
9114
|
+
params;
|
|
9115
|
+
evm;
|
|
9116
|
+
tronWebInstance;
|
|
9067
9117
|
/**
|
|
9068
|
-
*
|
|
9069
|
-
*
|
|
9070
|
-
* Costs two RPCs per block when `knownVersion` is supplied and four without it, which is why the
|
|
9071
|
-
* poll goes to the trouble of establishing one. `api.at(hash)` has to work out which metadata to
|
|
9072
|
-
* decode the block against, and with nothing to go on it fetches the header and then the runtime
|
|
9073
|
-
* version at its parent — every block, forever. Its cheaper paths are a registry already pinned
|
|
9074
|
-
* to this exact hash (only ever the previous block's) or one matching a version the caller
|
|
9075
|
-
* names, so naming the version is the only way out. See `getBlockRegistry` in
|
|
9076
|
-
* `@polkadot/api/base/Init`; the `getUpgradeVersion` shortcut that would otherwise skip the
|
|
9077
|
-
* lookup only covers chains hardcoded in `@polkadot/types-known`, which Hyperbridge is not.
|
|
9118
|
+
* Creates a `TronChain` instance from a fully-specified config object.
|
|
9078
9119
|
*
|
|
9079
|
-
*
|
|
9080
|
-
* established one. Passing a version the block does not actually run decodes it against the
|
|
9081
|
-
* wrong metadata, so this is for callers that have checked, not a place to pass a guess.
|
|
9082
|
-
*/
|
|
9083
|
-
async getPhantomOrdersInBlock(blockNumber, knownVersion) {
|
|
9084
|
-
const api = await this.http();
|
|
9085
|
-
const blockHash = await api.rpc.chain.getBlockHash(blockNumber);
|
|
9086
|
-
return await this.getPhantomOrdersAtHash(blockHash.toHex(), knownVersion);
|
|
9087
|
-
}
|
|
9088
|
-
/**
|
|
9089
|
-
* The same read, for a caller that already holds the block's hash.
|
|
9120
|
+
* This is the only public way to construct a `TronChain` — the constructor is private.
|
|
9090
9121
|
*
|
|
9091
|
-
*
|
|
9092
|
-
*
|
|
9093
|
-
* its hash. `chain_getBlockHash` is the half of the pair that parallelises safely: it takes no
|
|
9094
|
-
* historic block hash, so it never triggers polkadot-js's per-hash registry resolution, and
|
|
9095
|
-
* concurrent calls cannot race each other's registry state.
|
|
9122
|
+
* @param params - Tron chain configuration
|
|
9123
|
+
* @returns A `TronChain` instance
|
|
9096
9124
|
*/
|
|
9097
|
-
async
|
|
9098
|
-
const
|
|
9099
|
-
|
|
9100
|
-
return phantomOrdersFrom(await apiAt.query.system.events());
|
|
9101
|
-
}
|
|
9102
|
-
/**
|
|
9103
|
-
* Every block's phantom orders across a whole range, in one `state_queryStorage` call.
|
|
9104
|
-
*
|
|
9105
|
-
* This is the cheap path: the request cost of a scan stops depending on how many blocks it
|
|
9106
|
-
* covers. The events key is the only key queried, and both bounds are block hashes the caller
|
|
9107
|
-
* already holds.
|
|
9108
|
-
*
|
|
9109
|
-
* Two properties of the RPC shape the result.
|
|
9110
|
-
*
|
|
9111
|
-
* It returns *diffs*: `query_storage_unfiltered` in `sc-rpc` pushes a change set for a block only
|
|
9112
|
-
* when the value differs from the previous block in the range (`has_changed`, and the set is
|
|
9113
|
-
* dropped when empty), so a block whose events encode byte-for-byte identically to its
|
|
9114
|
-
* predecessor's is simply absent. That happens on a quiet chain, where consecutive blocks carry
|
|
9115
|
-
* nothing but the timestamp inherent's `ExtrinsicSuccess`. It is safe here because an absent
|
|
9116
|
-
* block provably carries no phantom orders: a `PhantomOrderRegistered` commitment is derived from
|
|
9117
|
-
* the block number (`phantom_order_commitment`), so a block that registered orders can never
|
|
9118
|
-
* encode identically to any other block. Absent therefore means "same as the previous block",
|
|
9119
|
-
* and the previous block having orders would contradict that.
|
|
9120
|
-
*
|
|
9121
|
-
* And it is gated by `--rpc-methods` (`check_if_safe` in `sc-rpc`), which answers a denied call
|
|
9122
|
-
* with `Method not found`. The node this reads from must already run unsafe RPC to serve
|
|
9123
|
-
* `offchain_localStorageGet` for the orders themselves, so this is normally available; the poll
|
|
9124
|
-
* falls back to reading block by block when it is not.
|
|
9125
|
-
*
|
|
9126
|
-
* @returns one entry per block the node reported a change for, in ascending block order.
|
|
9127
|
-
*/
|
|
9128
|
-
async getPhantomOrdersInRange(fromBlockHash, toBlockHash) {
|
|
9129
|
-
const api = await this.http();
|
|
9130
|
-
const changeSets = await api.rpc.state.queryStorage.raw(
|
|
9131
|
-
[SYSTEM_EVENTS_KEY],
|
|
9132
|
-
fromBlockHash,
|
|
9133
|
-
toBlockHash
|
|
9134
|
-
);
|
|
9135
|
-
return changeSets.map((changeSet) => {
|
|
9136
|
-
const value = changeSet?.changes?.find(([key]) => key === SYSTEM_EVENTS_KEY)?.[1];
|
|
9137
|
-
if (!value) return [];
|
|
9138
|
-
return phantomOrdersFrom(api.registry.createType("Vec<EventRecord>", value));
|
|
9139
|
-
});
|
|
9140
|
-
}
|
|
9141
|
-
/**
|
|
9142
|
-
* Polls for newly registered phantom orders, invoking the callback once per block that carries
|
|
9143
|
-
* any, with all of that block's orders.
|
|
9144
|
-
*
|
|
9145
|
-
* Per block rather than per order because that is how the pallet writes them: one order per
|
|
9146
|
-
* configured chain, all registered in the same `on_initialize`. Delivering them together lets a
|
|
9147
|
-
* caller bid on the whole interval in one extrinsic (see {@link submitPhantomBids}) instead of
|
|
9148
|
-
* one per chain.
|
|
9149
|
-
*
|
|
9150
|
-
* Each tick reads the current head and scans every block between the last one processed and that
|
|
9151
|
-
* head, so the block cursor — not the connection — determines what has been seen. This replaced a
|
|
9152
|
-
* system.events subscription, which was only as reliable as its socket: polkadot-js reconnects
|
|
9153
|
-
* the transport but does not reliably re-establish storage subscriptions, and anything emitted
|
|
9154
|
-
* while disconnected was lost silently. With a bid window measured in a handful of blocks, that
|
|
9155
|
-
* meant silently missed bids.
|
|
9156
|
-
*
|
|
9157
|
-
* Scanning a block range is gap-free rather than merely self-healing: an outage delays orders but
|
|
9158
|
-
* cannot drop them, because the cursor only advances past a block whose events were actually
|
|
9159
|
-
* read. Recovery replays the backlog.
|
|
9160
|
-
*
|
|
9161
|
-
* Every read here goes over HTTP, never the websocket. Polling is a sequence of independent
|
|
9162
|
-
* one-shot requests with no state to lose between them, which is exactly what a stateless
|
|
9163
|
-
* transport does well: a request either answers or fails loudly on this tick, instead of a
|
|
9164
|
-
* socket that looks alive while delivering nothing. It also means a websocket outage does not
|
|
9165
|
-
* pause phantom bidding at all — the two transports fail independently.
|
|
9166
|
-
*
|
|
9167
|
-
* What the cadence does *not* describe is the request rate, which is what rate limiters police.
|
|
9168
|
-
* A tick costs four requests whatever the range covers — the head, the runtime version, the two
|
|
9169
|
-
* bounding block hashes as one batched request, and one `state_queryStorage` for every block's
|
|
9170
|
-
* events — and they go out back-to-back, so an interval well under any per-second limit could
|
|
9171
|
-
* still arrive as a burst over it. Three things keep that in bounds: the provider coalesces
|
|
9172
|
-
* concurrent calls into one request and paces requests through the endpoint's token bucket (see
|
|
9173
|
-
* `http`), and `maxBlocksPerPoll` bounds the range. A 429 that gets through anyway backs the
|
|
9174
|
-
* poll off for a doubling number of ticks, so a limiter that is already shedding load is not
|
|
9175
|
-
* handed the next window's budget in rejections too.
|
|
9176
|
-
*
|
|
9177
|
-
* Where the node will not serve `state_queryStorage` the poll reads block by block instead, at
|
|
9178
|
-
* three requests plus one per block; see {@link scanRangeAtOnce}.
|
|
9179
|
-
*
|
|
9180
|
-
* Returns a function that stops polling.
|
|
9181
|
-
*/
|
|
9182
|
-
pollPhantomOrders(callback, options = {}) {
|
|
9183
|
-
const {
|
|
9184
|
-
intervalMs,
|
|
9185
|
-
maxBlocksPerPoll = DEFAULT_MAX_BLOCKS_PER_POLL,
|
|
9186
|
-
onError,
|
|
9187
|
-
onSkip
|
|
9188
|
-
} = options;
|
|
9189
|
-
let cursor = null;
|
|
9190
|
-
let inFlight = false;
|
|
9191
|
-
let stopped = false;
|
|
9192
|
-
let backoffTicks = 0;
|
|
9193
|
-
let backoffLength = 0;
|
|
9194
|
-
const tick = async () => {
|
|
9195
|
-
if (inFlight || stopped) return;
|
|
9196
|
-
if (backoffTicks > 0) {
|
|
9197
|
-
backoffTicks -= 1;
|
|
9198
|
-
return;
|
|
9199
|
-
}
|
|
9200
|
-
inFlight = true;
|
|
9201
|
-
try {
|
|
9202
|
-
const api = await this.http();
|
|
9203
|
-
const head = (await api.rpc.chain.getHeader()).number.toNumber();
|
|
9204
|
-
if (cursor === null) {
|
|
9205
|
-
cursor = Math.max(head - 1, -1);
|
|
9206
|
-
} else {
|
|
9207
|
-
const { bidWindowBlocks, intervalBlocks } = await this.phantomTimings();
|
|
9208
|
-
if (head - cursor > bidWindowBlocks + Math.max(intervalBlocks, bidWindowBlocks)) {
|
|
9209
|
-
const from = cursor + 1;
|
|
9210
|
-
cursor = Math.max(head - 1 - bidWindowBlocks, -1);
|
|
9211
|
-
onSkip?.({ from, to: cursor, head });
|
|
9212
|
-
}
|
|
9213
|
-
}
|
|
9214
|
-
if (head <= cursor) return;
|
|
9215
|
-
const knownVersion = await this.confirmedRuntimeVersion();
|
|
9216
|
-
const to = Math.min(head, cursor + maxBlocksPerPoll);
|
|
9217
|
-
const ranged = await this.scanRangeAtOnce(api, cursor + 1, to, knownVersion, onError);
|
|
9218
|
-
if (ranged) {
|
|
9219
|
-
for (const orders of ranged) {
|
|
9220
|
-
if (stopped) return;
|
|
9221
|
-
if (orders.length > 0) callback(orders);
|
|
9222
|
-
}
|
|
9223
|
-
cursor = to;
|
|
9224
|
-
backoffLength = 0;
|
|
9225
|
-
return;
|
|
9226
|
-
}
|
|
9227
|
-
const numbers = [];
|
|
9228
|
-
for (let blockNumber = cursor + 1; blockNumber <= to; blockNumber++) numbers.push(blockNumber);
|
|
9229
|
-
const hashes = await Promise.allSettled(
|
|
9230
|
-
numbers.map((blockNumber) => api.rpc.chain.getBlockHash(blockNumber))
|
|
9231
|
-
);
|
|
9232
|
-
for (let index = 0; index < numbers.length; index++) {
|
|
9233
|
-
if (stopped) return;
|
|
9234
|
-
const hash = hashes[index];
|
|
9235
|
-
if (hash.status === "rejected") throw hash.reason;
|
|
9236
|
-
const orders = await this.getPhantomOrdersAtHash(hash.value.toHex(), knownVersion);
|
|
9237
|
-
if (orders.length > 0) callback(orders);
|
|
9238
|
-
cursor = numbers[index];
|
|
9239
|
-
}
|
|
9240
|
-
backoffLength = 0;
|
|
9241
|
-
} catch (err) {
|
|
9242
|
-
if (isRateLimited(err)) {
|
|
9243
|
-
backoffLength = Math.min(backoffLength === 0 ? 1 : backoffLength * 2, MAX_RATE_LIMIT_BACKOFF_TICKS);
|
|
9244
|
-
backoffTicks = backoffLength;
|
|
9245
|
-
}
|
|
9246
|
-
onError?.(err);
|
|
9247
|
-
} finally {
|
|
9248
|
-
inFlight = false;
|
|
9249
|
-
}
|
|
9250
|
-
};
|
|
9251
|
-
void tick();
|
|
9252
|
-
let timer = null;
|
|
9253
|
-
const startTimer = (ms) => {
|
|
9254
|
-
if (stopped) return;
|
|
9255
|
-
timer = setInterval(() => void tick(), ms);
|
|
9256
|
-
};
|
|
9257
|
-
if (intervalMs !== void 0) startTimer(intervalMs);
|
|
9258
|
-
else void this.phantomPollIntervalMs().then(startTimer);
|
|
9259
|
-
return () => {
|
|
9260
|
-
stopped = true;
|
|
9261
|
-
if (timer) clearInterval(timer);
|
|
9262
|
-
};
|
|
9263
|
-
}
|
|
9264
|
-
/**
|
|
9265
|
-
* The Hyperbridge head, over HTTP like every other read here.
|
|
9266
|
-
*
|
|
9267
|
-
* Exposed for callers that have to know how old something is: a phantom order carries the block
|
|
9268
|
-
* it was registered at, and only against the head does that become "still biddable" or "long
|
|
9269
|
-
* expired".
|
|
9270
|
-
*/
|
|
9271
|
-
async latestBlockNumber() {
|
|
9272
|
-
const api = await this.http();
|
|
9273
|
-
return (await api.rpc.chain.getHeader()).number.toNumber();
|
|
9274
|
-
}
|
|
9275
|
-
/**
|
|
9276
|
-
* The pallet's phantom timings, read from chain state.
|
|
9277
|
-
*
|
|
9278
|
-
* Both are governance-settable and neither is derivable: on Nexus today the window is 15 while
|
|
9279
|
-
* the runtime constant behind it is 25, so anything hard-coded is wrong in one direction or the
|
|
9280
|
-
* other — too tight and live orders are dropped, too loose and bids are sent into a closed
|
|
9281
|
-
* window for the pallet to reject.
|
|
9282
|
-
*
|
|
9283
|
-
* Read once per instance and cached, because a governance change to either is rare and a read
|
|
9284
|
-
* per poll tick would be a request per tick forever. The cost is that a change is picked up on
|
|
9285
|
-
* the next restart rather than immediately. A failed read is not cached, so it retries.
|
|
9286
|
-
*/
|
|
9287
|
-
async phantomTimings() {
|
|
9288
|
-
if (!this.phantomTimingsRead) {
|
|
9289
|
-
this.phantomTimingsRead = this.readPhantomTimings().catch((err) => {
|
|
9290
|
-
this.phantomTimingsRead = null;
|
|
9291
|
-
throw err;
|
|
9292
|
-
});
|
|
9293
|
-
}
|
|
9294
|
-
return this.phantomTimingsRead;
|
|
9295
|
-
}
|
|
9296
|
-
async readPhantomTimings() {
|
|
9297
|
-
const api = await this.http();
|
|
9298
|
-
const [window, interval] = await Promise.all([
|
|
9299
|
-
api.query.intentsCoprocessor.phantomBidWindow(),
|
|
9300
|
-
api.query.intentsCoprocessor.phantomOrderInterval()
|
|
9301
|
-
]);
|
|
9302
|
-
const stored = Number(window.toString());
|
|
9303
|
-
return {
|
|
9304
|
-
bidWindowBlocks: stored === 0 ? Number(api.consts.intentsCoprocessor.phantomOrderBidWindowBlocks.toString()) : stored,
|
|
9305
|
-
intervalBlocks: Number(interval.toString())
|
|
9306
|
-
};
|
|
9307
|
-
}
|
|
9308
|
-
/**
|
|
9309
|
-
* A whole range of blocks in one `state_queryStorage` call, or `null` when that is not available
|
|
9310
|
-
* and the caller should read block by block.
|
|
9311
|
-
*
|
|
9312
|
-
* Two conditions have to hold, and both are about decoding rather than the range itself.
|
|
9313
|
-
*
|
|
9314
|
-
* The version must be confirmed for this tick — an upgrade inside the range means blocks decode
|
|
9315
|
-
* against different metadata, and one call cannot do that.
|
|
9316
|
-
*
|
|
9317
|
-
* And that confirmed version must still be the one the api's own registry was built for.
|
|
9318
|
-
* `state_queryStorage` declares no historic block hash, so rpc-core skips its registry swap and
|
|
9319
|
-
* decodes the reply against the default registry — fixed at connect, with no
|
|
9320
|
-
* `subscribeRuntimeVersion` on an HTTP api to refresh it. After an upgrade the two diverge, and
|
|
9321
|
-
* the per-block path takes over for good: `api.at(hash, version)` resolves, and builds, the right
|
|
9322
|
-
* registry. That costs a restart to get the cheap path back, which is the correct direction to
|
|
9323
|
-
* fail in.
|
|
9324
|
-
*/
|
|
9325
|
-
async scanRangeAtOnce(api, from, to, knownVersion, onError) {
|
|
9326
|
-
if (this.rangeQueryUnavailable || !knownVersion) return null;
|
|
9327
|
-
const registryVersion = api.runtimeVersion?.specVersion;
|
|
9328
|
-
if (!registryVersion || !knownVersion.specVersion.eq(registryVersion)) return null;
|
|
9329
|
-
const [fromHash, toHash] = from === to ? await Promise.all([api.rpc.chain.getBlockHash(from)]).then(([only]) => [only, only]) : await Promise.all([api.rpc.chain.getBlockHash(from), api.rpc.chain.getBlockHash(to)]);
|
|
9330
|
-
try {
|
|
9331
|
-
return await this.getPhantomOrdersInRange(fromHash.toHex(), toHash.toHex());
|
|
9332
|
-
} catch (err) {
|
|
9333
|
-
if (isMethodUnavailable(err)) {
|
|
9334
|
-
this.rangeQueryUnavailable = true;
|
|
9335
|
-
return null;
|
|
9336
|
-
}
|
|
9337
|
-
if (err instanceof EventDecodeError) {
|
|
9338
|
-
this.rangeQueryUnavailable = true;
|
|
9339
|
-
onError?.(err);
|
|
9340
|
-
return null;
|
|
9341
|
-
}
|
|
9342
|
-
throw err;
|
|
9343
|
-
}
|
|
9344
|
-
}
|
|
9345
|
-
/**
|
|
9346
|
-
* The runtime version this tick's blocks may be decoded against, or `undefined` when that cannot
|
|
9347
|
-
* be established and each block must resolve its own.
|
|
9348
|
-
*
|
|
9349
|
-
* Naming a version to `api.at` is what removes two of the four RPCs a block scan costs, and it
|
|
9350
|
-
* is only sound while the version is actually the block's. Getting that wrong is not a loud
|
|
9351
|
-
* failure: events decoded against the wrong metadata come back as a shape the scan does not
|
|
9352
|
-
* recognise, so the block reads as carrying no phantom orders and the cursor advances past it —
|
|
9353
|
-
* exactly the silent miss the block cursor exists to rule out.
|
|
9354
|
-
*
|
|
9355
|
-
* So the version is read fresh each tick and only used when it matches the previous reading.
|
|
9356
|
-
* `specVersion` only ever increases, and this read happens *after* the head read, so two equal
|
|
9357
|
-
* readings mean no upgrade landed anywhere in between — and therefore none in the range about to
|
|
9358
|
-
* be scanned. A reading that differs means an upgrade landed inside the range: that tick falls
|
|
9359
|
-
* back to per-block resolution, which is exact, and the version is used from the next tick on
|
|
9360
|
-
* once it has been seen twice.
|
|
9361
|
-
*
|
|
9362
|
-
* The gap this leaves is a backlog reaching back past an upgrade, whose oldest blocks predate
|
|
9363
|
-
* even the previous reading. Recovering from an outage that long means those bid windows closed
|
|
9364
|
-
* many upgrades ago, so nothing is lost that was still winnable.
|
|
9365
|
-
*
|
|
9366
|
-
* A version that cannot be read at all yields `undefined` rather than an error: the scan is
|
|
9367
|
-
* about to make the same request against the same endpoint and is the better place to report it.
|
|
9368
|
-
*/
|
|
9369
|
-
async confirmedRuntimeVersion() {
|
|
9370
|
-
let api;
|
|
9371
|
-
let current;
|
|
9372
|
-
try {
|
|
9373
|
-
api = await this.http();
|
|
9374
|
-
current = await api.rpc.state.getRuntimeVersion();
|
|
9375
|
-
} catch {
|
|
9376
|
-
return void 0;
|
|
9377
|
-
}
|
|
9378
|
-
const previous = this.lastRuntimeVersion ?? api.runtimeVersion;
|
|
9379
|
-
this.lastRuntimeVersion = current;
|
|
9380
|
-
if (!previous?.specVersion || !previous?.specName) return void 0;
|
|
9381
|
-
return current.specVersion.eq(previous.specVersion) && current.specName.eq(previous.specName) ? current : void 0;
|
|
9382
|
-
}
|
|
9383
|
-
/**
|
|
9384
|
-
* The poll cadence for the runtime this instance is connected to: Gargantua polls every block,
|
|
9385
|
-
* everything else every 15s. Falls back to the slower cadence if the runtime cannot be read,
|
|
9386
|
-
* since an unreachable node is the poll's problem to report, not the cadence lookup's.
|
|
9387
|
-
*/
|
|
9388
|
-
async phantomPollIntervalMs() {
|
|
9389
|
-
try {
|
|
9390
|
-
const specName = (await this.http()).runtimeVersion.specName.toString();
|
|
9391
|
-
return specName === "gargantua" ? GARGANTUA_PHANTOM_POLL_INTERVAL_MS : PHANTOM_POLL_INTERVAL_MS;
|
|
9392
|
-
} catch {
|
|
9393
|
-
return PHANTOM_POLL_INTERVAL_MS;
|
|
9394
|
-
}
|
|
9395
|
-
}
|
|
9396
|
-
};
|
|
9397
|
-
var TronChain = class _TronChain {
|
|
9398
|
-
constructor(params, evm) {
|
|
9399
|
-
this.params = params;
|
|
9400
|
-
this.evm = evm;
|
|
9401
|
-
this.tronWebInstance = new TronWeb({ fullHost: params.rpcUrl });
|
|
9402
|
-
}
|
|
9403
|
-
params;
|
|
9404
|
-
evm;
|
|
9405
|
-
tronWebInstance;
|
|
9406
|
-
/**
|
|
9407
|
-
* Creates a `TronChain` instance from a fully-specified config object.
|
|
9408
|
-
*
|
|
9409
|
-
* This is the only public way to construct a `TronChain` — the constructor is private.
|
|
9410
|
-
*
|
|
9411
|
-
* @param params - Tron chain configuration
|
|
9412
|
-
* @returns A `TronChain` instance
|
|
9413
|
-
*/
|
|
9414
|
-
static async fromParams(params) {
|
|
9415
|
-
const evm = await EvmChain.create(params.rpcUrl, params.bundlerUrl);
|
|
9416
|
-
return new _TronChain(params, evm);
|
|
9125
|
+
static async fromParams(params) {
|
|
9126
|
+
const evm = await EvmChain.create(params.rpcUrl, params.bundlerUrl);
|
|
9127
|
+
return new _TronChain(params, evm);
|
|
9417
9128
|
}
|
|
9418
9129
|
// -------------------------------------------------------------------------
|
|
9419
9130
|
// Public accessors
|
|
@@ -10476,8 +10187,8 @@ var PharosChain = class _PharosChain {
|
|
|
10476
10187
|
};
|
|
10477
10188
|
async function generateRootWithProof(postRequest, treeSize) {
|
|
10478
10189
|
const { generate_root_with_proof: generate_root_with_proof2 } = await load_ckb_mmr();
|
|
10479
|
-
const { commitment: hash, encodePacked:
|
|
10480
|
-
const result = JSON.parse(generate_root_with_proof2(hexToBytes(
|
|
10190
|
+
const { commitment: hash, encodePacked: encodePacked5 } = postRequestCommitment(postRequest);
|
|
10191
|
+
const result = JSON.parse(generate_root_with_proof2(hexToBytes(encodePacked5), treeSize));
|
|
10481
10192
|
const { root, proof, mmr_size, keccak_hash_calldata } = result;
|
|
10482
10193
|
if (keccak_hash_calldata !== hash) {
|
|
10483
10194
|
console.log("keccak_hash", keccak_hash_calldata);
|
|
@@ -10694,7 +10405,8 @@ async function retryPromise(operation, retryConfig) {
|
|
|
10694
10405
|
return await operation();
|
|
10695
10406
|
} catch (error) {
|
|
10696
10407
|
if (shouldRetry && !shouldRetry(error)) throw error;
|
|
10697
|
-
|
|
10408
|
+
const detail = error instanceof Error ? error.message.split("\n")[0] : String(error);
|
|
10409
|
+
logger.trace(`Retrying(${i}) > ${logMessage}: ${detail.slice(0, 200)}`);
|
|
10698
10410
|
lastError = error;
|
|
10699
10411
|
if (i === retryConfig.maxRetries - 1) break;
|
|
10700
10412
|
await new Promise((resolve) => setTimeout(resolve, retryConfig.backoffMs * 2 ** i));
|
|
@@ -12740,92 +12452,6 @@ query OrderStatus($commitment: String!) {
|
|
|
12740
12452
|
}
|
|
12741
12453
|
}
|
|
12742
12454
|
}`;
|
|
12743
|
-
var LATEST_PHANTOM_ORDER_PRICE_SNAPSHOT = `
|
|
12744
|
-
query LatestPhantomOrderPriceSnapshot($tokenA: String!, $tokenB: String!) {
|
|
12745
|
-
phantomOrderPriceSnapshots(
|
|
12746
|
-
filter: {
|
|
12747
|
-
and: [
|
|
12748
|
-
{ tokenA: { equalTo: $tokenA } }
|
|
12749
|
-
{ tokenB: { equalTo: $tokenB } }
|
|
12750
|
-
{ medianPrice: { isNull: false } }
|
|
12751
|
-
]
|
|
12752
|
-
}
|
|
12753
|
-
orderBy: BLOCK_NUMBER_DESC
|
|
12754
|
-
first: 1
|
|
12755
|
-
) {
|
|
12756
|
-
nodes {
|
|
12757
|
-
commitment
|
|
12758
|
-
tokenA
|
|
12759
|
-
tokenB
|
|
12760
|
-
standardAmount
|
|
12761
|
-
blockNumber
|
|
12762
|
-
medianPrice
|
|
12763
|
-
lowestPrice
|
|
12764
|
-
highestPrice
|
|
12765
|
-
bidCount
|
|
12766
|
-
snapshotTime
|
|
12767
|
-
}
|
|
12768
|
-
}
|
|
12769
|
-
}`;
|
|
12770
|
-
var AVAILABLE_LIQUIDITY = `
|
|
12771
|
-
query AvailableLiquidity(
|
|
12772
|
-
$poolId: String!
|
|
12773
|
-
$sourceChain: String!
|
|
12774
|
-
$destinationChain: String!
|
|
12775
|
-
$direction: String!
|
|
12776
|
-
) {
|
|
12777
|
-
poolChainLiquidities(
|
|
12778
|
-
filter: {
|
|
12779
|
-
and: [
|
|
12780
|
-
{ poolId: { equalToInsensitive: $poolId } }
|
|
12781
|
-
{ chain: { equalTo: $destinationChain } }
|
|
12782
|
-
{ direction: { equalTo: $direction } }
|
|
12783
|
-
]
|
|
12784
|
-
}
|
|
12785
|
-
first: 1
|
|
12786
|
-
) {
|
|
12787
|
-
nodes {
|
|
12788
|
-
depth
|
|
12789
|
-
bidCount
|
|
12790
|
-
unrestrictedDepth
|
|
12791
|
-
unrestrictedBidCount
|
|
12792
|
-
lastUpdatedAt
|
|
12793
|
-
}
|
|
12794
|
-
}
|
|
12795
|
-
poolRoutes(
|
|
12796
|
-
filter: {
|
|
12797
|
-
and: [
|
|
12798
|
-
{ poolId: { equalToInsensitive: $poolId } }
|
|
12799
|
-
{ sourceChain: { equalTo: $sourceChain } }
|
|
12800
|
-
{ chain: { equalTo: $destinationChain } }
|
|
12801
|
-
{ direction: { equalTo: $direction } }
|
|
12802
|
-
]
|
|
12803
|
-
}
|
|
12804
|
-
first: 1
|
|
12805
|
-
) {
|
|
12806
|
-
nodes {
|
|
12807
|
-
depth
|
|
12808
|
-
bidCount
|
|
12809
|
-
lastUpdatedAt
|
|
12810
|
-
}
|
|
12811
|
-
}
|
|
12812
|
-
}`;
|
|
12813
|
-
var BUY_AND_SELL_RATES = `
|
|
12814
|
-
query GetLiquidityPoolRate($poolId: String!) {
|
|
12815
|
-
liquidityPools(
|
|
12816
|
-
first: 1
|
|
12817
|
-
filter: { id: { equalToInsensitive: $poolId } }
|
|
12818
|
-
) {
|
|
12819
|
-
nodes {
|
|
12820
|
-
id
|
|
12821
|
-
token0Symbol
|
|
12822
|
-
token1Symbol
|
|
12823
|
-
sellRate
|
|
12824
|
-
buyRate
|
|
12825
|
-
lastUpdatedAt
|
|
12826
|
-
}
|
|
12827
|
-
}
|
|
12828
|
-
}`;
|
|
12829
12455
|
var TOKEN_GATEWAY_ASSET_TELEPORTED_STATUS = `
|
|
12830
12456
|
query TokenGatewayAssetTeleportedStatus($commitment: String!) {
|
|
12831
12457
|
tokenGatewayAssetTeleportedV2s(
|
|
@@ -12887,29 +12513,6 @@ async function queryAssetTeleported(params) {
|
|
|
12887
12513
|
function queryGetRequest(params) {
|
|
12888
12514
|
return _queryGetRequestInternal(params);
|
|
12889
12515
|
}
|
|
12890
|
-
async function _queryLatestPhantomOrderPriceSnapshot(params) {
|
|
12891
|
-
const response = await params.queryClient.request(
|
|
12892
|
-
LATEST_PHANTOM_ORDER_PRICE_SNAPSHOT,
|
|
12893
|
-
{
|
|
12894
|
-
tokenA: params.tokenA.toLowerCase(),
|
|
12895
|
-
tokenB: params.tokenB.toLowerCase()
|
|
12896
|
-
}
|
|
12897
|
-
);
|
|
12898
|
-
const snapshot = response.phantomOrderPriceSnapshots.nodes[0];
|
|
12899
|
-
if (!snapshot?.medianPrice) return;
|
|
12900
|
-
return {
|
|
12901
|
-
commitment: snapshot.commitment,
|
|
12902
|
-
tokenA: snapshot.tokenA,
|
|
12903
|
-
tokenB: snapshot.tokenB,
|
|
12904
|
-
standardAmount: BigInt(snapshot.standardAmount),
|
|
12905
|
-
blockNumber: BigInt(snapshot.blockNumber),
|
|
12906
|
-
medianPrice: BigInt(snapshot.medianPrice),
|
|
12907
|
-
lowestPrice: snapshot.lowestPrice === null ? void 0 : BigInt(snapshot.lowestPrice),
|
|
12908
|
-
highestPrice: snapshot.highestPrice === null ? void 0 : BigInt(snapshot.highestPrice),
|
|
12909
|
-
bidCount: snapshot.bidCount,
|
|
12910
|
-
snapshotTime: new Date(snapshot.snapshotTime)
|
|
12911
|
-
};
|
|
12912
|
-
}
|
|
12913
12516
|
async function _queryTokenGatewayAssetTeleportedInternal(params) {
|
|
12914
12517
|
const { commitmentHash, queryClient: client, logger = DEFAULT_LOGGER } = params;
|
|
12915
12518
|
const response = await retryPromise(
|
|
@@ -16183,18 +15786,39 @@ var CryptoUtils = class _CryptoUtils {
|
|
|
16183
15786
|
}
|
|
16184
15787
|
/**
|
|
16185
15788
|
* Derives the ERC-4337 nonce key that binds a bid UserOperation to its
|
|
16186
|
-
* order
|
|
16187
|
-
* `keccak256(commitment ‖ sessionKey)`. `SolverAccount`
|
|
16188
|
-
* operations whose nonce key differs — this is what lets the
|
|
16189
|
-
* the plain userOpHash while staying committed to the order and
|
|
16190
|
-
* session key it bid against.
|
|
15789
|
+
* order, session key and calldata: the lower 192 bits of
|
|
15790
|
+
* `keccak256(commitment ‖ sessionKey ‖ keccak256(callData))`. `SolverAccount`
|
|
15791
|
+
* rejects bid operations whose nonce key differs — this is what lets the
|
|
15792
|
+
* solver sign the plain userOpHash while staying committed to the order and
|
|
15793
|
+
* to the session key it bid against.
|
|
15794
|
+
*
|
|
15795
|
+
* The calldata gives every bid its own key. A solver bidding several prices
|
|
15796
|
+
* on one order signs one op per price, and each is sequence 0 of its own key,
|
|
15797
|
+
* so they execute independently rather than in a sequence where one bid that
|
|
15798
|
+
* is never selected blocks the rest.
|
|
16191
15799
|
*
|
|
16192
15800
|
* @param commitment - The order commitment (`order.id`).
|
|
16193
15801
|
* @param sessionKey - The order's session key address (`order.session`).
|
|
15802
|
+
* @param callData - The UserOperation's `callData`.
|
|
16194
15803
|
* @returns The 192-bit nonce key as a bigint (pass to `EntryPoint.getNonce`).
|
|
16195
15804
|
*/
|
|
16196
|
-
static bidNonceKey(commitment, sessionKey) {
|
|
16197
|
-
return BigInt(
|
|
15805
|
+
static bidNonceKey(commitment, sessionKey, callData) {
|
|
15806
|
+
return BigInt(
|
|
15807
|
+
keccak256(
|
|
15808
|
+
encodePacked(["bytes32", "address", "bytes32"], [commitment, sessionKey, keccak256(callData)])
|
|
15809
|
+
)
|
|
15810
|
+
) & (1n << 192n) - 1n;
|
|
15811
|
+
}
|
|
15812
|
+
/**
|
|
15813
|
+
* The identifier Hyperbridge files a bid under: `keccak256` of the UserOp's
|
|
15814
|
+
* `callData`. It is the same hash {@link bidNonceKey} takes, so a bid's
|
|
15815
|
+
* identifier and its nonce key both follow from the op itself, and one
|
|
15816
|
+
* solver's bids on one order are kept apart for the same reason on both sides.
|
|
15817
|
+
*
|
|
15818
|
+
* @param callData - The UserOperation's `callData`.
|
|
15819
|
+
*/
|
|
15820
|
+
static bidId(callData) {
|
|
15821
|
+
return keccak256(callData);
|
|
16198
15822
|
}
|
|
16199
15823
|
/**
|
|
16200
15824
|
* Builds the EIP-712 typed-data payload whose digest is the EntryPoint v0.8
|
|
@@ -16753,9 +16377,98 @@ var OrderPlacer = class {
|
|
|
16753
16377
|
return { order: finalizedOrder, receipt };
|
|
16754
16378
|
}
|
|
16755
16379
|
};
|
|
16380
|
+
var TOKEN_KEYED_GATEWAY_ABI = parseAbi([
|
|
16381
|
+
"function _orders(bytes32 commitment, address token) view returns (uint256)",
|
|
16382
|
+
"function _partialFills(bytes32 commitment, bytes32 token) view returns (uint256)"
|
|
16383
|
+
]);
|
|
16384
|
+
var keyingByClient = /* @__PURE__ */ new WeakMap();
|
|
16385
|
+
async function readLegEscrow(client, gateway, commitment, index, token) {
|
|
16386
|
+
return readKeyed(
|
|
16387
|
+
client,
|
|
16388
|
+
gateway,
|
|
16389
|
+
(keying) => keying === "leg" ? client.readContract({
|
|
16390
|
+
address: gateway,
|
|
16391
|
+
abi: ABI3,
|
|
16392
|
+
functionName: "_orders",
|
|
16393
|
+
args: [commitment, BigInt(index)]
|
|
16394
|
+
}) : client.readContract({
|
|
16395
|
+
address: gateway,
|
|
16396
|
+
abi: TOKEN_KEYED_GATEWAY_ABI,
|
|
16397
|
+
functionName: "_orders",
|
|
16398
|
+
args: [commitment, bytes32ToBytes20(token)]
|
|
16399
|
+
})
|
|
16400
|
+
);
|
|
16401
|
+
}
|
|
16402
|
+
async function readLegPartialFill(client, gateway, commitment, index, token) {
|
|
16403
|
+
return readKeyed(
|
|
16404
|
+
client,
|
|
16405
|
+
gateway,
|
|
16406
|
+
(keying) => keying === "leg" ? client.readContract({
|
|
16407
|
+
address: gateway,
|
|
16408
|
+
abi: ABI3,
|
|
16409
|
+
functionName: "_partialFills",
|
|
16410
|
+
args: [commitment, BigInt(index)]
|
|
16411
|
+
}) : client.readContract({
|
|
16412
|
+
address: gateway,
|
|
16413
|
+
abi: TOKEN_KEYED_GATEWAY_ABI,
|
|
16414
|
+
functionName: "_partialFills",
|
|
16415
|
+
args: [commitment, token]
|
|
16416
|
+
})
|
|
16417
|
+
);
|
|
16418
|
+
}
|
|
16419
|
+
async function readKeyed(client, gateway, read) {
|
|
16420
|
+
let known = keyingByClient.get(client);
|
|
16421
|
+
if (!known) {
|
|
16422
|
+
known = /* @__PURE__ */ new Map();
|
|
16423
|
+
keyingByClient.set(client, known);
|
|
16424
|
+
}
|
|
16425
|
+
const key = gateway.toLowerCase();
|
|
16426
|
+
const first = known.get(key) ?? "leg";
|
|
16427
|
+
try {
|
|
16428
|
+
const value = await read(first);
|
|
16429
|
+
known.set(key, first);
|
|
16430
|
+
return value;
|
|
16431
|
+
} catch (error) {
|
|
16432
|
+
if (!isRevert(error)) throw error;
|
|
16433
|
+
const second = first === "leg" ? "token" : "leg";
|
|
16434
|
+
try {
|
|
16435
|
+
const value = await read(second);
|
|
16436
|
+
known.set(key, second);
|
|
16437
|
+
return value;
|
|
16438
|
+
} catch (secondError) {
|
|
16439
|
+
throw isRevert(secondError) ? error : secondError;
|
|
16440
|
+
}
|
|
16441
|
+
}
|
|
16442
|
+
}
|
|
16443
|
+
function isRevert(error) {
|
|
16444
|
+
let current = error;
|
|
16445
|
+
while (current && typeof current === "object") {
|
|
16446
|
+
const item = current;
|
|
16447
|
+
if (item.name === "ContractFunctionZeroDataError") return true;
|
|
16448
|
+
if (item.code === 3) return true;
|
|
16449
|
+
if (!item.cause || typeof item.cause !== "object") {
|
|
16450
|
+
return /^(?:execution reverted\b|VM Exception while processing transaction:\s*revert\b|function selector was not recognized\b)/i.test(
|
|
16451
|
+
item.message ?? ""
|
|
16452
|
+
);
|
|
16453
|
+
}
|
|
16454
|
+
current = item.cause;
|
|
16455
|
+
}
|
|
16456
|
+
return false;
|
|
16457
|
+
}
|
|
16458
|
+
var PARTIAL_FILLS_SLOT = 11n;
|
|
16459
|
+
function partialFillSlot(commitment, index) {
|
|
16460
|
+
const inner = keccak256(encodePacked(["bytes32", "uint256"], [commitment, PARTIAL_FILLS_SLOT]));
|
|
16461
|
+
return keccak256(encodePacked(["uint256", "bytes32"], [BigInt(index), inner]));
|
|
16462
|
+
}
|
|
16756
16463
|
|
|
16757
16464
|
// src/protocols/intents/OrderExecutor.ts
|
|
16758
16465
|
var USED_USEROPS_STORAGE_KEY = (commitment) => `used-userops:${commitment.toLowerCase()}`;
|
|
16466
|
+
function remainingAfter(targets, filled) {
|
|
16467
|
+
return targets.map((target, index) => {
|
|
16468
|
+
const credited = filled[index]?.amount ?? 0n;
|
|
16469
|
+
return { token: target.token, amount: credited >= target.amount ? 0n : target.amount - credited };
|
|
16470
|
+
});
|
|
16471
|
+
}
|
|
16759
16472
|
var OrderExecutor = class {
|
|
16760
16473
|
constructor(ctx, bidManager) {
|
|
16761
16474
|
this.ctx = ctx;
|
|
@@ -16805,6 +16518,38 @@ var OrderExecutor = class {
|
|
|
16805
16518
|
JSON.stringify([...usedUserOps])
|
|
16806
16519
|
);
|
|
16807
16520
|
}
|
|
16521
|
+
/**
|
|
16522
|
+
* Reads the order's state on its destination chain into `totalFilledAssets`: the output credited
|
|
16523
|
+
* per leg from `_partialFills`, never below what is already counted, so a lagging RPC node cannot
|
|
16524
|
+
* take back a fill this executor has seen. Other solvers can fill the order too, so the chain, not
|
|
16525
|
+
* this executor's own fills, says how much is left.
|
|
16526
|
+
*
|
|
16527
|
+
* Returns the terminal update once `_filled` is set: `FILLED` when every leg is complete,
|
|
16528
|
+
* `CANCELLED` otherwise. `_filled` is read first because progress cannot change after it is set,
|
|
16529
|
+
* so a finalized order is never paired with progress from before its last fill.
|
|
16530
|
+
*/
|
|
16531
|
+
async syncWithDestination(order, commitment, targetAssets, totalFilledAssets) {
|
|
16532
|
+
const client = this.ctx.dest.client;
|
|
16533
|
+
const gateway = this.ctx.dest.configService.getIntentGatewayAddress(normalizeStateMachineId(order.destination));
|
|
16534
|
+
const finalizer = await client.readContract({
|
|
16535
|
+
address: gateway,
|
|
16536
|
+
abi: ABI3,
|
|
16537
|
+
functionName: "_filled",
|
|
16538
|
+
args: [commitment]
|
|
16539
|
+
});
|
|
16540
|
+
const filled = await Promise.all(
|
|
16541
|
+
order.output.assets.map(async (asset, index) => {
|
|
16542
|
+
const credited = await readLegPartialFill(client, gateway, commitment, index, asset.token);
|
|
16543
|
+
const counted = totalFilledAssets[index]?.amount ?? 0n;
|
|
16544
|
+
return { token: asset.token, amount: credited > counted ? credited : counted };
|
|
16545
|
+
})
|
|
16546
|
+
);
|
|
16547
|
+
const remainingAssets = remainingAfter(targetAssets, filled);
|
|
16548
|
+
if (/^0x0{40}$/i.test(finalizer)) return { totalFilledAssets: filled, remainingAssets };
|
|
16549
|
+
const progress = { commitment, totalFilledAssets: filled, remainingAssets };
|
|
16550
|
+
const final = remainingAssets.every((asset) => asset.amount === 0n) ? { status: "FILLED", selectedSolver: finalizer, ...progress } : { status: "CANCELLED", ...progress };
|
|
16551
|
+
return { totalFilledAssets: filled, remainingAssets, final };
|
|
16552
|
+
}
|
|
16808
16553
|
/**
|
|
16809
16554
|
* Creates a closure that computes the deduplication hash key for a
|
|
16810
16555
|
* UserOperation, pre-bound to the order's destination chain and entry point.
|
|
@@ -16863,12 +16608,12 @@ var OrderExecutor = class {
|
|
|
16863
16608
|
}
|
|
16864
16609
|
if (result.fillStatus === "partial") {
|
|
16865
16610
|
const filledAssets = result.filledAssets ?? [];
|
|
16866
|
-
totalFilledAssets = totalFilledAssets.map((a) => {
|
|
16867
|
-
const filled = filledAssets
|
|
16611
|
+
totalFilledAssets = totalFilledAssets.map((a, index) => {
|
|
16612
|
+
const filled = filledAssets[index];
|
|
16868
16613
|
return filled ? { token: a.token, amount: a.amount + filled.amount } : { ...a };
|
|
16869
16614
|
});
|
|
16870
|
-
remainingAssets = targetAssets.map((target) => {
|
|
16871
|
-
const filled = totalFilledAssets
|
|
16615
|
+
remainingAssets = targetAssets.map((target, index) => {
|
|
16616
|
+
const filled = totalFilledAssets[index];
|
|
16872
16617
|
const filledAmt = filled?.amount ?? 0n;
|
|
16873
16618
|
return {
|
|
16874
16619
|
token: target.token,
|
|
@@ -16934,8 +16679,27 @@ var OrderExecutor = class {
|
|
|
16934
16679
|
const usedUserOps = await this.loadUsedUserOps(commitment);
|
|
16935
16680
|
const userOpHashKey = this.createUserOpHasher(order);
|
|
16936
16681
|
const targetAssets = order.output.assets.map((a) => ({ token: a.token, amount: a.amount }));
|
|
16937
|
-
let
|
|
16938
|
-
|
|
16682
|
+
let initial;
|
|
16683
|
+
try {
|
|
16684
|
+
initial = await this.syncWithDestination(
|
|
16685
|
+
order,
|
|
16686
|
+
commitment,
|
|
16687
|
+
targetAssets,
|
|
16688
|
+
order.output.assets.map((a) => ({ token: a.token, amount: 0n }))
|
|
16689
|
+
);
|
|
16690
|
+
} catch (err) {
|
|
16691
|
+
yield {
|
|
16692
|
+
status: "FAILED",
|
|
16693
|
+
commitment,
|
|
16694
|
+
error: `Could not read the order on its destination chain: ${err instanceof Error ? err.message : String(err)}`
|
|
16695
|
+
};
|
|
16696
|
+
return;
|
|
16697
|
+
}
|
|
16698
|
+
if (initial.final) {
|
|
16699
|
+
yield initial.final;
|
|
16700
|
+
return;
|
|
16701
|
+
}
|
|
16702
|
+
const { totalFilledAssets, remainingAssets } = initial;
|
|
16939
16703
|
const executionStream = this.executionStream({
|
|
16940
16704
|
order,
|
|
16941
16705
|
sessionPrivateKey,
|
|
@@ -16967,7 +16731,7 @@ var OrderExecutor = class {
|
|
|
16967
16731
|
if (done) return;
|
|
16968
16732
|
const fed = yield value;
|
|
16969
16733
|
if (value.status === "BIDS_RECEIVED") input = fed;
|
|
16970
|
-
if (value.status === "EXPIRED" || value.status === "FILLED") return;
|
|
16734
|
+
if (value.status === "EXPIRED" || value.status === "FILLED" || value.status === "CANCELLED") return;
|
|
16971
16735
|
}
|
|
16972
16736
|
} finally {
|
|
16973
16737
|
console.log(`[OrderExecutor] Tearing down streams for commitment=${commitment}`);
|
|
@@ -17026,18 +16790,29 @@ var OrderExecutor = class {
|
|
|
17026
16790
|
}
|
|
17027
16791
|
while (true) {
|
|
17028
16792
|
let freshBids;
|
|
16793
|
+
let final;
|
|
17029
16794
|
try {
|
|
17030
|
-
|
|
17031
|
-
|
|
16795
|
+
;
|
|
16796
|
+
({ totalFilledAssets, remainingAssets, final } = await this.syncWithDestination(
|
|
16797
|
+
order,
|
|
16798
|
+
commitment,
|
|
16799
|
+
targetAssets,
|
|
16800
|
+
totalFilledAssets
|
|
16801
|
+
));
|
|
16802
|
+
freshBids = final ? [] : (await this.fetchBids({ commitment, solver, solverLockStartTime })).filter(isFreshBid);
|
|
17032
16803
|
} catch {
|
|
17033
16804
|
await sleep(pollIntervalMs);
|
|
17034
16805
|
continue;
|
|
17035
16806
|
}
|
|
16807
|
+
if (final) {
|
|
16808
|
+
yield final;
|
|
16809
|
+
return;
|
|
16810
|
+
}
|
|
17036
16811
|
if (freshBids.length === 0) {
|
|
17037
16812
|
await sleep(pollIntervalMs);
|
|
17038
16813
|
continue;
|
|
17039
16814
|
}
|
|
17040
|
-
const bids = this.bidManager.buildBids(order, freshBids, sessionPrivateKey);
|
|
16815
|
+
const bids = this.bidManager.buildBids(order, freshBids, sessionPrivateKey).filter((bid) => servesOpenLeg(bid, remainingAssets));
|
|
17041
16816
|
if (bids.length === 0) {
|
|
17042
16817
|
await sleep(pollIntervalMs);
|
|
17043
16818
|
continue;
|
|
@@ -17080,6 +16855,10 @@ var OrderExecutor = class {
|
|
|
17080
16855
|
}
|
|
17081
16856
|
}
|
|
17082
16857
|
};
|
|
16858
|
+
function servesOpenLeg(bid, remainingAssets) {
|
|
16859
|
+
if (bid.outputs.length !== remainingAssets.length) return true;
|
|
16860
|
+
return bid.outputs.some((output, leg) => output.amount > 0n && remainingAssets[leg].amount > 0n);
|
|
16861
|
+
}
|
|
17083
16862
|
var OrderCanceller = class _OrderCanceller {
|
|
17084
16863
|
/**
|
|
17085
16864
|
* @param ctx - Shared IntentsV2 context providing the source and destination
|
|
@@ -17118,8 +16897,9 @@ var OrderCanceller = class _OrderCanceller {
|
|
|
17118
16897
|
/**
|
|
17119
16898
|
* Quotes the native token cost of a source-initiated cross-chain cancellation.
|
|
17120
16899
|
*
|
|
17121
|
-
* Constructs
|
|
17122
|
-
* calls `quoteNative` on the source host to
|
|
16900
|
+
* Constructs the ISMP GET request the source gateway will dispatch, one
|
|
16901
|
+
* `_partialFills` key per leg, and calls `quoteNative` on the source host to
|
|
16902
|
+
* obtain the dispatch fee.
|
|
17123
16903
|
* Returns 0 for same-chain orders (no ISMP call needed).
|
|
17124
16904
|
*
|
|
17125
16905
|
* @param order - The order to quote.
|
|
@@ -17133,21 +16913,16 @@ var OrderCanceller = class _OrderCanceller {
|
|
|
17133
16913
|
}
|
|
17134
16914
|
const height = order.deadline + 1n;
|
|
17135
16915
|
const destIntentGateway = this.ctx.dest.configService.getIntentGatewayAddress(destStateMachine);
|
|
17136
|
-
const
|
|
17137
|
-
|
|
17138
|
-
|
|
17139
|
-
functionName: "calculateCommitmentSlotHash",
|
|
17140
|
-
args: [order.id]
|
|
17141
|
-
});
|
|
17142
|
-
const key = concatHex([destIntentGateway, slotHash]);
|
|
17143
|
-
const context = encodeWithdrawalRequest(order, order.user);
|
|
16916
|
+
const commitment = this.orderId(order);
|
|
16917
|
+
const keys = order.inputs.map((_, index) => concatHex([destIntentGateway, partialFillSlot(commitment, index)]));
|
|
16918
|
+
const context = cancelFromSourceContext(order, commitment);
|
|
17144
16919
|
const getRequest = {
|
|
17145
16920
|
source: sourceStateMachine,
|
|
17146
16921
|
dest: destStateMachine,
|
|
17147
16922
|
from: this.ctx.source.configService.getIntentGatewayAddress(destStateMachine),
|
|
17148
16923
|
nonce: await this.ctx.source.getHostNonce(),
|
|
17149
16924
|
height,
|
|
17150
|
-
keys
|
|
16925
|
+
keys,
|
|
17151
16926
|
timeoutTimestamp: 0n,
|
|
17152
16927
|
context
|
|
17153
16928
|
};
|
|
@@ -17172,10 +16947,13 @@ var OrderCanceller = class _OrderCanceller {
|
|
|
17172
16947
|
*
|
|
17173
16948
|
* @param order - The order to cancel.
|
|
17174
16949
|
* @param indexerClient - Indexer client used to stream ISMP request status
|
|
17175
|
-
* updates and query state-machine heights.
|
|
17176
|
-
*
|
|
16950
|
+
* updates and query state-machine heights. The direct same-chain route does
|
|
16951
|
+
* not access it.
|
|
16952
|
+
* @param options - Choose the initiation side. Defaults to source-side
|
|
16953
|
+
* cancellation. Same-chain orders always use the direct local route.
|
|
17177
16954
|
* @yields {@link CancelEvent} objects describing each stage of the
|
|
17178
|
-
* cancellation lifecycle.
|
|
16955
|
+
* cancellation lifecycle. The caller signs or broadcasts the yielded
|
|
16956
|
+
* transaction, so its signer may differ from `order.user` after expiry.
|
|
17179
16957
|
*/
|
|
17180
16958
|
async *cancelOrder(order, indexerClient, options = {}) {
|
|
17181
16959
|
const sourceStateMachine = normalizeStateMachineId(order.source);
|
|
@@ -17209,9 +16987,12 @@ var OrderCanceller = class _OrderCanceller {
|
|
|
17209
16987
|
* Async generator that cancels an order by initiating the cancel from the
|
|
17210
16988
|
* source chain.
|
|
17211
16989
|
*
|
|
17212
|
-
* **Same-chain path:** encodes a direct `cancelOrder` call
|
|
17213
|
-
* `AWAITING_CANCEL_TRANSACTION`,
|
|
17214
|
-
*
|
|
16990
|
+
* **Same-chain path:** encodes a direct `cancelOrder` call with zero cancel
|
|
16991
|
+
* options, yields `AWAITING_CANCEL_TRANSACTION`, accepts either a signed raw
|
|
16992
|
+
* transaction or an already-broadcast hash, and yields `CANCELLATION_COMPLETE`
|
|
16993
|
+
* after confirming the `EscrowRefunded` event. The contract authorizes the
|
|
16994
|
+
* order user through the deadline and any caller strictly after it; the SDK
|
|
16995
|
+
* preserves `order.user` in calldata so a third party cannot redirect escrow.
|
|
17215
16996
|
*
|
|
17216
16997
|
* **Cross-chain path:**
|
|
17217
16998
|
* 1. Fetches (or resumes from cache) a destination finalization proof.
|
|
@@ -17521,9 +17302,9 @@ var OrderCanceller = class _OrderCanceller {
|
|
|
17521
17302
|
}
|
|
17522
17303
|
}
|
|
17523
17304
|
/**
|
|
17524
|
-
* Polls for a finalized destination-chain state proof
|
|
17525
|
-
*
|
|
17526
|
-
*
|
|
17305
|
+
* Polls for a finalized destination-chain state proof of every leg's
|
|
17306
|
+
* `_partialFills` slot, i.e. how much of the order was filled before the
|
|
17307
|
+
* deadline.
|
|
17527
17308
|
*
|
|
17528
17309
|
* Waits until the latest Hyperbridge-tracked state-machine height exceeds
|
|
17529
17310
|
* `order.deadline` (or the last failed probe height) before attempting to
|
|
@@ -17552,14 +17333,9 @@ var OrderCanceller = class _OrderCanceller {
|
|
|
17552
17333
|
const intentGatewayV2Address = this.ctx.dest.configService.getIntentGatewayAddress(
|
|
17553
17334
|
this.ctx.dest.config.stateMachineId
|
|
17554
17335
|
);
|
|
17555
|
-
const
|
|
17556
|
-
const
|
|
17557
|
-
|
|
17558
|
-
address: intentGatewayV2Address,
|
|
17559
|
-
functionName: "calculateCommitmentSlotHash",
|
|
17560
|
-
args: [orderId]
|
|
17561
|
-
});
|
|
17562
|
-
const proofHex = await this.ctx.dest.queryStateProof(latestHeight, [slotHash], intentGatewayV2Address);
|
|
17336
|
+
const commitment = this.orderId(order);
|
|
17337
|
+
const slots = order.inputs.map((_, index) => partialFillSlot(commitment, index));
|
|
17338
|
+
const proofHex = await this.ctx.dest.queryStateProof(latestHeight, slots, intentGatewayV2Address);
|
|
17563
17339
|
const proof = {
|
|
17564
17340
|
consensusStateId: this.ctx.dest.config.consensusStateId,
|
|
17565
17341
|
height: latestHeight,
|
|
@@ -17757,118 +17533,135 @@ var OrderCanceller = class _OrderCanceller {
|
|
|
17757
17533
|
return feeInDestFeeToken * 1005n / 1000n;
|
|
17758
17534
|
}
|
|
17759
17535
|
};
|
|
17760
|
-
|
|
17761
|
-
|
|
17762
|
-
|
|
17763
|
-
|
|
17764
|
-
|
|
17765
|
-
outputs: [],
|
|
17766
|
-
inputs: [
|
|
17767
|
-
ABI3.find((e) => e.type === "function" && e.name === "fillOrder").inputs[0],
|
|
17536
|
+
function cancelFromSourceContext(order, commitment) {
|
|
17537
|
+
return encodeAbiParameters(
|
|
17538
|
+
[
|
|
17539
|
+
{ type: "bytes32" },
|
|
17540
|
+
{ type: "bytes32" },
|
|
17768
17541
|
{
|
|
17769
|
-
|
|
17770
|
-
type: "tuple",
|
|
17771
|
-
internalType: "struct FillOptions",
|
|
17542
|
+
type: "tuple[]",
|
|
17772
17543
|
components: [
|
|
17773
|
-
{ name: "
|
|
17774
|
-
{ name: "
|
|
17775
|
-
{
|
|
17776
|
-
name: "outputs",
|
|
17777
|
-
type: "tuple[]",
|
|
17778
|
-
internalType: "struct TokenInfo[]",
|
|
17779
|
-
components: [
|
|
17780
|
-
{ name: "token", type: "bytes32", internalType: "bytes32" },
|
|
17781
|
-
{ name: "amount", type: "uint256", internalType: "uint256" }
|
|
17782
|
-
]
|
|
17783
|
-
}
|
|
17544
|
+
{ name: "token", type: "bytes32" },
|
|
17545
|
+
{ name: "amount", type: "uint256" }
|
|
17784
17546
|
]
|
|
17785
|
-
}
|
|
17547
|
+
},
|
|
17548
|
+
{ type: "uint256[]" }
|
|
17549
|
+
],
|
|
17550
|
+
[
|
|
17551
|
+
commitment,
|
|
17552
|
+
bytes20ToBytes32(order.user),
|
|
17553
|
+
order.inputs.map((input) => ({ token: normalizeAddressForEvmBytes32(input.token), amount: input.amount })),
|
|
17554
|
+
order.output.assets.map((asset) => asset.amount)
|
|
17786
17555
|
]
|
|
17556
|
+
);
|
|
17557
|
+
}
|
|
17558
|
+
var FILL_ORDER_SELECTOR = "0x68ddf058";
|
|
17559
|
+
var SUPPORTED_INTENTS_VERSION = 3n;
|
|
17560
|
+
var CONTRACT_VERSION_ABI = [
|
|
17561
|
+
{
|
|
17562
|
+
type: "function",
|
|
17563
|
+
name: "version",
|
|
17564
|
+
stateMutability: "view",
|
|
17565
|
+
inputs: [],
|
|
17566
|
+
outputs: [{ name: "", type: "uint64" }]
|
|
17787
17567
|
}
|
|
17788
17568
|
];
|
|
17789
|
-
|
|
17790
|
-
|
|
17791
|
-
|
|
17792
|
-
|
|
17793
|
-
|
|
17794
|
-
|
|
17795
|
-
|
|
17796
|
-
var CHAINS_WITHOUT_VALID_UNTIL = /* @__PURE__ */ new Set([
|
|
17797
|
-
97,
|
|
17798
|
-
// BNB testnet
|
|
17799
|
-
10200,
|
|
17800
|
-
// Gnosis Chiado
|
|
17801
|
-
80002,
|
|
17802
|
-
// Polygon Amoy
|
|
17803
|
-
84532,
|
|
17804
|
-
// Base Sepolia
|
|
17805
|
-
421614,
|
|
17806
|
-
// Arbitrum Sepolia
|
|
17807
|
-
688689,
|
|
17808
|
-
// Pharos testnet
|
|
17809
|
-
11155111,
|
|
17810
|
-
// Sepolia
|
|
17811
|
-
11155420,
|
|
17812
|
-
// Optimism Sepolia
|
|
17813
|
-
420420417
|
|
17814
|
-
// Polkadot Hub Paseo
|
|
17815
|
-
]);
|
|
17816
|
-
var knownV2Gateways = /* @__PURE__ */ new Set();
|
|
17817
|
-
function resetFillOptionsVersionCache() {
|
|
17818
|
-
knownV2Gateways.clear();
|
|
17569
|
+
async function readContractVersion(client, address) {
|
|
17570
|
+
try {
|
|
17571
|
+
return await client.readContract({ address, abi: CONTRACT_VERSION_ABI, functionName: "version" });
|
|
17572
|
+
} catch (error) {
|
|
17573
|
+
if (isRevert(error)) return void 0;
|
|
17574
|
+
throw error;
|
|
17575
|
+
}
|
|
17819
17576
|
}
|
|
17820
|
-
async function
|
|
17821
|
-
|
|
17822
|
-
if (!slot || slot.length < 66) return gateway;
|
|
17823
|
-
const addr = `0x${slot.slice(-40)}`;
|
|
17824
|
-
return /^0x0{40}$/.test(addr) ? gateway : addr;
|
|
17577
|
+
async function supportsRateFills(client, gateway) {
|
|
17578
|
+
return await readContractVersion(client, gateway) === SUPPORTED_INTENTS_VERSION;
|
|
17825
17579
|
}
|
|
17826
|
-
async function
|
|
17827
|
-
const
|
|
17828
|
-
if (
|
|
17829
|
-
|
|
17830
|
-
|
|
17831
|
-
|
|
17832
|
-
if (LEGACY_FILL_OPTIONS_IMPLEMENTATIONS.has(implementation.toLowerCase())) return 1;
|
|
17833
|
-
knownV2Gateways.add(key);
|
|
17834
|
-
return 2;
|
|
17580
|
+
async function assertGatewayRelease(client, gateway) {
|
|
17581
|
+
const version = await readContractVersion(client, gateway);
|
|
17582
|
+
if (version === SUPPORTED_INTENTS_VERSION) return;
|
|
17583
|
+
throw new Error(
|
|
17584
|
+
version === void 0 ? `IntentGateway ${gateway} reports no version(); this SDK requires release ${SUPPORTED_INTENTS_VERSION}` : `IntentGateway ${gateway} reports release ${String(version)}; this SDK requires release ${SUPPORTED_INTENTS_VERSION}`
|
|
17585
|
+
);
|
|
17835
17586
|
}
|
|
17836
|
-
|
|
17837
|
-
|
|
17838
|
-
|
|
17839
|
-
|
|
17840
|
-
|
|
17841
|
-
|
|
17842
|
-
|
|
17587
|
+
var CANONICAL_EVM_TOKEN = /^0x0{24}[0-9a-fA-F]{40}$/;
|
|
17588
|
+
function isCanonicalEvmToken(token) {
|
|
17589
|
+
return CANONICAL_EVM_TOKEN.test(token);
|
|
17590
|
+
}
|
|
17591
|
+
function validateFillQuotes(order, options) {
|
|
17592
|
+
const count = order.output.assets.length;
|
|
17593
|
+
if (!count || !Array.isArray(options.inputs) || options.inputs.length !== count || options.outputs.length !== count || order.inputs.length !== count) {
|
|
17594
|
+
throw new Error("Fill inputs and outputs must quote every order leg");
|
|
17595
|
+
}
|
|
17596
|
+
for (let i = 0; i < count; i++) {
|
|
17597
|
+
const input = options.inputs[i];
|
|
17598
|
+
const output = options.outputs[i];
|
|
17599
|
+
if (input.token.toLowerCase() !== order.inputs[i].token.toLowerCase() || output.token.toLowerCase() !== order.output.assets[i].token.toLowerCase() || !isCanonicalEvmToken(input.token) || !isCanonicalEvmToken(output.token)) {
|
|
17600
|
+
throw new Error("Fill quote tokens must match their order legs");
|
|
17601
|
+
}
|
|
17602
|
+
if (input.amount === 0n !== (output.amount === 0n)) {
|
|
17603
|
+
throw new Error("Fill quote input and output must both be zero or positive");
|
|
17604
|
+
}
|
|
17843
17605
|
}
|
|
17844
|
-
|
|
17606
|
+
}
|
|
17607
|
+
function encodeFillOrder(order, options) {
|
|
17608
|
+
validateFillQuotes(order, options);
|
|
17845
17609
|
return encodeFunctionData({
|
|
17846
|
-
abi:
|
|
17610
|
+
abi: ABI3,
|
|
17847
17611
|
functionName: "fillOrder",
|
|
17848
|
-
args: [order,
|
|
17612
|
+
args: [order, options]
|
|
17849
17613
|
});
|
|
17850
17614
|
}
|
|
17851
17615
|
function decodeFillOrder(data) {
|
|
17852
17616
|
try {
|
|
17853
17617
|
const decoded = decodeFunctionData({ abi: ABI3, data });
|
|
17854
|
-
if (decoded.functionName
|
|
17855
|
-
|
|
17856
|
-
|
|
17857
|
-
|
|
17858
|
-
|
|
17859
|
-
try {
|
|
17860
|
-
const decoded = decodeFunctionData({ abi: FILL_ORDER_V1_ABI, data });
|
|
17861
|
-
if (decoded.functionName === "fillOrder" && decoded.args && decoded.args.length >= 2) {
|
|
17862
|
-
const legacy = decoded.args[1];
|
|
17863
|
-
return { order: decoded.args[0], options: { ...legacy, validUntil: 0n } };
|
|
17864
|
-
}
|
|
17618
|
+
if (decoded.functionName !== "fillOrder" || !decoded.args || decoded.args.length < 2) return null;
|
|
17619
|
+
const order = decoded.args[0];
|
|
17620
|
+
const options = decoded.args[1];
|
|
17621
|
+
validateFillQuotes(order, options);
|
|
17622
|
+
return { order, options };
|
|
17865
17623
|
} catch {
|
|
17624
|
+
return null;
|
|
17866
17625
|
}
|
|
17867
|
-
return null;
|
|
17868
17626
|
}
|
|
17869
|
-
var
|
|
17870
|
-
|
|
17627
|
+
var ENTRY_POINT_EVENT_ABI = [
|
|
17628
|
+
{ type: "event", name: "BeforeExecution", inputs: [] },
|
|
17629
|
+
{
|
|
17630
|
+
type: "event",
|
|
17631
|
+
name: "UserOperationEvent",
|
|
17632
|
+
inputs: [
|
|
17633
|
+
{ name: "userOpHash", type: "bytes32", indexed: true },
|
|
17634
|
+
{ name: "sender", type: "address", indexed: true },
|
|
17635
|
+
{ name: "paymaster", type: "address", indexed: true },
|
|
17636
|
+
{ name: "nonce", type: "uint256", indexed: false },
|
|
17637
|
+
{ name: "success", type: "bool", indexed: false },
|
|
17638
|
+
{ name: "actualGasCost", type: "uint256", indexed: false },
|
|
17639
|
+
{ name: "actualGasUsed", type: "uint256", indexed: false }
|
|
17640
|
+
]
|
|
17641
|
+
}
|
|
17642
|
+
];
|
|
17643
|
+
function userOperationLogs(logs, entryPoint, userOpHash) {
|
|
17644
|
+
const [beforeExecution, userOperationEvent] = ENTRY_POINT_EVENT_ABI.map((event) => toEventSelector(event));
|
|
17645
|
+
const isBoundary = (log) => log.address.toLowerCase() === entryPoint.toLowerCase() && (log.topics[0] === beforeExecution || log.topics[0] === userOperationEvent);
|
|
17646
|
+
const end = logs.findIndex(
|
|
17647
|
+
(log) => isBoundary(log) && log.topics[0] === userOperationEvent && log.topics[1]?.toLowerCase() === userOpHash.toLowerCase()
|
|
17648
|
+
);
|
|
17649
|
+
if (end === -1) throw new Error(`UserOperation ${userOpHash} is not in the transaction`);
|
|
17650
|
+
const { args } = decodeEventLog({
|
|
17651
|
+
abi: ENTRY_POINT_EVENT_ABI,
|
|
17652
|
+
eventName: "UserOperationEvent",
|
|
17653
|
+
data: logs[end].data,
|
|
17654
|
+
topics: logs[end].topics
|
|
17655
|
+
});
|
|
17656
|
+
if (!args.success) throw new Error(`UserOperation ${userOpHash} reverted`);
|
|
17657
|
+
let start = end - 1;
|
|
17658
|
+
while (start >= 0 && !isBoundary(logs[start])) start--;
|
|
17659
|
+
return logs.slice(start + 1, end);
|
|
17660
|
+
}
|
|
17661
|
+
var BidImpl = class {
|
|
17662
|
+
solverAddress;
|
|
17871
17663
|
outputs;
|
|
17664
|
+
inputs;
|
|
17872
17665
|
relayerFee;
|
|
17873
17666
|
nativeDispatchFee;
|
|
17874
17667
|
userOp;
|
|
@@ -17891,6 +17684,7 @@ var BidImpl = class {
|
|
|
17891
17684
|
this.sessionPrivateKey = params.sessionPrivateKey;
|
|
17892
17685
|
this.solverAddress = params.fillerBid.userOp.sender;
|
|
17893
17686
|
this.outputs = params.fillOptions.outputs;
|
|
17687
|
+
this.inputs = params.fillOptions.inputs;
|
|
17894
17688
|
this.relayerFee = params.fillOptions.relayerFee;
|
|
17895
17689
|
this.nativeDispatchFee = params.fillOptions.nativeDispatchFee;
|
|
17896
17690
|
this.userOp = params.fillerBid.userOp;
|
|
@@ -18023,31 +17817,28 @@ var BidImpl = class {
|
|
|
18023
17817
|
{ maxRetries: 5, backoffMs: 2e3, logMessage: "Fetching user operation receipt" }
|
|
18024
17818
|
);
|
|
18025
17819
|
txnHash = receipt.receipt.transactionHash;
|
|
18026
|
-
|
|
18027
|
-
|
|
18028
|
-
|
|
18029
|
-
|
|
18030
|
-
|
|
18031
|
-
|
|
18032
|
-
|
|
18033
|
-
|
|
18034
|
-
|
|
18035
|
-
|
|
18036
|
-
|
|
18037
|
-
|
|
18038
|
-
|
|
18039
|
-
|
|
18040
|
-
|
|
18041
|
-
|
|
18042
|
-
|
|
18043
|
-
|
|
18044
|
-
|
|
18045
|
-
|
|
18046
|
-
|
|
18047
|
-
|
|
18048
|
-
}
|
|
18049
|
-
} catch {
|
|
18050
|
-
throw new Error("Failed to determine fill status from logs");
|
|
17820
|
+
const chainReceipt = await this.ctx.dest.client.waitForTransactionReceipt({
|
|
17821
|
+
hash: txnHash,
|
|
17822
|
+
confirmations: 1
|
|
17823
|
+
});
|
|
17824
|
+
const gateway = this.ctx.dest.configService.getIntentGatewayAddress(
|
|
17825
|
+
normalizeStateMachineId(this.order.destination)
|
|
17826
|
+
);
|
|
17827
|
+
const fills = parseEventLogs({
|
|
17828
|
+
abi: ABI3,
|
|
17829
|
+
logs: userOperationLogs(chainReceipt.logs, entryPointAddress, userOpHash),
|
|
17830
|
+
eventName: ["OrderFilled", "PartialFill"]
|
|
17831
|
+
}).filter(
|
|
17832
|
+
(event) => event.address.toLowerCase() === gateway.toLowerCase() && event.args.commitment.toLowerCase() === commitment.toLowerCase()
|
|
17833
|
+
);
|
|
17834
|
+
if (fills.some((event) => event.eventName === "OrderFilled")) {
|
|
17835
|
+
fillStatus = "full";
|
|
17836
|
+
} else if (fills.length > 0) {
|
|
17837
|
+
fillStatus = "partial";
|
|
17838
|
+
filledAssets = fills[0].args.outputs.map(({ token }, index) => ({
|
|
17839
|
+
token,
|
|
17840
|
+
amount: fills.reduce((sum, event) => sum + (event.args.outputs[index]?.amount ?? 0n), 0n)
|
|
17841
|
+
}));
|
|
18051
17842
|
}
|
|
18052
17843
|
} catch (err) {
|
|
18053
17844
|
throw new Error(`Failed to execute bid: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -18114,6 +17905,20 @@ var BidManager = class {
|
|
|
18114
17905
|
callData,
|
|
18115
17906
|
paymasterAndData = "0x"
|
|
18116
17907
|
} = options;
|
|
17908
|
+
const fills = (this.crypto.decodeERC7821Execute(callData) ?? []).filter(
|
|
17909
|
+
(call) => call.data.slice(0, 10).toLowerCase() === FILL_ORDER_SELECTOR
|
|
17910
|
+
);
|
|
17911
|
+
if (fills.length === 0) throw new Error("Bid calldata carries no fillOrder call");
|
|
17912
|
+
for (const call of fills) {
|
|
17913
|
+
if (!decodeFillOrder(call.data)) {
|
|
17914
|
+
throw new Error("Malformed fill quote; every leg requires inputs and outputs");
|
|
17915
|
+
}
|
|
17916
|
+
}
|
|
17917
|
+
const chain = normalizeStateMachineId(order.destination);
|
|
17918
|
+
const gateway = this.ctx.dest.configService.getIntentGatewayAddress(chain);
|
|
17919
|
+
if (!await supportsRateFills(this.ctx.dest.client, gateway)) {
|
|
17920
|
+
throw new Error("Fills are not supported by the destination gateway");
|
|
17921
|
+
}
|
|
18117
17922
|
const chainId = BigInt(
|
|
18118
17923
|
this.ctx.dest.client.chain?.id ?? Number.parseInt(this.ctx.dest.config.stateMachineId.split("-")[1])
|
|
18119
17924
|
);
|
|
@@ -18131,10 +17936,10 @@ var BidManager = class {
|
|
|
18131
17936
|
signature: "0x"
|
|
18132
17937
|
};
|
|
18133
17938
|
const nonceKey = BigInt(nonce) >> 64n;
|
|
18134
|
-
const expectedKey = CryptoUtils.bidNonceKey(order.id, order.session);
|
|
17939
|
+
const expectedKey = CryptoUtils.bidNonceKey(order.id, order.session, callData);
|
|
18135
17940
|
if (nonceKey !== expectedKey) {
|
|
18136
17941
|
console.warn(
|
|
18137
|
-
`[BidManager] bid nonce key does not bind the order commitment
|
|
17942
|
+
`[BidManager] bid nonce key does not bind the order commitment, session key and calldata; on-chain validation will fail (order=${order.id})`
|
|
18138
17943
|
);
|
|
18139
17944
|
}
|
|
18140
17945
|
const solverSignature = await solverSigner.signTypedData(
|
|
@@ -18199,7 +18004,7 @@ var BidManager = class {
|
|
|
18199
18004
|
return this.selectAndExecuteBest(order, this.buildBids(order, bids, sessionPrivateKey));
|
|
18200
18005
|
}
|
|
18201
18006
|
/**
|
|
18202
|
-
* Autopilot bid selection: sorts the given bids by
|
|
18007
|
+
* Autopilot bid selection: sorts the given bids by rate, simulates
|
|
18203
18008
|
* each in order and attempts execution. Any bid that fails simulation or
|
|
18204
18009
|
* execution is skipped once so the next ranked bid can be attempted in the
|
|
18205
18010
|
* same round. For consumers that do not need custom selection logic.
|
|
@@ -18254,35 +18059,58 @@ var BidManager = class {
|
|
|
18254
18059
|
throw new Error("No bids passed simulation and execution");
|
|
18255
18060
|
}
|
|
18256
18061
|
/**
|
|
18257
|
-
* Sorts
|
|
18062
|
+
* Sorts bids by rate, best to worst, independently of how much each one fills.
|
|
18258
18063
|
*
|
|
18259
|
-
*
|
|
18260
|
-
*
|
|
18261
|
-
*
|
|
18262
|
-
*
|
|
18263
|
-
* - Mixed outputs: sort by DEX-quoted USD value descending, with a raw-amount
|
|
18264
|
-
* fallback if pricing fails.
|
|
18064
|
+
* A leg's rate is what the bid pays out for what it takes: `output / input` for
|
|
18065
|
+
* that leg. Every leg of an order trades the same pair, so a bid's rate is its
|
|
18066
|
+
* total output over its total input across the legs it quotes. Rates are
|
|
18067
|
+
* compared exactly, by cross-multiplication; equal rates keep arrival order.
|
|
18265
18068
|
*
|
|
18266
|
-
*
|
|
18069
|
+
* A bid is dropped when it does not quote the order's legs one for one, names
|
|
18070
|
+
* another token on a leg, quotes an input without an output (or the reverse),
|
|
18071
|
+
* quotes no leg at all, or quotes a leg below the rate the order requires.
|
|
18267
18072
|
*
|
|
18268
|
-
* @param order - The placed order
|
|
18073
|
+
* @param order - The placed order the bids compete to fill.
|
|
18269
18074
|
* @param bids - Executable bids to sort (from {@link buildBids}).
|
|
18270
|
-
* @returns
|
|
18075
|
+
* @returns The valid bids, best rate first, ready for simulation.
|
|
18271
18076
|
*/
|
|
18272
18077
|
async sortBids(order, bids) {
|
|
18273
|
-
const
|
|
18274
|
-
|
|
18275
|
-
|
|
18276
|
-
|
|
18277
|
-
|
|
18278
|
-
|
|
18279
|
-
|
|
18280
|
-
|
|
18281
|
-
|
|
18282
|
-
|
|
18078
|
+
const legs = order.inputs.length;
|
|
18079
|
+
const ranked = [];
|
|
18080
|
+
for (const [index, bid] of bids.entries()) {
|
|
18081
|
+
if (bid.inputs.length !== legs || bid.outputs.length !== legs || order.output.assets.length !== legs) {
|
|
18082
|
+
console.warn(`[BidManager] Bid from solver=${bid.solverAddress} REJECTED: does not quote the order's legs`);
|
|
18083
|
+
continue;
|
|
18084
|
+
}
|
|
18085
|
+
let input = 0n;
|
|
18086
|
+
let output = 0n;
|
|
18087
|
+
let reason = "";
|
|
18088
|
+
for (let leg = 0; leg < legs && !reason; leg++) {
|
|
18089
|
+
const take = bid.inputs[leg];
|
|
18090
|
+
const pay = bid.outputs[leg];
|
|
18091
|
+
const escrow = order.inputs[leg];
|
|
18092
|
+
const required = order.output.assets[leg];
|
|
18093
|
+
if (take.token.toLowerCase() !== escrow.token.toLowerCase()) reason = `input token mismatch on leg ${leg}`;
|
|
18094
|
+
else if (pay.token.toLowerCase() !== required.token.toLowerCase()) reason = `output token mismatch on leg ${leg}`;
|
|
18095
|
+
else if (take.amount < 0n || pay.amount < 0n || take.amount === 0n !== (pay.amount === 0n))
|
|
18096
|
+
reason = `no valid quote on leg ${leg}`;
|
|
18097
|
+
else if (pay.amount * escrow.amount < take.amount * required.amount) reason = `rate below the order on leg ${leg}`;
|
|
18098
|
+
input += take.amount;
|
|
18099
|
+
output += pay.amount;
|
|
18100
|
+
}
|
|
18101
|
+
if (!reason && input === 0n) reason = "quotes no leg";
|
|
18102
|
+
if (reason) {
|
|
18103
|
+
console.warn(`[BidManager] Bid from solver=${bid.solverAddress} REJECTED: ${reason}`);
|
|
18104
|
+
continue;
|
|
18105
|
+
}
|
|
18106
|
+
ranked.push({ bid, input, output, index });
|
|
18283
18107
|
}
|
|
18284
|
-
|
|
18285
|
-
|
|
18108
|
+
ranked.sort((a, b) => {
|
|
18109
|
+
const left = a.output * b.input;
|
|
18110
|
+
const right = b.output * a.input;
|
|
18111
|
+
return left === right ? a.index - b.index : left > right ? -1 : 1;
|
|
18112
|
+
});
|
|
18113
|
+
return ranked.map(({ bid }) => bid);
|
|
18286
18114
|
}
|
|
18287
18115
|
/**
|
|
18288
18116
|
* Extracts the `FillOptions` struct from a single bid's ERC-7821
|
|
@@ -18305,150 +18133,6 @@ var BidManager = class {
|
|
|
18305
18133
|
}
|
|
18306
18134
|
return null;
|
|
18307
18135
|
}
|
|
18308
|
-
/**
|
|
18309
|
-
* Case A: single output token.
|
|
18310
|
-
* Filter bids by token match only, sort descending by amount.
|
|
18311
|
-
* Partial fill bids are allowed — the contract determines fill status.
|
|
18312
|
-
*/
|
|
18313
|
-
sortSingleOutput(bids, requiredAsset) {
|
|
18314
|
-
const requiredAmount = new Decimal2(requiredAsset.amount.toString());
|
|
18315
|
-
console.log(
|
|
18316
|
-
`[BidManager] sortSingleOutput: required token=${requiredAsset.token}, amount=${requiredAmount.toString()}`
|
|
18317
|
-
);
|
|
18318
|
-
const validBids = [];
|
|
18319
|
-
for (const bid of bids) {
|
|
18320
|
-
const bidOutput = bid.outputs[0];
|
|
18321
|
-
const bidAmount = new Decimal2(bidOutput.amount.toString());
|
|
18322
|
-
if (bidOutput.token.toLowerCase() !== requiredAsset.token.toLowerCase()) {
|
|
18323
|
-
console.warn(
|
|
18324
|
-
`[BidManager] Bid from solver=${bid.solverAddress} REJECTED: token mismatch (bid=${bidOutput.token}, required=${requiredAsset.token})`
|
|
18325
|
-
);
|
|
18326
|
-
continue;
|
|
18327
|
-
}
|
|
18328
|
-
if (bidAmount.lt(requiredAmount)) {
|
|
18329
|
-
console.log(
|
|
18330
|
-
`[BidManager] Bid from solver=${bid.solverAddress}: partial fill candidate (bid=${bidAmount.toString()}, required=${requiredAmount.toString()}, covers=${bidAmount.div(requiredAmount).mul(100).toFixed(2)}%)`
|
|
18331
|
-
);
|
|
18332
|
-
} else {
|
|
18333
|
-
console.log(
|
|
18334
|
-
`[BidManager] Bid from solver=${bid.solverAddress} ACCEPTED: amount=${bidAmount.toString()} (surplus=${bidAmount.minus(requiredAmount).toString()})`
|
|
18335
|
-
);
|
|
18336
|
-
}
|
|
18337
|
-
validBids.push({ bid, amount: bidOutput.amount });
|
|
18338
|
-
}
|
|
18339
|
-
validBids.sort((a, b) => {
|
|
18340
|
-
const aAmt = new Decimal2(a.amount.toString());
|
|
18341
|
-
const bAmt = new Decimal2(b.amount.toString());
|
|
18342
|
-
return bAmt.comparedTo(aAmt);
|
|
18343
|
-
});
|
|
18344
|
-
return validBids.map(({ bid }) => bid);
|
|
18345
|
-
}
|
|
18346
|
-
/**
|
|
18347
|
-
* Case B: all outputs are USDC/USDT.
|
|
18348
|
-
* Sum normalised USD values (treating each stable as $1) and sort descending.
|
|
18349
|
-
* Partial fill bids are allowed.
|
|
18350
|
-
*/
|
|
18351
|
-
sortAllStables(bids, orderOutputs, chainId) {
|
|
18352
|
-
const requiredUsd = this.computeStablesUsdValue(orderOutputs, chainId);
|
|
18353
|
-
console.log(`[BidManager] sortAllStables: required USD value=${requiredUsd.toString()}`);
|
|
18354
|
-
const validBids = [];
|
|
18355
|
-
for (const bid of bids) {
|
|
18356
|
-
const bidUsd = this.computeStablesUsdValue(bid.outputs, chainId);
|
|
18357
|
-
if (bidUsd === null) {
|
|
18358
|
-
console.warn(`[BidManager] Bid from solver=${bid.solverAddress} REJECTED: unable to compute USD value`);
|
|
18359
|
-
continue;
|
|
18360
|
-
}
|
|
18361
|
-
if (bidUsd.lt(requiredUsd)) {
|
|
18362
|
-
console.log(
|
|
18363
|
-
`[BidManager] Bid from solver=${bid.solverAddress}: partial fill candidate (bid=${bidUsd.toString()}, required=${requiredUsd.toString()}, covers=${bidUsd.div(requiredUsd).mul(100).toFixed(2)}%)`
|
|
18364
|
-
);
|
|
18365
|
-
} else {
|
|
18366
|
-
console.log(`[BidManager] Bid from solver=${bid.solverAddress} ACCEPTED: USD value=${bidUsd.toString()}`);
|
|
18367
|
-
}
|
|
18368
|
-
validBids.push({ bid, usdValue: bidUsd });
|
|
18369
|
-
}
|
|
18370
|
-
validBids.sort((a, b) => b.usdValue.comparedTo(a.usdValue));
|
|
18371
|
-
return validBids.map(({ bid }) => bid);
|
|
18372
|
-
}
|
|
18373
|
-
/**
|
|
18374
|
-
* Case C: mixed output tokens (at least one non-stable).
|
|
18375
|
-
* Price every token via on-chain DEX quotes, fall back to raw amounts
|
|
18376
|
-
* if pricing is unavailable. Partial fill bids are allowed.
|
|
18377
|
-
*/
|
|
18378
|
-
async sortMixedOutputs(bids, orderOutputs, chainId) {
|
|
18379
|
-
const requiredUsd = await this.computeOutputsUsdValue(orderOutputs, chainId);
|
|
18380
|
-
if (requiredUsd === null) {
|
|
18381
|
-
console.warn("[BidManager] sortMixedOutputs: output tokens unpriceable, falling back to raw-amount sort");
|
|
18382
|
-
return this.sortByRawAmountFallback(bids, orderOutputs);
|
|
18383
|
-
}
|
|
18384
|
-
console.log(`[BidManager] sortMixedOutputs: required USD value=${requiredUsd.toString()}`);
|
|
18385
|
-
const validBids = [];
|
|
18386
|
-
for (const bid of bids) {
|
|
18387
|
-
const bidUsd = await this.computeOutputsUsdValue(bid.outputs, chainId);
|
|
18388
|
-
if (bidUsd === null) {
|
|
18389
|
-
console.warn(`[BidManager] Bid from solver=${bid.solverAddress} REJECTED: unable to price mixed outputs`);
|
|
18390
|
-
continue;
|
|
18391
|
-
}
|
|
18392
|
-
if (bidUsd.lt(requiredUsd)) {
|
|
18393
|
-
console.log(
|
|
18394
|
-
`[BidManager] Bid from solver=${bid.solverAddress}: partial fill candidate (bid=${bidUsd.toString()}, required=${requiredUsd.toString()}, covers=${bidUsd.div(requiredUsd).mul(100).toFixed(2)}%)`
|
|
18395
|
-
);
|
|
18396
|
-
} else {
|
|
18397
|
-
console.log(
|
|
18398
|
-
`[BidManager] Bid from solver=${bid.solverAddress} ACCEPTED: mixed USD value=${bidUsd.toString()}`
|
|
18399
|
-
);
|
|
18400
|
-
}
|
|
18401
|
-
validBids.push({ bid, usdValue: bidUsd });
|
|
18402
|
-
}
|
|
18403
|
-
validBids.sort((a, b) => b.usdValue.comparedTo(a.usdValue));
|
|
18404
|
-
return validBids.map(({ bid }) => bid);
|
|
18405
|
-
}
|
|
18406
|
-
/**
|
|
18407
|
-
* Fallback when DEX pricing is unavailable.
|
|
18408
|
-
* Computes total spread per bid. Bids missing a required token are rejected.
|
|
18409
|
-
* Bids offering less than required for a token are allowed (partial fill).
|
|
18410
|
-
* Sorted by total offered amount descending.
|
|
18411
|
-
*/
|
|
18412
|
-
sortByRawAmountFallback(bids, orderOutputs) {
|
|
18413
|
-
console.log(
|
|
18414
|
-
`[BidManager] sortByRawAmountFallback: checking ${bids.length} bid(s) against ${orderOutputs.length} required output(s)`
|
|
18415
|
-
);
|
|
18416
|
-
const validBids = [];
|
|
18417
|
-
for (const bid of bids) {
|
|
18418
|
-
let valid = true;
|
|
18419
|
-
let totalOffered = new Decimal2(0);
|
|
18420
|
-
let rejectReason = "";
|
|
18421
|
-
for (const required of orderOutputs) {
|
|
18422
|
-
const matching = bid.outputs.find((o) => o.token.toLowerCase() === required.token.toLowerCase());
|
|
18423
|
-
if (!matching) {
|
|
18424
|
-
valid = false;
|
|
18425
|
-
rejectReason = `missing output token=${required.token}`;
|
|
18426
|
-
break;
|
|
18427
|
-
}
|
|
18428
|
-
totalOffered = totalOffered.plus(new Decimal2(matching.amount.toString()));
|
|
18429
|
-
}
|
|
18430
|
-
if (!valid) {
|
|
18431
|
-
console.warn(`[BidManager] Bid from solver=${bid.solverAddress} REJECTED (fallback): ${rejectReason}`);
|
|
18432
|
-
continue;
|
|
18433
|
-
}
|
|
18434
|
-
const totalRequired = orderOutputs.reduce(
|
|
18435
|
-
(acc, o) => acc.plus(new Decimal2(o.amount.toString())),
|
|
18436
|
-
new Decimal2(0)
|
|
18437
|
-
);
|
|
18438
|
-
if (totalOffered.lt(totalRequired)) {
|
|
18439
|
-
console.log(
|
|
18440
|
-
`[BidManager] Bid from solver=${bid.solverAddress}: partial fill candidate (fallback) (offered=${totalOffered.toString()}, required=${totalRequired.toString()}, covers=${totalOffered.div(totalRequired).mul(100).toFixed(2)}%)`
|
|
18441
|
-
);
|
|
18442
|
-
} else {
|
|
18443
|
-
console.log(
|
|
18444
|
-
`[BidManager] Bid from solver=${bid.solverAddress} ACCEPTED (fallback): totalOffered=${totalOffered.toString()}`
|
|
18445
|
-
);
|
|
18446
|
-
}
|
|
18447
|
-
validBids.push({ bid, totalOffered });
|
|
18448
|
-
}
|
|
18449
|
-
validBids.sort((a, b) => b.totalOffered.comparedTo(a.totalOffered));
|
|
18450
|
-
return validBids.map(({ bid }) => bid);
|
|
18451
|
-
}
|
|
18452
18136
|
// ── Token classification helpers ──────────────────────────────────
|
|
18453
18137
|
/**
|
|
18454
18138
|
* Returns `true` if `tokenAddr` is either USDC or USDT on the given chain.
|
|
@@ -18479,23 +18163,6 @@ var BidManager = class {
|
|
|
18479
18163
|
return configService.getUsdtDecimals(chainId);
|
|
18480
18164
|
}
|
|
18481
18165
|
// ── Basket valuation helpers ──────────────────────────────────────
|
|
18482
|
-
/**
|
|
18483
|
-
* Sums the USD value of a basket of stable tokens (USDC/USDT only),
|
|
18484
|
-
* normalising each amount by its decimal count and treating each token as $1.
|
|
18485
|
-
*
|
|
18486
|
-
* @param outputs - List of token/amount pairs where every token is a stable.
|
|
18487
|
-
* @param chainId - State-machine ID used to look up decimals.
|
|
18488
|
-
* @returns Total USD value as a `Decimal`.
|
|
18489
|
-
*/
|
|
18490
|
-
computeStablesUsdValue(outputs, chainId) {
|
|
18491
|
-
let total = new Decimal2(0);
|
|
18492
|
-
for (const output of outputs) {
|
|
18493
|
-
const tokenAddr = bytes32ToBytes20(output.token);
|
|
18494
|
-
const decimals = this.getStableDecimals(tokenAddr, chainId);
|
|
18495
|
-
total = total.plus(new Decimal2(output.amount.toString()).div(new Decimal2(10).pow(decimals)));
|
|
18496
|
-
}
|
|
18497
|
-
return total;
|
|
18498
|
-
}
|
|
18499
18166
|
/**
|
|
18500
18167
|
* Prices every token in the basket via on-chain DEX quotes (token → USDC).
|
|
18501
18168
|
* Stables are valued at $1. Non-stables are quoted through Uniswap
|
|
@@ -18510,6 +18177,7 @@ var BidManager = class {
|
|
|
18510
18177
|
const { asset: wethAddr } = configService.getWrappedNativeAssetWithDecimals(chainId);
|
|
18511
18178
|
let totalUsd = new Decimal2(0);
|
|
18512
18179
|
for (const output of outputs) {
|
|
18180
|
+
if (output.amount === 0n) continue;
|
|
18513
18181
|
const tokenAddr = bytes32ToBytes20(output.token);
|
|
18514
18182
|
if (this.isStableToken(tokenAddr, chainId)) {
|
|
18515
18183
|
const decimals = this.getStableDecimals(tokenAddr, chainId);
|
|
@@ -18633,6 +18301,14 @@ var GasEstimator = class {
|
|
|
18633
18301
|
*/
|
|
18634
18302
|
async estimateFillOrder(params, pricingOptions = {}) {
|
|
18635
18303
|
const { order } = params;
|
|
18304
|
+
if (params.outputs !== void 0 && params.inputs === void 0) {
|
|
18305
|
+
throw new Error("Custom output quotes require explicit inputs");
|
|
18306
|
+
}
|
|
18307
|
+
const inputs = (params.inputs ?? order.inputs).map((input) => ({
|
|
18308
|
+
...input,
|
|
18309
|
+
token: normalizeAddressForEvmBytes32(input.token)
|
|
18310
|
+
}));
|
|
18311
|
+
const quotedOutputs = params.outputs ?? order.output.assets;
|
|
18636
18312
|
const orderFeeGasPriceBumpPercent = pricingOptions.orderFeeGasPriceBumpPercent ?? 0n;
|
|
18637
18313
|
const solverPrivateKey = generatePrivateKey();
|
|
18638
18314
|
const solverAccountAddress = privateKeyToAddress(solverPrivateKey);
|
|
@@ -18641,7 +18317,7 @@ var GasEstimator = class {
|
|
|
18641
18317
|
const intentGatewayV2Address = this.ctx.dest.configService.getIntentGatewayAddress(destStateMachineId);
|
|
18642
18318
|
const entryPointAddress = this.ctx.dest.configService.getEntryPointV08Address(destStateMachineId);
|
|
18643
18319
|
const chainId = BigInt(Number.parseInt(destStateMachineId.split("-")[1]));
|
|
18644
|
-
const totalEthValue =
|
|
18320
|
+
const totalEthValue = quotedOutputs.filter((output) => bytes32ToBytes20(output.token) === ADDRESS_ZERO2).reduce((sum, output) => sum + output.amount, 0n);
|
|
18645
18321
|
const [sourceFeeToken, destFeeToken, gasPrice, latestBlock] = await Promise.all([
|
|
18646
18322
|
getFeeToken(this.ctx, this.ctx.source.config.stateMachineId, this.ctx.source),
|
|
18647
18323
|
getFeeToken(this.ctx, this.ctx.dest.config.stateMachineId, this.ctx.dest),
|
|
@@ -18650,7 +18326,7 @@ var GasEstimator = class {
|
|
|
18650
18326
|
]);
|
|
18651
18327
|
const baseFeePerGas = latestBlock.baseFeePerGas ?? gasPrice;
|
|
18652
18328
|
const feeTokenAsBytes32 = bytes20ToBytes32(destFeeToken.address);
|
|
18653
|
-
const assetsForOverrides = [...
|
|
18329
|
+
const assetsForOverrides = [...quotedOutputs];
|
|
18654
18330
|
if (!assetsForOverrides.some((asset) => asset.token.toLowerCase() === feeTokenAsBytes32.toLowerCase())) {
|
|
18655
18331
|
assetsForOverrides.push({ token: feeTokenAsBytes32, amount: 0n });
|
|
18656
18332
|
}
|
|
@@ -18673,6 +18349,7 @@ var GasEstimator = class {
|
|
|
18673
18349
|
]);
|
|
18674
18350
|
const { bundler: bundlerStateOverrides } = stateOverridesResult;
|
|
18675
18351
|
const fillOptions = {
|
|
18352
|
+
inputs,
|
|
18676
18353
|
relayerFee: crossChainFees.postRequestFee,
|
|
18677
18354
|
// Always dispatch with the fee token (see the method docs).
|
|
18678
18355
|
nativeDispatchFee: 0n,
|
|
@@ -18680,7 +18357,7 @@ var GasEstimator = class {
|
|
|
18680
18357
|
// bound here would only risk the estimate reverting on a slow bundler round trip.
|
|
18681
18358
|
// The caller sets the real one on the options it actually signs.
|
|
18682
18359
|
validUntil: 0n,
|
|
18683
|
-
outputs:
|
|
18360
|
+
outputs: quotedOutputs.map((asset) => ({
|
|
18684
18361
|
...asset,
|
|
18685
18362
|
token: normalizeAddressForEvmBytes32(asset.token)
|
|
18686
18363
|
}))
|
|
@@ -18692,12 +18369,8 @@ var GasEstimator = class {
|
|
|
18692
18369
|
let maxFeePerGas = gasPrice + gasPrice * BigInt(maxFeeBumpPercent) / 100n;
|
|
18693
18370
|
const orderForEstimation = { ...order, session: solverAccountAddress };
|
|
18694
18371
|
const commitment = orderCommitment(orderForEstimation);
|
|
18695
|
-
|
|
18696
|
-
const fillOrderCalldata = encodeFillOrder(
|
|
18697
|
-
transformOrderForContract(orderForEstimation),
|
|
18698
|
-
fillOptions,
|
|
18699
|
-
fillOptionsVersion
|
|
18700
|
-
);
|
|
18372
|
+
await assertGatewayRelease(this.ctx.dest.client, intentGatewayV2Address);
|
|
18373
|
+
const fillOrderCalldata = encodeFillOrder(transformOrderForContract(orderForEstimation), fillOptions);
|
|
18701
18374
|
let callGasLimit = 500000n;
|
|
18702
18375
|
let verificationGasLimit = 100000n;
|
|
18703
18376
|
let preVerificationGas = 100000n;
|
|
@@ -18844,7 +18517,8 @@ var GasEstimator = class {
|
|
|
18844
18517
|
totalGasCostWei,
|
|
18845
18518
|
totalGasInFeeToken: totalGasInSourceFeeToken,
|
|
18846
18519
|
relayerFeeInSourceFeeToken: crossChainFees.relayerFeeInSourceFeeToken,
|
|
18847
|
-
fillOptions
|
|
18520
|
+
fillOptions,
|
|
18521
|
+
inputs
|
|
18848
18522
|
};
|
|
18849
18523
|
}
|
|
18850
18524
|
/**
|
|
@@ -19007,35 +18681,47 @@ var OrderStatusChecker = class {
|
|
|
19007
18681
|
}
|
|
19008
18682
|
ctx;
|
|
19009
18683
|
/**
|
|
19010
|
-
*
|
|
19011
|
-
*
|
|
19012
|
-
*
|
|
19013
|
-
* A non-zero value at that slot means the solver has called `fillOrder` and the order is complete
|
|
19014
|
-
* from the user's perspective (the beneficiary has received their tokens).
|
|
18684
|
+
* Whether the order is finalized on the destination chain, read from the gateway's `_filled`
|
|
18685
|
+
* getter. It is set by the completing fill, and by a cancellation, which records the refund
|
|
18686
|
+
* beneficiary there. A partially filled order reads false; see {@link getFillProgress}.
|
|
19015
18687
|
*
|
|
19016
18688
|
* @param order - The V2 order to check. `order.id` is used as the commitment; if not set it is computed.
|
|
19017
|
-
* @returns True if the order has been filled on the destination chain, false otherwise.
|
|
19018
18689
|
*/
|
|
19019
18690
|
async isOrderFilled(order) {
|
|
19020
18691
|
const commitment = order.id ?? orderCommitment(order);
|
|
19021
|
-
const
|
|
19022
|
-
const
|
|
19023
|
-
const filledSlot = await this.ctx.dest.client.readContract({
|
|
18692
|
+
const gateway = this.ctx.dest.configService.getIntentGatewayAddress(destinationStateMachine(order));
|
|
18693
|
+
const finalizer = await this.ctx.dest.client.readContract({
|
|
19024
18694
|
abi: ABI3,
|
|
19025
|
-
address:
|
|
19026
|
-
functionName: "
|
|
18695
|
+
address: gateway,
|
|
18696
|
+
functionName: "_filled",
|
|
19027
18697
|
args: [commitment]
|
|
19028
18698
|
});
|
|
19029
|
-
|
|
19030
|
-
|
|
19031
|
-
|
|
19032
|
-
|
|
19033
|
-
|
|
18699
|
+
return !/^0x0{40}$/i.test(finalizer);
|
|
18700
|
+
}
|
|
18701
|
+
/**
|
|
18702
|
+
* Output credited to the order so far, one entry per leg, read from `_partialFills` on the
|
|
18703
|
+
* destination chain. Several solvers can each fill a slice of a same-chain or cross-chain order,
|
|
18704
|
+
* so this, not {@link isOrderFilled}, says how far along an open order is. Surplus paid above
|
|
18705
|
+
* the order's rate is not counted.
|
|
18706
|
+
*
|
|
18707
|
+
* @param order - The V2 order to check. `order.id` is used as the commitment; if not set it is computed.
|
|
18708
|
+
*/
|
|
18709
|
+
async getFillProgress(order) {
|
|
18710
|
+
const commitment = order.id ?? orderCommitment(order);
|
|
18711
|
+
const gateway = this.ctx.dest.configService.getIntentGatewayAddress(destinationStateMachine(order));
|
|
18712
|
+
return Promise.all(
|
|
18713
|
+
order.output.assets.map(async (asset, index) => ({
|
|
18714
|
+
token: asset.token,
|
|
18715
|
+
amount: await readLegPartialFill(this.ctx.dest.client, gateway, commitment, index, asset.token)
|
|
18716
|
+
}))
|
|
18717
|
+
);
|
|
19034
18718
|
}
|
|
19035
18719
|
/**
|
|
19036
18720
|
* Checks if a V2 order has been refunded by reading the `_orders` mapping on the source chain.
|
|
19037
18721
|
*
|
|
19038
|
-
* Calls `_orders(commitment,
|
|
18722
|
+
* Calls `_orders(commitment, index)` for each input: escrow is held per leg, keyed by the input's
|
|
18723
|
+
* index, so inputs that repeat a token are read separately. A gateway not yet upgraded to per-leg
|
|
18724
|
+
* escrow is read by token instead, see {@link readLegEscrow}. When the order is placed the
|
|
19039
18725
|
* escrowed amounts are stored there. After a successful refund the contract zeroes them out.
|
|
19040
18726
|
* An order is considered refunded when all escrowed input amounts have been returned (i.e. are 0).
|
|
19041
18727
|
*
|
|
@@ -19047,14 +18733,14 @@ var OrderStatusChecker = class {
|
|
|
19047
18733
|
const commitment = order.id ?? orderCommitment(order);
|
|
19048
18734
|
const sourceStateMachineId = isHex(order.source) ? hexToString$1(order.source) : order.source;
|
|
19049
18735
|
const intentGatewayV2Address = this.ctx.source.configService.getIntentGatewayAddress(sourceStateMachineId);
|
|
19050
|
-
for (
|
|
19051
|
-
const
|
|
19052
|
-
|
|
19053
|
-
|
|
19054
|
-
|
|
19055
|
-
|
|
19056
|
-
|
|
19057
|
-
|
|
18736
|
+
for (let index = 0; index < order.inputs.length; index++) {
|
|
18737
|
+
const escrowedAmount = await readLegEscrow(
|
|
18738
|
+
this.ctx.source.client,
|
|
18739
|
+
intentGatewayV2Address,
|
|
18740
|
+
commitment,
|
|
18741
|
+
index,
|
|
18742
|
+
order.inputs[index].token
|
|
18743
|
+
);
|
|
19058
18744
|
if (escrowedAmount !== 0n) {
|
|
19059
18745
|
return false;
|
|
19060
18746
|
}
|
|
@@ -19062,727 +18748,374 @@ var OrderStatusChecker = class {
|
|
|
19062
18748
|
return true;
|
|
19063
18749
|
}
|
|
19064
18750
|
};
|
|
19065
|
-
|
|
19066
|
-
|
|
19067
|
-
function sortPoolSymbols(symbolA, symbolB) {
|
|
19068
|
-
return symbolA.toLowerCase() <= symbolB.toLowerCase() ? [symbolA, symbolB] : [symbolB, symbolA];
|
|
18751
|
+
function destinationStateMachine(order) {
|
|
18752
|
+
return isHex(order.destination) ? hexToString$1(order.destination) : order.destination;
|
|
19069
18753
|
}
|
|
19070
|
-
|
|
19071
|
-
|
|
19072
|
-
|
|
19073
|
-
|
|
19074
|
-
|
|
19075
|
-
return
|
|
19076
|
-
poolId: `${token0Symbol}-${token1Symbol}`,
|
|
19077
|
-
token0Symbol,
|
|
19078
|
-
token1Symbol
|
|
19079
|
-
};
|
|
18754
|
+
var ORDERBOOK_URLS = {
|
|
18755
|
+
mainnet: "https://orderbook.hyperfx.finance/mainnet/graphql",
|
|
18756
|
+
testnet: "https://orderbook.hyperfx.finance/testnet/graphql"
|
|
18757
|
+
};
|
|
18758
|
+
function orderbookUrlFor(stateMachineId) {
|
|
18759
|
+
return TESTNET_CHAINS.has(stateMachineId) ? ORDERBOOK_URLS.testnet : ORDERBOOK_URLS.mainnet;
|
|
19080
18760
|
}
|
|
19081
|
-
|
|
19082
|
-
|
|
19083
|
-
var
|
|
19084
|
-
|
|
19085
|
-
|
|
19086
|
-
|
|
19087
|
-
|
|
19088
|
-
|
|
19089
|
-
|
|
19090
|
-
|
|
19091
|
-
|
|
19092
|
-
|
|
18761
|
+
var ORDERBOOK_DECIMALS = 18;
|
|
18762
|
+
var ORDERBOOK_SCALE = 10n ** BigInt(ORDERBOOK_DECIMALS);
|
|
18763
|
+
var OrderbookRequestError = class extends Error {
|
|
18764
|
+
constructor(message) {
|
|
18765
|
+
super(`HyperFX orderbook request failed: ${message}`);
|
|
18766
|
+
this.name = "OrderbookRequestError";
|
|
18767
|
+
}
|
|
18768
|
+
};
|
|
18769
|
+
var RATE_FIELDS = "side fillChain rate depthIn depthOut backingLiquidity sourceChains orderCount solverCount";
|
|
18770
|
+
var TOP_OF_BOOK_QUERY = `
|
|
18771
|
+
query TopOfBook($tokenA: String!, $tokenB: String!, $fillChain: String!, $sourceChain: String!) {
|
|
18772
|
+
books { id base quote }
|
|
18773
|
+
aToB: bestRate(tokenIn: $tokenA, tokenOut: $tokenB, fillChain: $fillChain, sourceChain: $sourceChain) { ${RATE_FIELDS} }
|
|
18774
|
+
bToA: bestRate(tokenIn: $tokenB, tokenOut: $tokenA, fillChain: $fillChain, sourceChain: $sourceChain) { ${RATE_FIELDS} }
|
|
18775
|
+
}`;
|
|
18776
|
+
var ROUTE_LIQUIDITY_QUERY = `
|
|
18777
|
+
query RouteLiquidity($route: RouteInput!) {
|
|
18778
|
+
books { id base quote }
|
|
18779
|
+
routeLiquidity(route: $route) {
|
|
18780
|
+
route bestRate depthIn depthOut availableLiquidity maxFillableIn orderCount solverCount
|
|
18781
|
+
}
|
|
18782
|
+
}`;
|
|
18783
|
+
var QUOTE_QUERY = `
|
|
18784
|
+
query Quote($route: RouteInput!, $amountIn: BigInt!) {
|
|
18785
|
+
quote(route: $route, amountIn: $amountIn) {
|
|
18786
|
+
route side amountIn amountOut rate fillable depth maxFillableIn
|
|
18787
|
+
fills { orderRate amountOut advertisedSize }
|
|
18788
|
+
}
|
|
18789
|
+
}`;
|
|
18790
|
+
var ORDERBOOK_QUERIES = {
|
|
18791
|
+
topOfBook: TOP_OF_BOOK_QUERY,
|
|
18792
|
+
routeLiquidity: ROUTE_LIQUIDITY_QUERY,
|
|
18793
|
+
quote: QUOTE_QUERY
|
|
18794
|
+
};
|
|
18795
|
+
var HyperFxOrderbook = class {
|
|
18796
|
+
client;
|
|
18797
|
+
/** @param urlOrClient - The orderbook's GraphQL URL, or a configured `graphql-request` client. */
|
|
18798
|
+
constructor(urlOrClient = ORDERBOOK_URLS.mainnet) {
|
|
18799
|
+
this.client = typeof urlOrClient === "string" ? new GraphQLClient(urlOrClient) : urlOrClient;
|
|
18800
|
+
}
|
|
19093
18801
|
/**
|
|
19094
|
-
*
|
|
19095
|
-
*
|
|
19096
|
-
|
|
19097
|
-
|
|
19098
|
-
|
|
19099
|
-
|
|
19100
|
-
|
|
19101
|
-
|
|
19102
|
-
|
|
19103
|
-
|
|
19104
|
-
|
|
19105
|
-
*/
|
|
19106
|
-
async getAvailableLiquidity(params) {
|
|
19107
|
-
const pool = resolveLiquidityPool(params.source.symbol, params.destination.symbol);
|
|
19108
|
-
const direction = params.source.symbol.toLowerCase() === pool.token0Symbol.toLowerCase() ? SELL : BUY;
|
|
19109
|
-
const variables = {
|
|
19110
|
-
poolId: pool.poolId,
|
|
19111
|
-
sourceChain: params.source.chain,
|
|
19112
|
-
destinationChain: params.destination.chain,
|
|
19113
|
-
direction
|
|
18802
|
+
* The best bid and ask on `fillChain` for the pair `tokenA`/`tokenB`, counting
|
|
18803
|
+
* only orders a swap from `sourceChain` can use.
|
|
18804
|
+
*/
|
|
18805
|
+
async topOfBook(params) {
|
|
18806
|
+
const data = await this.request(TOP_OF_BOOK_QUERY, params);
|
|
18807
|
+
const book = findBook(data.books, params.tokenA, params.tokenB);
|
|
18808
|
+
const rates = [data.aToB, data.bToA].filter((rate) => rate !== null).map(parseRate);
|
|
18809
|
+
return {
|
|
18810
|
+
book,
|
|
18811
|
+
bid: rates.find((rate) => rate.side === "BID") ?? null,
|
|
18812
|
+
ask: rates.find((rate) => rate.side === "ASK") ?? null
|
|
19114
18813
|
};
|
|
19115
|
-
|
|
19116
|
-
|
|
19117
|
-
|
|
19118
|
-
}
|
|
19119
|
-
const
|
|
19120
|
-
if (!chainLiquidity) return void 0;
|
|
19121
|
-
const route = response.poolRoutes.nodes[0];
|
|
18814
|
+
}
|
|
18815
|
+
/** Total liquidity on a route, no amount required. */
|
|
18816
|
+
async routeLiquidity(route) {
|
|
18817
|
+
const { books, routeLiquidity: raw } = await this.request(ROUTE_LIQUIDITY_QUERY, { route });
|
|
18818
|
+
const book = findBook(books, route.tokenIn, route.tokenOut);
|
|
19122
18819
|
return {
|
|
19123
|
-
|
|
19124
|
-
|
|
19125
|
-
|
|
19126
|
-
|
|
19127
|
-
|
|
19128
|
-
|
|
19129
|
-
|
|
19130
|
-
|
|
19131
|
-
|
|
19132
|
-
|
|
19133
|
-
explicitRoute: route ? {
|
|
19134
|
-
...readLiquiditySlice(route.depth, route.bidCount, "explicit route"),
|
|
19135
|
-
updatedAt: readIndexerDate(route.lastUpdatedAt, "route lastUpdatedAt")
|
|
19136
|
-
} : null
|
|
18820
|
+
route: raw.route,
|
|
18821
|
+
book,
|
|
18822
|
+
side: book.base === route.tokenIn ? "BID" : "ASK",
|
|
18823
|
+
bestRate: raw.bestRate === null ? null : BigInt(raw.bestRate),
|
|
18824
|
+
depthIn: BigInt(raw.depthIn),
|
|
18825
|
+
depthOut: BigInt(raw.depthOut),
|
|
18826
|
+
availableLiquidity: BigInt(raw.availableLiquidity),
|
|
18827
|
+
maxFillableIn: BigInt(raw.maxFillableIn),
|
|
18828
|
+
orderCount: raw.orderCount,
|
|
18829
|
+
solverCount: raw.solverCount
|
|
19137
18830
|
};
|
|
19138
18831
|
}
|
|
19139
|
-
/**
|
|
19140
|
-
|
|
19141
|
-
|
|
19142
|
-
|
|
19143
|
-
|
|
19144
|
-
* source and destination chains remain part of the result because they define
|
|
19145
|
-
* the cross-chain route whose configured token symbols were resolved.
|
|
19146
|
-
*/
|
|
19147
|
-
async getBuyAndSellRates(params) {
|
|
19148
|
-
const pool = resolveLiquidityPool(params.tokenInSymbol, params.tokenOutSymbol);
|
|
19149
|
-
const response = await this.queryClient.request(BUY_AND_SELL_RATES, {
|
|
19150
|
-
poolId: pool.poolId
|
|
18832
|
+
/** The clearing price for `amountIn` (1e18 tokenIn) on a route, which may combine several solvers' orders. */
|
|
18833
|
+
async quote(route, amountIn) {
|
|
18834
|
+
const { quote: raw } = await this.request(QUOTE_QUERY, {
|
|
18835
|
+
route,
|
|
18836
|
+
amountIn: amountIn.toString()
|
|
19151
18837
|
});
|
|
19152
|
-
if (!response?.liquidityPools?.nodes) {
|
|
19153
|
-
throw new InvalidLiquidityIndexerResponseError("liquidity pool connection is missing");
|
|
19154
|
-
}
|
|
19155
|
-
const indexedPool = response.liquidityPools.nodes[0];
|
|
19156
|
-
if (!indexedPool) return void 0;
|
|
19157
|
-
validateIndexedPool(indexedPool, pool);
|
|
19158
|
-
const sell = readIndexedRate(indexedPool.sellRate, indexedPool.lastUpdatedAt, "pool sell rate");
|
|
19159
|
-
const buy = readIndexedRate(indexedPool.buyRate, indexedPool.lastUpdatedAt, "pool buy rate");
|
|
19160
|
-
const inputIsToken0 = params.tokenInSymbol.toLowerCase() === pool.token0Symbol.toLowerCase();
|
|
19161
|
-
const direct = inputIsToken0 ? sell : buy;
|
|
19162
|
-
const reverse = inputIsToken0 ? buy : sell;
|
|
19163
|
-
if (!direct && !reverse) return void 0;
|
|
19164
|
-
const quoteTokenSymbol = resolveQuoteTokenSymbol(
|
|
19165
|
-
params.tokenInSymbol,
|
|
19166
|
-
params.tokenOutSymbol,
|
|
19167
|
-
direct?.scaledRate,
|
|
19168
|
-
reverse?.scaledRate
|
|
19169
|
-
);
|
|
19170
|
-
const quoteIsTokenOut = quoteTokenSymbol === params.tokenOutSymbol;
|
|
19171
|
-
const orientedBuy = quoteIsTokenOut ? direct : reverse;
|
|
19172
|
-
const orientedSell = quoteIsTokenOut ? reverse : direct;
|
|
19173
18838
|
return {
|
|
19174
|
-
|
|
19175
|
-
|
|
19176
|
-
|
|
19177
|
-
|
|
19178
|
-
|
|
19179
|
-
|
|
19180
|
-
|
|
19181
|
-
|
|
18839
|
+
route: raw.route,
|
|
18840
|
+
side: raw.side,
|
|
18841
|
+
amountIn: BigInt(raw.amountIn),
|
|
18842
|
+
amountOut: BigInt(raw.amountOut),
|
|
18843
|
+
rate: raw.rate === null ? null : BigInt(raw.rate),
|
|
18844
|
+
fillable: raw.fillable,
|
|
18845
|
+
depth: BigInt(raw.depth),
|
|
18846
|
+
maxFillableIn: BigInt(raw.maxFillableIn),
|
|
18847
|
+
fills: raw.fills.map((fill) => ({
|
|
18848
|
+
orderRate: BigInt(fill.orderRate),
|
|
18849
|
+
amountOut: BigInt(fill.amountOut),
|
|
18850
|
+
advertisedSize: BigInt(fill.advertisedSize)
|
|
18851
|
+
}))
|
|
19182
18852
|
};
|
|
19183
18853
|
}
|
|
19184
|
-
|
|
19185
|
-
|
|
19186
|
-
|
|
19187
|
-
|
|
19188
|
-
|
|
18854
|
+
async request(query, variables) {
|
|
18855
|
+
try {
|
|
18856
|
+
return await this.client.request(query, variables);
|
|
18857
|
+
} catch (error) {
|
|
18858
|
+
throw new OrderbookRequestError(describeError(error));
|
|
18859
|
+
}
|
|
19189
18860
|
}
|
|
19190
18861
|
};
|
|
18862
|
+
function describeError(error) {
|
|
18863
|
+
const graphqlErrors = error?.response?.errors;
|
|
18864
|
+
if (graphqlErrors?.length) return graphqlErrors.map((e) => e.message).join("; ");
|
|
18865
|
+
return error instanceof Error ? error.message : String(error);
|
|
18866
|
+
}
|
|
18867
|
+
function findBook(books, tokenA, tokenB) {
|
|
18868
|
+
const book = books.find(
|
|
18869
|
+
(b) => b.base === tokenA && b.quote === tokenB || b.base === tokenB && b.quote === tokenA
|
|
18870
|
+
);
|
|
18871
|
+
if (!book) throw new OrderbookRequestError(`no book trades ${tokenA} for ${tokenB}`);
|
|
18872
|
+
return book;
|
|
18873
|
+
}
|
|
18874
|
+
function parseRate(raw) {
|
|
18875
|
+
return {
|
|
18876
|
+
side: raw.side,
|
|
18877
|
+
fillChain: raw.fillChain,
|
|
18878
|
+
rate: BigInt(raw.rate),
|
|
18879
|
+
depthIn: BigInt(raw.depthIn),
|
|
18880
|
+
depthOut: BigInt(raw.depthOut),
|
|
18881
|
+
backingLiquidity: BigInt(raw.backingLiquidity),
|
|
18882
|
+
sourceChains: raw.sourceChains,
|
|
18883
|
+
orderCount: raw.orderCount,
|
|
18884
|
+
solverCount: raw.solverCount
|
|
18885
|
+
};
|
|
18886
|
+
}
|
|
18887
|
+
|
|
18888
|
+
// src/protocols/intents/orderbook/types.ts
|
|
19191
18889
|
var UnsupportedLiquidityAssetError = class extends Error {
|
|
19192
18890
|
constructor(chain, asset) {
|
|
19193
|
-
super(`No configured
|
|
18891
|
+
super(`No configured asset found for ${asset} on ${chain}`);
|
|
19194
18892
|
this.name = "UnsupportedLiquidityAssetError";
|
|
19195
18893
|
}
|
|
19196
18894
|
};
|
|
19197
18895
|
var UnsupportedLiquidityChainError = class extends Error {
|
|
19198
18896
|
constructor(chainId) {
|
|
19199
|
-
super(`No configured
|
|
18897
|
+
super(`No configured chain found for chain ID ${chainId}`);
|
|
19200
18898
|
this.name = "UnsupportedLiquidityChainError";
|
|
19201
18899
|
}
|
|
19202
18900
|
};
|
|
19203
|
-
|
|
19204
|
-
|
|
19205
|
-
throw new InvalidLiquidityIndexerResponseError(`${label} provider count is invalid`);
|
|
19206
|
-
}
|
|
19207
|
-
return { totalLiquidity: formatIndexerAmount(depth, `${label} depth`), providerCount };
|
|
19208
|
-
}
|
|
19209
|
-
function formatIndexerAmount(value, label) {
|
|
19210
|
-
try {
|
|
19211
|
-
const amount = BigInt(value);
|
|
19212
|
-
if (amount < 0n) throw new Error();
|
|
19213
|
-
return formatUnits(amount, INDEXER_FIXED_POINT_DECIMALS);
|
|
19214
|
-
} catch {
|
|
19215
|
-
throw new InvalidLiquidityIndexerResponseError(`${label} is not a non-negative integer`);
|
|
19216
|
-
}
|
|
19217
|
-
}
|
|
19218
|
-
function readIndexerDate(value, label) {
|
|
19219
|
-
const date = new Date(dateStringtoTimestamp(value));
|
|
19220
|
-
if (Number.isNaN(date.getTime())) throw new InvalidLiquidityIndexerResponseError(`${label} is invalid`);
|
|
19221
|
-
return date;
|
|
19222
|
-
}
|
|
19223
|
-
function readIndexedRate(value, lastUpdatedAt, label) {
|
|
19224
|
-
if (value === null) return void 0;
|
|
19225
|
-
try {
|
|
19226
|
-
const scaledRate = BigInt(value);
|
|
19227
|
-
if (scaledRate <= 0n) throw new Error();
|
|
19228
|
-
return {
|
|
19229
|
-
scaledRate,
|
|
19230
|
-
updatedAt: readIndexerDate(lastUpdatedAt, `${label} lastUpdatedAt`)
|
|
19231
|
-
};
|
|
19232
|
-
} catch (error) {
|
|
19233
|
-
if (error instanceof InvalidLiquidityIndexerResponseError) throw error;
|
|
19234
|
-
throw new InvalidLiquidityIndexerResponseError(`${label} is not a positive integer`);
|
|
19235
|
-
}
|
|
19236
|
-
}
|
|
19237
|
-
function validateIndexedPool(indexedPool, expected) {
|
|
19238
|
-
if (indexedPool.id.toLowerCase() !== expected.poolId.toLowerCase() || indexedPool.token0Symbol.toLowerCase() !== expected.token0Symbol.toLowerCase() || indexedPool.token1Symbol.toLowerCase() !== expected.token1Symbol.toLowerCase()) {
|
|
19239
|
-
throw new InvalidLiquidityIndexerResponseError(`pool identity does not match ${expected.poolId}`);
|
|
19240
|
-
}
|
|
19241
|
-
}
|
|
19242
|
-
function resolveQuoteTokenSymbol(tokenInSymbol, tokenOutSymbol, directRate, reverseRate) {
|
|
19243
|
-
const inputIsUsdStable = USD_STABLE_SYMBOLS.has(tokenInSymbol);
|
|
19244
|
-
const outputIsUsdStable = USD_STABLE_SYMBOLS.has(tokenOutSymbol);
|
|
19245
|
-
if (inputIsUsdStable !== outputIsUsdStable) return inputIsUsdStable ? tokenOutSymbol : tokenInSymbol;
|
|
19246
|
-
if (directRate !== void 0) return directRate >= POOL_RATE_SCALE ? tokenOutSymbol : tokenInSymbol;
|
|
19247
|
-
if (reverseRate !== void 0) return reverseRate >= POOL_RATE_SCALE ? tokenInSymbol : tokenOutSymbol;
|
|
19248
|
-
throw new InvalidLiquidityIndexerResponseError("cannot orient an empty rate pair");
|
|
19249
|
-
}
|
|
19250
|
-
function reciprocalRate(rate, label) {
|
|
19251
|
-
const numerator = POOL_RATE_SCALE * POOL_RATE_SCALE;
|
|
19252
|
-
const reciprocal = (numerator + rate - 1n) / rate;
|
|
19253
|
-
if (reciprocal <= 0n) throw new InvalidLiquidityIndexerResponseError(`${label} reciprocal underflowed`);
|
|
19254
|
-
return reciprocal;
|
|
19255
|
-
}
|
|
19256
|
-
|
|
19257
|
-
// src/protocols/intents/quote/types.ts
|
|
19258
|
-
var UnsupportedIntentQuoteStrategyError = class extends Error {
|
|
19259
|
-
constructor(strategy) {
|
|
19260
|
-
super(`Unsupported intent quote strategy: ${strategy}`);
|
|
19261
|
-
this.name = "UnsupportedIntentQuoteStrategyError";
|
|
19262
|
-
}
|
|
19263
|
-
};
|
|
19264
|
-
var UnsupportedIntentQuotePairError = class extends Error {
|
|
19265
|
-
constructor(params) {
|
|
18901
|
+
var OrderbookQuoteNotConvergedError = class extends Error {
|
|
18902
|
+
constructor(route, rounds, lastAmountIn) {
|
|
19266
18903
|
super(
|
|
19267
|
-
`No
|
|
18904
|
+
`No input for ${route.tokenIn} -> ${route.tokenOut} on ${route.sourceChain} -> ${route.destinationChain} delivered the requested output within ${rounds} quotes; the last tried ${lastAmountIn} raw units`
|
|
19268
18905
|
);
|
|
19269
|
-
this.
|
|
19270
|
-
|
|
19271
|
-
|
|
19272
|
-
|
|
19273
|
-
|
|
19274
|
-
|
|
19275
|
-
|
|
19276
|
-
|
|
18906
|
+
this.route = route;
|
|
18907
|
+
this.rounds = rounds;
|
|
18908
|
+
this.lastAmountIn = lastAmountIn;
|
|
18909
|
+
this.name = "OrderbookQuoteNotConvergedError";
|
|
18910
|
+
}
|
|
18911
|
+
route;
|
|
18912
|
+
rounds;
|
|
18913
|
+
lastAmountIn;
|
|
19277
18914
|
};
|
|
19278
|
-
var
|
|
19279
|
-
constructor(
|
|
19280
|
-
super(
|
|
19281
|
-
|
|
19282
|
-
|
|
19283
|
-
|
|
19284
|
-
|
|
19285
|
-
|
|
19286
|
-
const route = params.source && params.destination && params.tokenIn && params.tokenOut ? ` for ${params.tokenIn} -> ${params.tokenOut} on ${params.source} -> ${params.destination}` : "";
|
|
19287
|
-
const side = params.side ? ` ${params.side}` : "";
|
|
19288
|
-
super(`No indexed${side} rate available${route}`);
|
|
19289
|
-
this.name = "IndexedRateUnavailableError";
|
|
19290
|
-
}
|
|
19291
|
-
};
|
|
19292
|
-
var InvalidIndexedRateError = class extends Error {
|
|
19293
|
-
constructor(reason) {
|
|
19294
|
-
super(`Invalid indexed intent rate: ${reason}`);
|
|
19295
|
-
this.name = "InvalidIndexedRateError";
|
|
18915
|
+
var InsufficientOrderbookLiquidityError = class extends Error {
|
|
18916
|
+
constructor(route, maxFillableIn) {
|
|
18917
|
+
super(
|
|
18918
|
+
`The HyperFX orderbook cannot fill ${route.tokenIn} -> ${route.tokenOut} on ${route.sourceChain} -> ${route.destinationChain}; max fillable input is ${maxFillableIn} raw units`
|
|
18919
|
+
);
|
|
18920
|
+
this.route = route;
|
|
18921
|
+
this.maxFillableIn = maxFillableIn;
|
|
18922
|
+
this.name = "InsufficientOrderbookLiquidityError";
|
|
19296
18923
|
}
|
|
18924
|
+
route;
|
|
18925
|
+
maxFillableIn;
|
|
19297
18926
|
};
|
|
19298
|
-
var BPS_DENOMINATOR = 10000n;
|
|
19299
|
-
function validateQuoteParams(params) {
|
|
19300
|
-
const hasAmountIn = params.amountIn !== void 0;
|
|
19301
|
-
const hasAmountOut = params.amountOut !== void 0;
|
|
19302
|
-
if (hasAmountIn === hasAmountOut) throw new Error("Provide exactly one of amountIn or amountOut");
|
|
19303
|
-
if (params.amountIn !== void 0 && params.amountIn <= 0n) throw new Error("amountIn must be greater than zero");
|
|
19304
|
-
if (params.amountOut !== void 0 && params.amountOut <= 0n) throw new Error("amountOut must be greater than zero");
|
|
19305
|
-
if (params.tokenIn.toLowerCase() === params.tokenOut.toLowerCase()) {
|
|
19306
|
-
throw new Error("tokenIn and tokenOut cannot be the same");
|
|
19307
|
-
}
|
|
19308
|
-
}
|
|
19309
|
-
async function readProtocolFeeBps(chainConfigService, source) {
|
|
19310
|
-
const gatewayAddress = chainConfigService.getIntentGatewayAddress(source.stateMachineId);
|
|
19311
|
-
if (!gatewayAddress || gatewayAddress === "0x" || gatewayAddress === zeroAddress) {
|
|
19312
|
-
throw new Error(`IntentGatewayV2 is not configured for chain ${source.stateMachineId}`);
|
|
19313
|
-
}
|
|
19314
|
-
const gatewayParams = await source.client.readContract({
|
|
19315
|
-
address: gatewayAddress,
|
|
19316
|
-
abi: IntentGatewayV2_default.ABI,
|
|
19317
|
-
functionName: "params"
|
|
19318
|
-
});
|
|
19319
|
-
const protocolFeeBps = Array.isArray(gatewayParams) ? BigInt(gatewayParams[4]) : BigInt(gatewayParams.protocolFeeBps ?? 0);
|
|
19320
|
-
if (protocolFeeBps < 0n || protocolFeeBps >= BPS_DENOMINATOR) {
|
|
19321
|
-
throw new Error(`Invalid IntentGateway protocol fee: ${protocolFeeBps} bps`);
|
|
19322
|
-
}
|
|
19323
|
-
return protocolFeeBps;
|
|
19324
|
-
}
|
|
19325
|
-
function deductProtocolFee(amount, protocolFeeBps) {
|
|
19326
|
-
if (protocolFeeBps <= 0n) return amount;
|
|
19327
|
-
const fee = amount * protocolFeeBps / BPS_DENOMINATOR;
|
|
19328
|
-
return amount - fee;
|
|
19329
|
-
}
|
|
19330
|
-
function grossUpForProtocolFee(netAmount, protocolFeeBps) {
|
|
19331
|
-
if (protocolFeeBps <= 0n) return netAmount;
|
|
19332
|
-
if (protocolFeeBps >= BPS_DENOMINATOR) throw new Error("protocolFeeBps must be less than 10,000");
|
|
19333
|
-
return divCeil(netAmount * BPS_DENOMINATOR, BPS_DENOMINATOR - protocolFeeBps);
|
|
19334
|
-
}
|
|
19335
|
-
function divCeil(numerator, denominator) {
|
|
19336
|
-
if (denominator <= 0n) throw new Error("denominator must be greater than zero");
|
|
19337
|
-
return (numerator + denominator - 1n) / denominator;
|
|
19338
|
-
}
|
|
19339
18927
|
|
|
19340
|
-
// src/protocols/intents/
|
|
19341
|
-
var
|
|
19342
|
-
var
|
|
19343
|
-
constructor(
|
|
19344
|
-
this.
|
|
19345
|
-
|
|
19346
|
-
|
|
19347
|
-
|
|
19348
|
-
|
|
18928
|
+
// src/protocols/intents/orderbook/market.ts
|
|
18929
|
+
var MAX_EXACT_OUTPUT_ROUNDS = 16;
|
|
18930
|
+
var OrderbookMarket = class {
|
|
18931
|
+
constructor(configService, orderbook) {
|
|
18932
|
+
this.configService = configService;
|
|
18933
|
+
this.orderbook = orderbook;
|
|
18934
|
+
}
|
|
18935
|
+
configService;
|
|
18936
|
+
orderbook;
|
|
18937
|
+
async quoteIntent(params, sourceChain, destinationChain) {
|
|
19349
18938
|
validateQuoteParams(params);
|
|
19350
|
-
const
|
|
19351
|
-
const
|
|
19352
|
-
const
|
|
19353
|
-
|
|
19354
|
-
|
|
19355
|
-
|
|
19356
|
-
|
|
19357
|
-
|
|
19358
|
-
if (this.baseQuoteClient) return this.baseQuoteClient;
|
|
19359
|
-
const rpcUrl = this.chainConfigService.getRpcUrl(UNISWAP_INTENT_QUOTE_CHAIN);
|
|
19360
|
-
if (!rpcUrl) throw new Error(`RPC URL is not configured for ${UNISWAP_INTENT_QUOTE_CHAIN}`);
|
|
19361
|
-
const baseQuoteClient = createPublicClient({
|
|
19362
|
-
chain: base,
|
|
19363
|
-
transport: http(rpcUrl)
|
|
19364
|
-
});
|
|
19365
|
-
this.baseQuoteClient = baseQuoteClient;
|
|
19366
|
-
return baseQuoteClient;
|
|
19367
|
-
}
|
|
19368
|
-
resolvePoolConfig(params, source, destination) {
|
|
19369
|
-
const override = params.uniswapV4?.poolKey;
|
|
19370
|
-
if (override) {
|
|
19371
|
-
const poolKey = normalizePoolKey(override);
|
|
19372
|
-
const tokenInForQuote = getAddress(override.currencyIn ?? params.tokenIn);
|
|
19373
|
-
if (tokenInForQuote !== poolKey.currency0 && tokenInForQuote !== poolKey.currency1) {
|
|
19374
|
-
throw new Error(
|
|
19375
|
-
`Input currency ${tokenInForQuote} is not part of the override pool (${poolKey.currency0}, ${poolKey.currency1}). For cross-chain quotes pass uniswapV4.poolKey.currencyIn with the Base-side input currency address.`
|
|
19376
|
-
);
|
|
19377
|
-
}
|
|
19378
|
-
return {
|
|
19379
|
-
poolKey,
|
|
19380
|
-
quoterAddress: this.resolveQuoterAddress(UNISWAP_INTENT_QUOTE_CHAIN, override.quoterAddress),
|
|
19381
|
-
tokenInForQuote
|
|
19382
|
-
};
|
|
19383
|
-
}
|
|
19384
|
-
const poolConfig = this.resolveConfiguredPool(params, source, destination, UNISWAP_INTENT_QUOTE_CHAIN);
|
|
19385
|
-
if (poolConfig) return poolConfig;
|
|
19386
|
-
throw new UnsupportedIntentQuotePairError({
|
|
19387
|
-
source,
|
|
19388
|
-
destination,
|
|
19389
|
-
tokenIn: params.tokenIn,
|
|
19390
|
-
tokenOut: params.tokenOut
|
|
19391
|
-
});
|
|
19392
|
-
}
|
|
19393
|
-
resolveConfiguredPool(params, sourceChain, destinationChain, quoteChain) {
|
|
19394
|
-
for (const pool of this.chainConfigService.getUniswapV4PoolConfigs(quoteChain)) {
|
|
19395
|
-
const resolvedPool = this.resolveConfiguredPoolTokens(quoteChain, pool);
|
|
19396
|
-
if (!resolvedPool) continue;
|
|
19397
|
-
const tokenInForQuote = this.matchPoolToken(params.tokenIn, sourceChain, resolvedPool);
|
|
19398
|
-
const tokenOutForQuote = this.matchPoolToken(params.tokenOut, destinationChain, resolvedPool);
|
|
19399
|
-
if (!tokenInForQuote || !tokenOutForQuote || tokenInForQuote.symbol === tokenOutForQuote.symbol) continue;
|
|
19400
|
-
const { currency0, currency1 } = sortCurrencies(resolvedPool[0].address, resolvedPool[1].address);
|
|
19401
|
-
return {
|
|
19402
|
-
poolKey: {
|
|
19403
|
-
currency0,
|
|
19404
|
-
currency1,
|
|
19405
|
-
fee: pool.fee,
|
|
19406
|
-
tickSpacing: pool.tickSpacing,
|
|
19407
|
-
hooks: getAddress(pool.hooks ?? zeroAddress)
|
|
19408
|
-
},
|
|
19409
|
-
quoterAddress: this.resolveQuoterAddress(quoteChain),
|
|
19410
|
-
tokenInForQuote: tokenInForQuote.address
|
|
19411
|
-
};
|
|
19412
|
-
}
|
|
19413
|
-
return null;
|
|
19414
|
-
}
|
|
19415
|
-
resolveQuoterAddress(chain, override) {
|
|
19416
|
-
const address = override ?? this.chainConfigService.getUniswapV4QuoterAddress(chain);
|
|
19417
|
-
if (!address || address === "0x" || address === zeroAddress) {
|
|
19418
|
-
throw new Error(`Uniswap V4 quoter is not configured for chain ${chain}`);
|
|
18939
|
+
const tokenIn = this.assetByAddress(sourceChain, params.tokenIn);
|
|
18940
|
+
const tokenOut = this.assetByAddress(destinationChain, params.tokenOut);
|
|
18941
|
+
const route = toRoute(tokenIn, tokenOut);
|
|
18942
|
+
if (params.amountIn !== void 0) {
|
|
18943
|
+
const quote2 = await this.orderbook().quote(route, toOrderbookAmount(params.amountIn, tokenIn.decimals));
|
|
18944
|
+
const amountOut2 = quote2.fillable ? fromOrderbookAmount(quote2.amountOut, tokenOut.decimals) : 0n;
|
|
18945
|
+
if (amountOut2 === 0n) throw this.insufficient(route, quote2.maxFillableIn, tokenIn);
|
|
18946
|
+
return buildQuote("EXACT_INPUT", params.amountIn, amountOut2, quote2, tokenIn, tokenOut);
|
|
19419
18947
|
}
|
|
19420
|
-
|
|
19421
|
-
|
|
19422
|
-
|
|
19423
|
-
|
|
19424
|
-
|
|
19425
|
-
return first && second ? [first, second] : null;
|
|
19426
|
-
}
|
|
19427
|
-
resolveConfiguredPoolToken(chain, symbol) {
|
|
19428
|
-
const address = this.chainConfigService.getAssetAddress(chain, symbol);
|
|
19429
|
-
if (!address || address === "0x") return null;
|
|
19430
|
-
return { symbol, address: getAddress(address) };
|
|
19431
|
-
}
|
|
19432
|
-
matchPoolToken(tokenAddress, orderChain, poolTokens) {
|
|
19433
|
-
const addressMatch = poolTokens.find(
|
|
19434
|
-
(poolToken) => poolToken.address.toLowerCase() === tokenAddress.toLowerCase()
|
|
19435
|
-
);
|
|
19436
|
-
if (addressMatch) return addressMatch;
|
|
19437
|
-
const metadata = this.chainConfigService.getAssetMetadataByAddress(orderChain, tokenAddress);
|
|
19438
|
-
if (!metadata) return null;
|
|
19439
|
-
return poolTokens.find((poolToken) => poolToken.symbol === metadata.symbol) ?? null;
|
|
19440
|
-
}
|
|
19441
|
-
async quoteExactInput(args) {
|
|
19442
|
-
const amountIn = args.params.amountIn;
|
|
19443
|
-
if (amountIn === void 0) throw new Error("amountIn is required for an exact-input quote");
|
|
19444
|
-
const swapAmountIn = deductProtocolFee(amountIn, args.protocolFeeBps);
|
|
19445
|
-
const amountOut = await this.readV4QuoteExactInput(args.client, args.poolConfig, swapAmountIn);
|
|
19446
|
-
return {
|
|
19447
|
-
strategy: "uniswap_v4",
|
|
19448
|
-
tradeType: "EXACT_INPUT",
|
|
19449
|
-
amountIn,
|
|
18948
|
+
const amountOut = params.amountOut;
|
|
18949
|
+
const quote = await this.quoteExactOutput(route, toOrderbookAmount(amountOut, tokenOut.decimals), tokenIn);
|
|
18950
|
+
return buildQuote(
|
|
18951
|
+
"EXACT_OUTPUT",
|
|
18952
|
+
fromOrderbookAmount(quote.amountIn, tokenIn.decimals),
|
|
19450
18953
|
amountOut,
|
|
19451
|
-
|
|
19452
|
-
|
|
19453
|
-
|
|
19454
|
-
|
|
19455
|
-
protocolFeeBps: args.protocolFeeBps
|
|
19456
|
-
}
|
|
19457
|
-
};
|
|
18954
|
+
quote,
|
|
18955
|
+
tokenIn,
|
|
18956
|
+
tokenOut
|
|
18957
|
+
);
|
|
19458
18958
|
}
|
|
19459
|
-
async
|
|
19460
|
-
const
|
|
19461
|
-
|
|
19462
|
-
const
|
|
19463
|
-
const
|
|
18959
|
+
async availableLiquidity(params, sourceChain, destinationChain) {
|
|
18960
|
+
const tokenIn = this.assetByAddress(sourceChain, params.tokenIn);
|
|
18961
|
+
const tokenOut = this.assetByAddress(destinationChain, params.tokenOut);
|
|
18962
|
+
const liquidity = await this.orderbook().routeLiquidity(toRoute(tokenIn, tokenOut));
|
|
18963
|
+
const [base3, quote] = liquidity.side === "BID" ? [tokenIn, tokenOut] : [tokenOut, tokenIn];
|
|
19464
18964
|
return {
|
|
19465
|
-
|
|
19466
|
-
|
|
19467
|
-
|
|
19468
|
-
|
|
19469
|
-
|
|
19470
|
-
|
|
19471
|
-
|
|
19472
|
-
|
|
19473
|
-
|
|
19474
|
-
|
|
18965
|
+
sourceChain: tokenIn.chain,
|
|
18966
|
+
destinationChain: tokenOut.chain,
|
|
18967
|
+
tokenInSymbol: tokenIn.symbol,
|
|
18968
|
+
tokenOutSymbol: tokenOut.symbol,
|
|
18969
|
+
tokenAddress: tokenOut.address,
|
|
18970
|
+
route: liquidity.route,
|
|
18971
|
+
side: liquidity.side,
|
|
18972
|
+
baseTokenSymbol: base3.symbol,
|
|
18973
|
+
quoteTokenSymbol: quote.symbol,
|
|
18974
|
+
bestRate: formatOptional(liquidity.bestRate),
|
|
18975
|
+
availableLiquidity: format(liquidity.availableLiquidity),
|
|
18976
|
+
depthIn: format(liquidity.depthIn),
|
|
18977
|
+
depthOut: format(liquidity.depthOut),
|
|
18978
|
+
maxFillableIn: format(liquidity.maxFillableIn),
|
|
18979
|
+
orderCount: liquidity.orderCount,
|
|
18980
|
+
solverCount: liquidity.solverCount
|
|
19475
18981
|
};
|
|
19476
18982
|
}
|
|
19477
|
-
async
|
|
19478
|
-
const
|
|
19479
|
-
|
|
19480
|
-
|
|
19481
|
-
|
|
19482
|
-
|
|
19483
|
-
|
|
19484
|
-
|
|
19485
|
-
exactAmount: amountIn,
|
|
19486
|
-
hookData: "0x"
|
|
19487
|
-
}
|
|
19488
|
-
]
|
|
19489
|
-
});
|
|
19490
|
-
const response = await client.call({ to: poolConfig.quoterAddress, data });
|
|
19491
|
-
if (!response.data || response.data === "0x") {
|
|
19492
|
-
throw new Error(`Uniswap V4 quoter at ${poolConfig.quoterAddress} returned no data`);
|
|
19493
|
-
}
|
|
19494
|
-
const [amountOut] = decodeFunctionResult({
|
|
19495
|
-
abi: UNISWAP_V4_QUOTER_ABI,
|
|
19496
|
-
functionName: "quoteExactInputSingle",
|
|
19497
|
-
data: response.data
|
|
19498
|
-
});
|
|
19499
|
-
return amountOut;
|
|
19500
|
-
}
|
|
19501
|
-
async readV4QuoteExactOutput(client, poolConfig, amountOut) {
|
|
19502
|
-
const data = encodeFunctionData({
|
|
19503
|
-
abi: UNISWAP_V4_QUOTER_ABI,
|
|
19504
|
-
functionName: "quoteExactOutputSingle",
|
|
19505
|
-
args: [
|
|
19506
|
-
{
|
|
19507
|
-
poolKey: poolConfig.poolKey,
|
|
19508
|
-
zeroForOne: getZeroForOne(poolConfig.tokenInForQuote, poolConfig.poolKey),
|
|
19509
|
-
exactAmount: amountOut,
|
|
19510
|
-
hookData: "0x"
|
|
19511
|
-
}
|
|
19512
|
-
]
|
|
18983
|
+
async buyAndSellRates(params) {
|
|
18984
|
+
const tokenIn = this.assetBySymbol(params.sourceChain, params.tokenInSymbol);
|
|
18985
|
+
const tokenOut = this.assetBySymbol(params.destinationChain, params.tokenOutSymbol);
|
|
18986
|
+
const { book, bid, ask } = await this.orderbook().topOfBook({
|
|
18987
|
+
tokenA: tokenIn.symbol,
|
|
18988
|
+
tokenB: tokenOut.symbol,
|
|
18989
|
+
fillChain: tokenOut.chain,
|
|
18990
|
+
sourceChain: tokenIn.chain
|
|
19513
18991
|
});
|
|
19514
|
-
const
|
|
19515
|
-
|
|
19516
|
-
|
|
19517
|
-
|
|
19518
|
-
const [amountIn] = decodeFunctionResult({
|
|
19519
|
-
abi: UNISWAP_V4_QUOTER_ABI,
|
|
19520
|
-
functionName: "quoteExactOutputSingle",
|
|
19521
|
-
data: response.data
|
|
19522
|
-
});
|
|
19523
|
-
return amountIn;
|
|
19524
|
-
}
|
|
19525
|
-
};
|
|
19526
|
-
function normalizePoolKey(poolKey) {
|
|
19527
|
-
return {
|
|
19528
|
-
currency0: getAddress(poolKey.currency0),
|
|
19529
|
-
currency1: getAddress(poolKey.currency1),
|
|
19530
|
-
fee: poolKey.fee,
|
|
19531
|
-
tickSpacing: poolKey.tickSpacing,
|
|
19532
|
-
hooks: getAddress(poolKey.hooks)
|
|
19533
|
-
};
|
|
19534
|
-
}
|
|
19535
|
-
function sortCurrencies(tokenIn, tokenOut) {
|
|
19536
|
-
const input = getAddress(tokenIn);
|
|
19537
|
-
const output = getAddress(tokenOut);
|
|
19538
|
-
return BigInt(input) < BigInt(output) ? { currency0: input, currency1: output } : { currency0: output, currency1: input };
|
|
19539
|
-
}
|
|
19540
|
-
function getZeroForOne(tokenIn, poolKey) {
|
|
19541
|
-
return getAddress(tokenIn).toLowerCase() === getAddress(poolKey.currency0).toLowerCase();
|
|
19542
|
-
}
|
|
19543
|
-
|
|
19544
|
-
// src/protocols/intents/quote/phantomSnapshot.ts
|
|
19545
|
-
var PHANTOM_INTENT_QUOTE_CHAIN = "EVM-8453" /* BASE_MAINNET */;
|
|
19546
|
-
var BASE_SNAPSHOT_ASSET_BY_ORDER_ASSET = {
|
|
19547
|
-
USDC: "USDC",
|
|
19548
|
-
USDT: "USDC",
|
|
19549
|
-
cNGN: "cNGN"
|
|
19550
|
-
};
|
|
19551
|
-
var SUPPORTED_BASE_SNAPSHOT_PAIRS = /* @__PURE__ */ new Set(["USDC:cNGN", "cNGN:USDC"]);
|
|
19552
|
-
var PhantomSnapshotIntentQuoteStrategy = class {
|
|
19553
|
-
constructor(chainConfigService, getQueryClient) {
|
|
19554
|
-
this.chainConfigService = chainConfigService;
|
|
19555
|
-
this.getQueryClient = getQueryClient;
|
|
19556
|
-
this.pairResolver = new PhantomSnapshotPairResolver(chainConfigService);
|
|
19557
|
-
}
|
|
19558
|
-
chainConfigService;
|
|
19559
|
-
getQueryClient;
|
|
19560
|
-
pairResolver;
|
|
19561
|
-
async quote(params, source, destination) {
|
|
19562
|
-
validateQuoteParams(params);
|
|
19563
|
-
const pair = this.pairResolver.resolve(params, source.stateMachineId, destination.stateMachineId);
|
|
19564
|
-
if (!pair) {
|
|
19565
|
-
throw new UnsupportedIntentQuotePairError({
|
|
19566
|
-
source: source.stateMachineId,
|
|
19567
|
-
destination: destination.stateMachineId,
|
|
19568
|
-
tokenIn: params.tokenIn,
|
|
19569
|
-
tokenOut: params.tokenOut,
|
|
19570
|
-
quoteSource: "Phantom snapshot pair"
|
|
19571
|
-
});
|
|
19572
|
-
}
|
|
19573
|
-
const queryClient = this.getQueryClient();
|
|
19574
|
-
const [protocolFeeBps, snapshot] = await Promise.all([
|
|
19575
|
-
readProtocolFeeBps(this.chainConfigService, source),
|
|
19576
|
-
_queryLatestPhantomOrderPriceSnapshot({
|
|
19577
|
-
tokenA: pair.tokenA,
|
|
19578
|
-
tokenB: pair.tokenB,
|
|
19579
|
-
queryClient
|
|
19580
|
-
})
|
|
19581
|
-
]);
|
|
19582
|
-
if (!snapshot) throw new PhantomSnapshotUnavailableError(pair.tokenA, pair.tokenB);
|
|
19583
|
-
this.validateSnapshot(snapshot);
|
|
19584
|
-
return this.quoteSnapshot(params, protocolFeeBps, snapshot);
|
|
19585
|
-
}
|
|
19586
|
-
quoteSnapshot(params, protocolFeeBps, snapshot) {
|
|
19587
|
-
if (params.amountIn !== void 0) {
|
|
19588
|
-
const netAmountIn2 = deductProtocolFee(params.amountIn, protocolFeeBps);
|
|
19589
|
-
const amountOut = netAmountIn2 * snapshot.medianPrice / snapshot.standardAmount;
|
|
19590
|
-
if (amountOut <= 0n) {
|
|
19591
|
-
throw new InvalidPhantomSnapshotError(snapshot.commitment, "quote rounds down to zero output");
|
|
19592
|
-
}
|
|
19593
|
-
return this.buildResult("EXACT_INPUT", params.amountIn, amountOut, protocolFeeBps, snapshot);
|
|
19594
|
-
}
|
|
19595
|
-
if (params.amountOut === void 0) throw new Error("Quote amount is missing after validation");
|
|
19596
|
-
const netAmountIn = divCeil(params.amountOut * snapshot.standardAmount, snapshot.medianPrice);
|
|
19597
|
-
const amountIn = grossUpForProtocolFee(netAmountIn, protocolFeeBps);
|
|
19598
|
-
return this.buildResult("EXACT_OUTPUT", amountIn, params.amountOut, protocolFeeBps, snapshot);
|
|
19599
|
-
}
|
|
19600
|
-
buildResult(tradeType, amountIn, amountOut, protocolFeeBps, snapshot) {
|
|
18992
|
+
const bidRate = bid?.rate ?? null;
|
|
18993
|
+
const askRate = ask?.rate ?? null;
|
|
18994
|
+
const mid = bidRate !== null && askRate !== null ? (bidRate + askRate) / 2n : null;
|
|
18995
|
+
const spread = bidRate !== null && askRate !== null && askRate >= bidRate ? askRate - bidRate : null;
|
|
19601
18996
|
return {
|
|
19602
|
-
|
|
19603
|
-
|
|
19604
|
-
|
|
19605
|
-
|
|
19606
|
-
|
|
19607
|
-
|
|
19608
|
-
|
|
19609
|
-
|
|
19610
|
-
|
|
19611
|
-
standardAmount: snapshot.standardAmount,
|
|
19612
|
-
medianPrice: snapshot.medianPrice,
|
|
19613
|
-
lowestPrice: snapshot.lowestPrice,
|
|
19614
|
-
highestPrice: snapshot.highestPrice,
|
|
19615
|
-
blockNumber: snapshot.blockNumber,
|
|
19616
|
-
snapshotTime: snapshot.snapshotTime,
|
|
19617
|
-
bidCount: snapshot.bidCount,
|
|
19618
|
-
protocolFeeBps
|
|
19619
|
-
}
|
|
18997
|
+
baseTokenSymbol: book.base,
|
|
18998
|
+
quoteTokenSymbol: book.quote,
|
|
18999
|
+
sourceChain: tokenIn.chain,
|
|
19000
|
+
destinationChain: tokenOut.chain,
|
|
19001
|
+
bid: formatOptional(bidRate),
|
|
19002
|
+
ask: formatOptional(askRate),
|
|
19003
|
+
mid: formatOptional(mid),
|
|
19004
|
+
spread: formatOptional(spread),
|
|
19005
|
+
spreadBps: spread !== null && mid ? Number(spread * 1000000n / mid) / 100 : null
|
|
19620
19006
|
};
|
|
19621
19007
|
}
|
|
19622
|
-
|
|
19623
|
-
|
|
19624
|
-
|
|
19625
|
-
|
|
19626
|
-
|
|
19627
|
-
|
|
19628
|
-
|
|
19629
|
-
|
|
19630
|
-
|
|
19631
|
-
|
|
19632
|
-
|
|
19633
|
-
|
|
19634
|
-
|
|
19635
|
-
|
|
19636
|
-
|
|
19637
|
-
|
|
19638
|
-
|
|
19639
|
-
|
|
19640
|
-
|
|
19641
|
-
|
|
19642
|
-
|
|
19643
|
-
|
|
19644
|
-
|
|
19645
|
-
|
|
19646
|
-
|
|
19647
|
-
}
|
|
19648
|
-
resolveBaseSnapshotToken(chain, tokenAddress) {
|
|
19649
|
-
const orderAsset = this.chainConfigService.getAssetMetadataByAddress(chain, tokenAddress)?.symbol;
|
|
19650
|
-
if (!orderAsset) return;
|
|
19651
|
-
const snapshotAsset = BASE_SNAPSHOT_ASSET_BY_ORDER_ASSET[orderAsset];
|
|
19652
|
-
if (!snapshotAsset) return;
|
|
19653
|
-
const address = this.chainConfigService.getAssetAddress(PHANTOM_INTENT_QUOTE_CHAIN, snapshotAsset);
|
|
19654
|
-
if (!isConfiguredAddress(address)) return;
|
|
19655
|
-
return { symbol: snapshotAsset, address };
|
|
19656
|
-
}
|
|
19657
|
-
};
|
|
19658
|
-
function isSupportedSnapshotPair(tokenA, tokenB) {
|
|
19659
|
-
return SUPPORTED_BASE_SNAPSHOT_PAIRS.has(`${tokenA}:${tokenB}`);
|
|
19660
|
-
}
|
|
19661
|
-
function isConfiguredAddress(address) {
|
|
19662
|
-
return Boolean(address && address !== "0x" && !/^0x0{40}$/i.test(address));
|
|
19663
|
-
}
|
|
19664
|
-
var INDEXED_RATE_DECIMALS = 18;
|
|
19665
|
-
var INDEXED_RATE_SCALE = 10n ** BigInt(INDEXED_RATE_DECIMALS);
|
|
19666
|
-
var IndexedRateIntentQuoteStrategy = class {
|
|
19667
|
-
constructor(chainConfigService, getQueryClient) {
|
|
19668
|
-
this.chainConfigService = chainConfigService;
|
|
19669
|
-
this.getQueryClient = getQueryClient;
|
|
19670
|
-
}
|
|
19671
|
-
chainConfigService;
|
|
19672
|
-
getQueryClient;
|
|
19673
|
-
async quote(params, source, destination) {
|
|
19674
|
-
validateQuoteParams(params);
|
|
19675
|
-
const sourceConfig = getConfigByStateMachineId(source.stateMachineId);
|
|
19676
|
-
const destinationConfig = getConfigByStateMachineId(destination.stateMachineId);
|
|
19677
|
-
if (!sourceConfig) throw new UnsupportedLiquidityChainError(source.stateMachineId);
|
|
19678
|
-
if (!destinationConfig) throw new UnsupportedLiquidityChainError(destination.stateMachineId);
|
|
19679
|
-
const tokenIn = this.resolveAsset(sourceConfig.stateMachineId, params.tokenIn);
|
|
19680
|
-
const tokenOut = this.resolveAsset(destinationConfig.stateMachineId, params.tokenOut);
|
|
19681
|
-
const [protocolFeeBps, rates] = await Promise.all([
|
|
19682
|
-
readProtocolFeeBps(this.chainConfigService, source),
|
|
19683
|
-
new LiquidityEngine(this.getQueryClient()).getBuyAndSellRates({
|
|
19684
|
-
sourceChain: sourceConfig.stateMachineId,
|
|
19685
|
-
destinationChain: destinationConfig.stateMachineId,
|
|
19686
|
-
tokenInSymbol: tokenIn.symbol,
|
|
19687
|
-
tokenOutSymbol: tokenOut.symbol
|
|
19688
|
-
})
|
|
19689
|
-
]);
|
|
19690
|
-
if (!rates) {
|
|
19691
|
-
throw new IndexedRateUnavailableError({
|
|
19692
|
-
source: sourceConfig.stateMachineId,
|
|
19693
|
-
destination: destinationConfig.stateMachineId,
|
|
19694
|
-
tokenIn: tokenIn.symbol,
|
|
19695
|
-
tokenOut: tokenOut.symbol
|
|
19696
|
-
});
|
|
19697
|
-
}
|
|
19698
|
-
const selectedRate = selectIndexedRate(rates, tokenIn.symbol, tokenOut.symbol);
|
|
19699
|
-
return quoteWithIndexedRate(params, tokenIn, tokenOut, selectedRate, rates, protocolFeeBps);
|
|
19008
|
+
/**
|
|
19009
|
+
* The orderbook only quotes an input amount, so an output is priced by
|
|
19010
|
+
* guessing the input from the best rate and raising it at each clearing
|
|
19011
|
+
* price until the quote delivers `targetOut`.
|
|
19012
|
+
*/
|
|
19013
|
+
async quoteExactOutput(route, targetOut, tokenIn) {
|
|
19014
|
+
const orderbook = this.orderbook();
|
|
19015
|
+
const liquidity = await orderbook.routeLiquidity(route);
|
|
19016
|
+
if (liquidity.bestRate === null) throw this.insufficient(route, 0n, tokenIn);
|
|
19017
|
+
const inputUnit = toOrderbookAmount(1n, tokenIn.decimals);
|
|
19018
|
+
let amountIn = roundUpTo(requiredInput(liquidity.side, targetOut, liquidity.bestRate), inputUnit);
|
|
19019
|
+
let lastAmountIn = amountIn;
|
|
19020
|
+
for (let round = 0; round < MAX_EXACT_OUTPUT_ROUNDS; round++) {
|
|
19021
|
+
if (amountIn > liquidity.maxFillableIn) throw this.insufficient(route, liquidity.maxFillableIn, tokenIn);
|
|
19022
|
+
const quote = await orderbook.quote(route, amountIn);
|
|
19023
|
+
if (quote.fillable && quote.amountOut >= targetOut) return quote;
|
|
19024
|
+
lastAmountIn = amountIn;
|
|
19025
|
+
const next = quote.rate === null ? amountIn : roundUpTo(requiredInput(quote.side, targetOut, quote.rate), inputUnit);
|
|
19026
|
+
amountIn = next > amountIn ? next : amountIn + inputUnit;
|
|
19027
|
+
}
|
|
19028
|
+
throw new OrderbookQuoteNotConvergedError(
|
|
19029
|
+
route,
|
|
19030
|
+
MAX_EXACT_OUTPUT_ROUNDS,
|
|
19031
|
+
fromOrderbookAmount(lastAmountIn, tokenIn.decimals)
|
|
19032
|
+
);
|
|
19700
19033
|
}
|
|
19701
|
-
|
|
19702
|
-
|
|
19703
|
-
if (!asset) throw new UnsupportedLiquidityAssetError(chain, address);
|
|
19704
|
-
const { decimals } = asset;
|
|
19705
|
-
if (decimals === void 0 || !Number.isSafeInteger(decimals) || decimals < 0) {
|
|
19706
|
-
throw new InvalidIndexedRateError(`decimals are not configured for ${asset.symbol} on ${chain}`);
|
|
19707
|
-
}
|
|
19708
|
-
return { ...asset, decimals };
|
|
19034
|
+
insufficient(route, maxFillableIn, tokenIn) {
|
|
19035
|
+
return new InsufficientOrderbookLiquidityError(route, fromOrderbookAmount(maxFillableIn, tokenIn.decimals));
|
|
19709
19036
|
}
|
|
19710
|
-
|
|
19711
|
-
|
|
19712
|
-
|
|
19713
|
-
|
|
19714
|
-
|
|
19715
|
-
|
|
19716
|
-
rates.buyRateUpdatedAt,
|
|
19717
|
-
rates,
|
|
19718
|
-
tokenInSymbol,
|
|
19719
|
-
tokenOutSymbol
|
|
19037
|
+
assetByAddress(chain, address) {
|
|
19038
|
+
const resolvedChain = resolveChain(chain);
|
|
19039
|
+
return withDecimals(
|
|
19040
|
+
resolvedChain,
|
|
19041
|
+
address,
|
|
19042
|
+
this.configService.getAssetMetadataByAddress(resolvedChain, address)
|
|
19720
19043
|
);
|
|
19721
19044
|
}
|
|
19722
|
-
|
|
19723
|
-
|
|
19724
|
-
|
|
19725
|
-
rates.sellRate,
|
|
19726
|
-
rates.sellRateUpdatedAt,
|
|
19727
|
-
rates,
|
|
19728
|
-
tokenInSymbol,
|
|
19729
|
-
tokenOutSymbol
|
|
19730
|
-
);
|
|
19045
|
+
assetBySymbol(chain, symbol) {
|
|
19046
|
+
const resolvedChain = resolveChain(chain);
|
|
19047
|
+
return withDecimals(resolvedChain, symbol, this.configService.getAssetMetadataBySymbol(resolvedChain, symbol));
|
|
19731
19048
|
}
|
|
19732
|
-
|
|
19733
|
-
|
|
19734
|
-
);
|
|
19049
|
+
};
|
|
19050
|
+
function resolveChain(chain) {
|
|
19051
|
+
const stateMachineId = getConfigByStateMachineId(chain)?.stateMachineId;
|
|
19052
|
+
if (!stateMachineId) throw new UnsupportedLiquidityChainError(chain);
|
|
19053
|
+
return stateMachineId;
|
|
19735
19054
|
}
|
|
19736
|
-
function
|
|
19737
|
-
if (!
|
|
19738
|
-
|
|
19739
|
-
|
|
19740
|
-
|
|
19741
|
-
tokenIn: tokenInSymbol,
|
|
19742
|
-
tokenOut: tokenOutSymbol,
|
|
19743
|
-
side
|
|
19744
|
-
});
|
|
19745
|
-
}
|
|
19746
|
-
try {
|
|
19747
|
-
const scaledRate = parseUnits(rate, INDEXED_RATE_DECIMALS);
|
|
19748
|
-
if (scaledRate <= 0n || Number.isNaN(updatedAt.getTime())) throw new Error();
|
|
19749
|
-
return { side, rate, scaledRate, updatedAt };
|
|
19750
|
-
} catch {
|
|
19751
|
-
throw new InvalidIndexedRateError(`${side} rate or timestamp is invalid`);
|
|
19055
|
+
function withDecimals(chain, asset, metadata) {
|
|
19056
|
+
if (!metadata) throw new UnsupportedLiquidityAssetError(chain, asset);
|
|
19057
|
+
const { decimals } = metadata;
|
|
19058
|
+
if (decimals === void 0 || !Number.isSafeInteger(decimals) || decimals < 0 || decimals > ORDERBOOK_DECIMALS) {
|
|
19059
|
+
throw new UnsupportedLiquidityAssetError(chain, `${metadata.symbol} (decimals are not configured)`);
|
|
19752
19060
|
}
|
|
19061
|
+
return { chain, symbol: metadata.symbol, address: metadata.address, decimals };
|
|
19062
|
+
}
|
|
19063
|
+
function validateQuoteParams(params) {
|
|
19064
|
+
const hasAmountIn = params.amountIn !== void 0;
|
|
19065
|
+
const hasAmountOut = params.amountOut !== void 0;
|
|
19066
|
+
if (hasAmountIn === hasAmountOut) throw new Error("Provide exactly one of amountIn or amountOut");
|
|
19067
|
+
if (params.amountIn !== void 0 && params.amountIn <= 0n) throw new Error("amountIn must be greater than zero");
|
|
19068
|
+
if (params.amountOut !== void 0 && params.amountOut <= 0n) throw new Error("amountOut must be greater than zero");
|
|
19753
19069
|
}
|
|
19754
|
-
function
|
|
19755
|
-
|
|
19756
|
-
|
|
19757
|
-
|
|
19758
|
-
|
|
19759
|
-
|
|
19760
|
-
|
|
19761
|
-
|
|
19762
|
-
|
|
19763
|
-
|
|
19764
|
-
const netAmountIn = selectedRate.side === "buy" ? divCeil(params.amountOut * inputUnit * INDEXED_RATE_SCALE, selectedRate.scaledRate * outputUnit) : divCeil(params.amountOut * inputUnit * selectedRate.scaledRate, outputUnit * INDEXED_RATE_SCALE);
|
|
19765
|
-
const amountIn = grossUpForProtocolFee(netAmountIn, protocolFeeBps);
|
|
19766
|
-
return buildResult("EXACT_OUTPUT", amountIn, params.amountOut, selectedRate, rates, protocolFeeBps);
|
|
19070
|
+
function toRoute(tokenIn, tokenOut) {
|
|
19071
|
+
return {
|
|
19072
|
+
tokenIn: tokenIn.symbol,
|
|
19073
|
+
tokenOut: tokenOut.symbol,
|
|
19074
|
+
sourceChain: tokenIn.chain,
|
|
19075
|
+
destinationChain: tokenOut.chain
|
|
19076
|
+
};
|
|
19077
|
+
}
|
|
19078
|
+
function requiredInput(side, amountOut, rate) {
|
|
19079
|
+
return side === "BID" ? divCeil(amountOut * ORDERBOOK_SCALE, rate) : divCeil(amountOut * rate, ORDERBOOK_SCALE);
|
|
19767
19080
|
}
|
|
19768
|
-
function
|
|
19081
|
+
function buildQuote(tradeType, amountIn, amountOut, quote, tokenIn, tokenOut) {
|
|
19082
|
+
if (quote.rate === null) throw new OrderbookRequestError("the orderbook served a fillable quote with no rate");
|
|
19083
|
+
const [base3, quoteToken] = quote.side === "BID" ? [tokenIn, tokenOut] : [tokenOut, tokenIn];
|
|
19769
19084
|
return {
|
|
19770
|
-
strategy: "indexed_rates",
|
|
19771
19085
|
tradeType,
|
|
19772
19086
|
amountIn,
|
|
19773
19087
|
amountOut,
|
|
19774
19088
|
quoteMetadata: {
|
|
19775
|
-
sourceChain:
|
|
19776
|
-
destinationChain:
|
|
19777
|
-
|
|
19778
|
-
|
|
19779
|
-
|
|
19780
|
-
|
|
19781
|
-
|
|
19782
|
-
|
|
19089
|
+
sourceChain: tokenIn.chain,
|
|
19090
|
+
destinationChain: tokenOut.chain,
|
|
19091
|
+
route: quote.route,
|
|
19092
|
+
side: quote.side,
|
|
19093
|
+
baseTokenSymbol: base3.symbol,
|
|
19094
|
+
quoteTokenSymbol: quoteToken.symbol,
|
|
19095
|
+
rate: format(quote.rate),
|
|
19096
|
+
maxFillableIn: fromOrderbookAmount(quote.maxFillableIn, tokenIn.decimals),
|
|
19097
|
+
orderCount: quote.fills.length
|
|
19783
19098
|
}
|
|
19784
19099
|
};
|
|
19785
19100
|
}
|
|
19101
|
+
function toOrderbookAmount(amount, decimals) {
|
|
19102
|
+
return amount * 10n ** BigInt(ORDERBOOK_DECIMALS - decimals);
|
|
19103
|
+
}
|
|
19104
|
+
function fromOrderbookAmount(amount, decimals) {
|
|
19105
|
+
return amount / 10n ** BigInt(ORDERBOOK_DECIMALS - decimals);
|
|
19106
|
+
}
|
|
19107
|
+
function roundUpTo(amount, unit) {
|
|
19108
|
+
return divCeil(amount, unit) * unit;
|
|
19109
|
+
}
|
|
19110
|
+
function divCeil(numerator, denominator) {
|
|
19111
|
+
return (numerator + denominator - 1n) / denominator;
|
|
19112
|
+
}
|
|
19113
|
+
function format(amount) {
|
|
19114
|
+
return formatUnits(amount, ORDERBOOK_DECIMALS);
|
|
19115
|
+
}
|
|
19116
|
+
function formatOptional(amount) {
|
|
19117
|
+
return amount === null ? null : format(amount);
|
|
19118
|
+
}
|
|
19786
19119
|
|
|
19787
19120
|
// src/protocols/intents/IntentGateway.ts
|
|
19788
19121
|
var ORDER_FEE_GAS_PRICE_BUMP_POLICY = {
|
|
@@ -19822,8 +19155,10 @@ var IntentGateway = class _IntentGateway {
|
|
|
19822
19155
|
bidManager;
|
|
19823
19156
|
/** Estimates gas costs for filling an order and converts them to fee-token amounts. */
|
|
19824
19157
|
gasEstimator;
|
|
19825
|
-
/**
|
|
19826
|
-
|
|
19158
|
+
/** The HyperFX orderbook quotes, liquidity and rates are read from. */
|
|
19159
|
+
orderbook;
|
|
19160
|
+
/** Prices intents, liquidity and rates from {@link orderbook}. */
|
|
19161
|
+
market;
|
|
19827
19162
|
/**
|
|
19828
19163
|
* Private constructor — use {@link IntentGateway.create} instead.
|
|
19829
19164
|
*
|
|
@@ -19867,17 +19202,8 @@ var IntentGateway = class _IntentGateway {
|
|
|
19867
19202
|
this.bidManager = bidManager;
|
|
19868
19203
|
this.gasEstimator = gasEstimator;
|
|
19869
19204
|
this._crypto = crypto;
|
|
19870
|
-
this.
|
|
19871
|
-
|
|
19872
|
-
dest.configService,
|
|
19873
|
-
() => this.requireIndexer().queryClient
|
|
19874
|
-
),
|
|
19875
|
-
phantom_snapshot: new PhantomSnapshotIntentQuoteStrategy(
|
|
19876
|
-
dest.configService,
|
|
19877
|
-
() => this.requireIndexer().queryClient
|
|
19878
|
-
),
|
|
19879
|
-
uniswap_v4: new UniswapV4IntentQuoteStrategy(dest.configService)
|
|
19880
|
-
};
|
|
19205
|
+
this.orderbook = new HyperFxOrderbook(orderbookUrlFor(dest.config.stateMachineId));
|
|
19206
|
+
this.market = new OrderbookMarket(dest.configService, () => this.orderbook);
|
|
19881
19207
|
}
|
|
19882
19208
|
/**
|
|
19883
19209
|
* Creates an initialized IntentGateway instance.
|
|
@@ -19923,89 +19249,66 @@ var IntentGateway = class _IntentGateway {
|
|
|
19923
19249
|
}
|
|
19924
19250
|
}
|
|
19925
19251
|
/**
|
|
19926
|
-
*
|
|
19252
|
+
* Points quotes, liquidity and rate reads at a HyperFX orderbook other than
|
|
19253
|
+
* the destination chain's network deployment ({@link ORDERBOOK_URLS}).
|
|
19254
|
+
* Returns `this` for chaining.
|
|
19255
|
+
*
|
|
19256
|
+
* @param orderbook - The orderbook's GraphQL URL, or a configured client.
|
|
19257
|
+
*/
|
|
19258
|
+
withOrderbook(orderbook) {
|
|
19259
|
+
this.orderbook = typeof orderbook === "string" ? new HyperFxOrderbook(orderbook) : orderbook;
|
|
19260
|
+
return this;
|
|
19261
|
+
}
|
|
19262
|
+
/**
|
|
19263
|
+
* Quotes an intent between this gateway's source and destination chains from
|
|
19264
|
+
* the HyperFX orderbook. Provide exactly one of `amountIn` or `amountOut`, in
|
|
19265
|
+
* raw token units.
|
|
19927
19266
|
*
|
|
19928
|
-
*
|
|
19929
|
-
*
|
|
19930
|
-
*
|
|
19931
|
-
*
|
|
19267
|
+
* An exact-input quote is the orderbook's clearing price for `amountIn`,
|
|
19268
|
+
* which may combine several solvers' orders. An exact-output quote finds the
|
|
19269
|
+
* smallest input whose clearing price delivers `amountOut`. A cross-chain
|
|
19270
|
+
* route only counts orders whose solvers accept the source chain.
|
|
19932
19271
|
*
|
|
19933
|
-
* The
|
|
19934
|
-
*
|
|
19935
|
-
* `amountIn`/`amountOut` already account for the gateway's protocol fee
|
|
19936
|
-
* (`quoteMetadata.protocolFeeBps`), which the gateway deducts from order inputs.
|
|
19272
|
+
* The orderbook's rates already carry the gateway protocol fee, so the
|
|
19273
|
+
* returned amounts can be placed as the order's inputs and outputs directly.
|
|
19937
19274
|
*
|
|
19938
|
-
* @
|
|
19939
|
-
* @
|
|
19940
|
-
* @throws {UnsupportedIntentQuoteStrategyError} For unknown strategies.
|
|
19941
|
-
* @throws {UnsupportedIntentQuotePairError} When the selected strategy does not support the pair.
|
|
19942
|
-
* @throws {IndexedRateUnavailableError} When the requested direction has no indexed rate.
|
|
19275
|
+
* @throws {InsufficientOrderbookLiquidityError} When the route cannot fill the amount.
|
|
19276
|
+
* @throws {OrderbookRequestError} When the orderbook is unreachable or trades no book for the pair.
|
|
19943
19277
|
*/
|
|
19944
19278
|
async quoteIntent(params) {
|
|
19945
|
-
|
|
19946
|
-
const destination = { stateMachineId: this.dest.config.stateMachineId, client: this.dest.client };
|
|
19947
|
-
const strategy = params.strategy ?? "indexed_rates";
|
|
19948
|
-
const handler = this.quoteStrategies[strategy];
|
|
19949
|
-
if (!handler) throw new UnsupportedIntentQuoteStrategyError(strategy);
|
|
19950
|
-
return handler.quote({ ...params, strategy }, source, destination);
|
|
19279
|
+
return this.market.quoteIntent(params, this.source.config.stateMachineId, this.dest.config.stateMachineId);
|
|
19951
19280
|
}
|
|
19952
19281
|
/**
|
|
19953
|
-
* Returns
|
|
19282
|
+
* Returns the orderbook liquidity serving a swap of `tokenIn` on the source
|
|
19283
|
+
* chain for `tokenOut` on the destination chain: the best rate, true and
|
|
19284
|
+
* virtual depth, and the largest input the route can fill.
|
|
19954
19285
|
*
|
|
19955
|
-
*
|
|
19956
|
-
* from the indexer's pair-centric liquidity entities. The SDK does not decide
|
|
19957
|
-
* whether unrestricted bidders cover the source chain. Amounts reflect the
|
|
19958
|
-
* latest rolling sample; they are not reservations or fill guarantees.
|
|
19959
|
-
*
|
|
19960
|
-
* Requires a prior call to {@link withQueryClient}.
|
|
19286
|
+
* Amounts reflect the live book; they are not reservations or fill guarantees.
|
|
19961
19287
|
*/
|
|
19962
19288
|
async queryAvailableLiquidity(params) {
|
|
19963
|
-
|
|
19964
|
-
|
|
19965
|
-
|
|
19966
|
-
|
|
19967
|
-
if (!destinationStateMachineId) throw new UnsupportedLiquidityChainError(this.dest.config.stateMachineId);
|
|
19968
|
-
const sourceToken = this.source.configService.getAssetMetadataByAddress(sourceStateMachineId, params.tokenIn);
|
|
19969
|
-
const destinationToken = this.dest.configService.getAssetMetadataByAddress(
|
|
19970
|
-
destinationStateMachineId,
|
|
19971
|
-
params.tokenOut
|
|
19289
|
+
return this.market.availableLiquidity(
|
|
19290
|
+
params,
|
|
19291
|
+
this.source.config.stateMachineId,
|
|
19292
|
+
this.dest.config.stateMachineId
|
|
19972
19293
|
);
|
|
19973
|
-
if (!sourceToken) throw new UnsupportedLiquidityAssetError(sourceStateMachineId, params.tokenIn);
|
|
19974
|
-
if (!destinationToken) throw new UnsupportedLiquidityAssetError(destinationStateMachineId, params.tokenOut);
|
|
19975
|
-
return new LiquidityEngine(queryClient).getAvailableLiquidity({
|
|
19976
|
-
source: {
|
|
19977
|
-
chain: sourceStateMachineId,
|
|
19978
|
-
...sourceToken
|
|
19979
|
-
},
|
|
19980
|
-
destination: {
|
|
19981
|
-
chain: destinationStateMachineId,
|
|
19982
|
-
...destinationToken
|
|
19983
|
-
}
|
|
19984
|
-
});
|
|
19985
19294
|
}
|
|
19986
19295
|
/**
|
|
19987
|
-
* Returns
|
|
19988
|
-
* units
|
|
19989
|
-
*
|
|
19296
|
+
* Returns the orderbook's best bid and ask for a pair, with the mid and
|
|
19297
|
+
* spread, in quote-token units per one base token. Only orders filled on the
|
|
19298
|
+
* destination chain that accept swaps from the source chain are counted.
|
|
19299
|
+
* Symbols are matched case-insensitively; chain IDs resolve configured token
|
|
19300
|
+
* deployments.
|
|
19990
19301
|
*/
|
|
19991
19302
|
async queryBuyAndSellRates(params) {
|
|
19992
|
-
const { queryClient } = this.requireIndexer();
|
|
19993
19303
|
const sourceChain = chainConfigs[params.sourceChainId]?.stateMachineId;
|
|
19994
19304
|
const destinationChain = chainConfigs[params.destinationChainId]?.stateMachineId;
|
|
19995
19305
|
if (!sourceChain) throw new UnsupportedLiquidityChainError(params.sourceChainId);
|
|
19996
19306
|
if (!destinationChain) throw new UnsupportedLiquidityChainError(params.destinationChainId);
|
|
19997
|
-
|
|
19998
|
-
const destinationToken = this.dest.configService.getAssetMetadataBySymbol(
|
|
19999
|
-
destinationChain,
|
|
20000
|
-
params.tokenOutSymbol
|
|
20001
|
-
);
|
|
20002
|
-
if (!sourceToken) throw new UnsupportedLiquidityAssetError(sourceChain, params.tokenInSymbol);
|
|
20003
|
-
if (!destinationToken) throw new UnsupportedLiquidityAssetError(destinationChain, params.tokenOutSymbol);
|
|
20004
|
-
return new LiquidityEngine(queryClient).getBuyAndSellRates({
|
|
19307
|
+
return this.market.buyAndSellRates({
|
|
20005
19308
|
sourceChain,
|
|
20006
19309
|
destinationChain,
|
|
20007
|
-
tokenInSymbol:
|
|
20008
|
-
tokenOutSymbol:
|
|
19310
|
+
tokenInSymbol: params.tokenInSymbol,
|
|
19311
|
+
tokenOutSymbol: params.tokenOutSymbol
|
|
20009
19312
|
});
|
|
20010
19313
|
}
|
|
20011
19314
|
/**
|
|
@@ -20256,6 +19559,8 @@ var IntentGateway = class _IntentGateway {
|
|
|
20256
19559
|
/**
|
|
20257
19560
|
* Returns both the native token cost and the relayer fee for cancelling an
|
|
20258
19561
|
* order. Use `relayerFee` to approve the ERC-20 spend before submitting.
|
|
19562
|
+
* Same-chain orders use the direct local route for either `from` option and
|
|
19563
|
+
* return `{ nativeValue: 0n, relayerFee: 0n }`.
|
|
20259
19564
|
*
|
|
20260
19565
|
* Delegates to {@link OrderCanceller.quoteCancelOrder}.
|
|
20261
19566
|
*
|
|
@@ -20279,9 +19584,17 @@ var IntentGateway = class _IntentGateway {
|
|
|
20279
19584
|
*
|
|
20280
19585
|
* Delegates to {@link OrderCanceller.cancelOrder}.
|
|
20281
19586
|
*
|
|
19587
|
+
* Same-chain orders always use the direct source-gateway route. The order
|
|
19588
|
+
* user may call through the deadline; any account may call strictly after
|
|
19589
|
+
* it, pays the transaction gas, and cannot change the refund beneficiary.
|
|
19590
|
+
* The SDK yields unsigned transaction fields and accepts either the caller's
|
|
19591
|
+
* signed raw transaction or its already-broadcast transaction hash.
|
|
19592
|
+
*
|
|
20282
19593
|
* @param order - The order to cancel.
|
|
20283
|
-
* @param indexerClient - Indexer client used for ISMP request
|
|
20284
|
-
*
|
|
19594
|
+
* @param indexerClient - Indexer client used for cross-chain ISMP request
|
|
19595
|
+
* status streaming; the same-chain route does not access it.
|
|
19596
|
+
* @param options - Choose the cross-chain initiation side. Defaults to source;
|
|
19597
|
+
* ignored for routing when source and destination are the same chain.
|
|
20285
19598
|
* @yields {@link CancelEvent} objects describing each cancellation stage.
|
|
20286
19599
|
*/
|
|
20287
19600
|
async *cancelOrder(order, indexerClient, options = {}) {
|
|
@@ -20411,7 +19724,7 @@ var IntentGateway = class _IntentGateway {
|
|
|
20411
19724
|
if (estimate.totalGasCostWei === 0n || estimate.totalGasInFeeToken === 0n) {
|
|
20412
19725
|
throw new Error("Gas estimation failed");
|
|
20413
19726
|
}
|
|
20414
|
-
const fees = isSameChain ? estimate.totalGasInFeeToken * 2n : (estimate.totalGasInFeeToken + estimate.relayerFeeInSourceFeeToken) * 105n / 100n;
|
|
19727
|
+
const fees = isSameChain ? estimate.totalGasInFeeToken * 2n : ((estimate.totalGasInFeeToken + estimate.relayerFeeInSourceFeeToken) * 105n + 99n) / 100n;
|
|
20415
19728
|
const { address: feeToken } = await this.source.getFeeTokenWithDecimals();
|
|
20416
19729
|
return {
|
|
20417
19730
|
fees,
|
|
@@ -20444,17 +19757,27 @@ var IntentGateway = class _IntentGateway {
|
|
|
20444
19757
|
return this._crypto.decodeERC7821Execute(callData);
|
|
20445
19758
|
}
|
|
20446
19759
|
/**
|
|
20447
|
-
* Checks whether an order
|
|
19760
|
+
* Checks whether an order is finalized on the destination chain.
|
|
20448
19761
|
*
|
|
20449
19762
|
* Delegates to {@link OrderStatusChecker.isOrderFilled}.
|
|
20450
19763
|
*
|
|
20451
19764
|
* @param order - The order to check.
|
|
20452
|
-
* @returns `true`
|
|
20453
|
-
*
|
|
19765
|
+
* @returns `true` once a completing fill or a destination-side cancellation
|
|
19766
|
+
* has finalized the order; `false` while it is open or only partly filled.
|
|
20454
19767
|
*/
|
|
20455
19768
|
async isOrderFilled(order) {
|
|
20456
19769
|
return this.orderStatusChecker.isOrderFilled(order);
|
|
20457
19770
|
}
|
|
19771
|
+
/**
|
|
19772
|
+
* Output credited to the order so far, one entry per leg.
|
|
19773
|
+
*
|
|
19774
|
+
* Delegates to {@link OrderStatusChecker.getFillProgress}.
|
|
19775
|
+
*
|
|
19776
|
+
* @param order - The order to check.
|
|
19777
|
+
*/
|
|
19778
|
+
async getFillProgress(order) {
|
|
19779
|
+
return this.orderStatusChecker.getFillProgress(order);
|
|
19780
|
+
}
|
|
20458
19781
|
/**
|
|
20459
19782
|
* Checks whether all escrowed inputs for an order have been refunded on the
|
|
20460
19783
|
* source chain.
|
|
@@ -20462,8 +19785,8 @@ var IntentGateway = class _IntentGateway {
|
|
|
20462
19785
|
* Delegates to {@link OrderStatusChecker.isOrderRefunded}.
|
|
20463
19786
|
*
|
|
20464
19787
|
* @param order - The order to check.
|
|
20465
|
-
* @returns `true` if every input
|
|
20466
|
-
* in the `_orders` mapping on the source chain.
|
|
19788
|
+
* @returns `true` if every input's escrowed amount has been zeroed out
|
|
19789
|
+
* in the per-leg `_orders` mapping on the source chain.
|
|
20467
19790
|
*/
|
|
20468
19791
|
async isOrderRefunded(order) {
|
|
20469
19792
|
return this.orderStatusChecker.isOrderRefunded(order);
|
|
@@ -20500,9 +19823,7 @@ var IntentGateway = class _IntentGateway {
|
|
|
20500
19823
|
}
|
|
20501
19824
|
requireIndexer() {
|
|
20502
19825
|
if (!this.indexer) {
|
|
20503
|
-
throw new Error(
|
|
20504
|
-
"IntentGateway: call withQueryClient(queryClient) before using indexer-backed methods or Phantom quotes"
|
|
20505
|
-
);
|
|
19826
|
+
throw new Error("IntentGateway: call withQueryClient(queryClient) before using indexer-backed methods");
|
|
20506
19827
|
}
|
|
20507
19828
|
return this.indexer;
|
|
20508
19829
|
}
|
|
@@ -20525,78 +19846,127 @@ var IntentGateway = class _IntentGateway {
|
|
|
20525
19846
|
const { queryClient, pollInterval, logger } = this.requireIndexer();
|
|
20526
19847
|
const streamLogger = logger.withTag("[orderStatusStream]");
|
|
20527
19848
|
const TERMINAL = ["FILLED", "REDEEMED", "REFUNDED"];
|
|
19849
|
+
const latestOrderStatus = (order2) => {
|
|
19850
|
+
const latest = order2.statuses[order2.statuses.length - 1];
|
|
19851
|
+
if (latest.status === "CANCELLED") {
|
|
19852
|
+
for (let i = order2.statuses.length - 1; i >= 0; i--) {
|
|
19853
|
+
if (TERMINAL.includes(order2.statuses[i].status)) return order2.statuses[i];
|
|
19854
|
+
}
|
|
19855
|
+
}
|
|
19856
|
+
return latest;
|
|
19857
|
+
};
|
|
20528
19858
|
let order;
|
|
20529
19859
|
while (!order) {
|
|
20530
19860
|
await sleep(pollInterval);
|
|
20531
19861
|
order = await _queryOrderInternal({ commitmentHash: commitment, queryClient, logger });
|
|
20532
19862
|
}
|
|
20533
19863
|
streamLogger.trace("`Order` found");
|
|
20534
|
-
|
|
19864
|
+
let latestStatus = latestOrderStatus(order);
|
|
20535
19865
|
yield { status: latestStatus.status, metadata: latestStatus.metadata };
|
|
20536
19866
|
if (TERMINAL.includes(latestStatus.status)) return;
|
|
20537
19867
|
while (true) {
|
|
20538
19868
|
await sleep(pollInterval);
|
|
20539
19869
|
const updatedOrder = await _queryOrderInternal({ commitmentHash: commitment, queryClient, logger });
|
|
20540
19870
|
if (!updatedOrder) continue;
|
|
20541
|
-
const newLatestStatus = updatedOrder
|
|
19871
|
+
const newLatestStatus = latestOrderStatus(updatedOrder);
|
|
20542
19872
|
if (newLatestStatus.status !== latestStatus.status) {
|
|
19873
|
+
latestStatus = newLatestStatus;
|
|
20543
19874
|
yield { status: newLatestStatus.status, metadata: newLatestStatus.metadata };
|
|
20544
19875
|
if (TERMINAL.includes(newLatestStatus.status)) return;
|
|
20545
19876
|
}
|
|
20546
19877
|
}
|
|
20547
19878
|
}
|
|
20548
19879
|
};
|
|
20549
|
-
|
|
20550
|
-
|
|
20551
|
-
|
|
20552
|
-
|
|
20553
|
-
}
|
|
20554
|
-
return f;
|
|
19880
|
+
|
|
19881
|
+
// src/protocols/intents/liquidity-pool.ts
|
|
19882
|
+
function sortPoolSymbols(symbolA, symbolB) {
|
|
19883
|
+
return symbolA.toLowerCase() <= symbolB.toLowerCase() ? [symbolA, symbolB] : [symbolB, symbolA];
|
|
20555
19884
|
}
|
|
20556
|
-
|
|
20557
|
-
|
|
20558
|
-
|
|
20559
|
-
|
|
20560
|
-
|
|
20561
|
-
|
|
20562
|
-
|
|
20563
|
-
}
|
|
20564
|
-
|
|
20565
|
-
|
|
20566
|
-
|
|
20567
|
-
|
|
20568
|
-
|
|
20569
|
-
|
|
20570
|
-
|
|
20571
|
-
|
|
20572
|
-
|
|
20573
|
-
|
|
20574
|
-
|
|
20575
|
-
|
|
20576
|
-
|
|
20577
|
-
body: JSON.stringify(payload)
|
|
20578
|
-
}),
|
|
20579
|
-
timeout
|
|
20580
|
-
]);
|
|
20581
|
-
const body = await response.json();
|
|
20582
|
-
if (body?.error) {
|
|
20583
|
-
lastErr = new Error(`rpc error: ${JSON.stringify(body.error).slice(0, 200)}`);
|
|
20584
|
-
continue;
|
|
20585
|
-
}
|
|
20586
|
-
return body;
|
|
20587
|
-
} catch (err) {
|
|
20588
|
-
lastErr = err;
|
|
20589
|
-
} finally {
|
|
20590
|
-
if (timer) clearTimeout(timer);
|
|
20591
|
-
}
|
|
20592
|
-
}
|
|
20593
|
-
throw new PhantomRpcError(`RPC call failed after 4 attempts: ${url}`, lastErr);
|
|
19885
|
+
function poolSlug(symbolA, symbolB) {
|
|
19886
|
+
return sortPoolSymbols(symbolA, symbolB).join("-");
|
|
19887
|
+
}
|
|
19888
|
+
|
|
19889
|
+
// src/protocols/intents/rateFill.ts
|
|
19890
|
+
function ceilDiv(numerator, denominator) {
|
|
19891
|
+
return numerator === 0n ? 0n : (numerator - 1n) / denominator + 1n;
|
|
19892
|
+
}
|
|
19893
|
+
function previewRateFill(escrow, required, filled, take, offered) {
|
|
19894
|
+
if (escrow <= 0n || required <= 0n || take <= 0n || offered <= 0n) {
|
|
19895
|
+
throw new Error("RateFillInvalidAmount");
|
|
19896
|
+
}
|
|
19897
|
+
if (filled < 0n || filled >= required) throw new Error("RateFillNoProgress");
|
|
19898
|
+
if (ceilDiv(take * required, escrow) > offered) throw new Error("RateBelowOrder");
|
|
19899
|
+
const uncappedCredit = take * required / escrow;
|
|
19900
|
+
const credit = uncappedCredit < required - filled ? uncappedCredit : required - filled;
|
|
19901
|
+
const release = escrow * (filled + credit) / required - escrow * filled / required;
|
|
19902
|
+
if (credit === 0n || release === 0n) throw new Error("RateFillNoProgress");
|
|
19903
|
+
const ratePayment = ceilDiv(offered * release, take);
|
|
19904
|
+
const delivered = ratePayment > credit ? ratePayment : credit;
|
|
19905
|
+
return { credit, release, delivered, surplus: delivered - credit };
|
|
20594
19906
|
}
|
|
20595
|
-
var FILL_ORDER_ABI = IntentGatewayV2_default.ABI;
|
|
20596
19907
|
var DECLARATION_V1 = 1;
|
|
20597
19908
|
var DECLARATION_V2 = 2;
|
|
19909
|
+
var PAYMASTER_ADDRESS_BYTES = 20;
|
|
19910
|
+
var PAYMASTER_GAS_LIMIT_BYTES = 16;
|
|
19911
|
+
var PAYMASTER_DATA_OFFSET = PAYMASTER_ADDRESS_BYTES + 2 * PAYMASTER_GAS_LIMIT_BYTES;
|
|
19912
|
+
var SIMPLEX_MODE_PERMIT2 = 2;
|
|
19913
|
+
var PERMIT2_DATA_BYTES = 1 + 20 + 32 + 32 + 32 + 1 + 32 + 32;
|
|
19914
|
+
var PERMIT2_SPONSORSHIP_BYTES = PAYMASTER_DATA_OFFSET + PERMIT2_DATA_BYTES;
|
|
20598
19915
|
var MAX_DECLARED_ENTRIES = 255;
|
|
20599
19916
|
var MAX_TOKEN_ID_BYTES = 32;
|
|
19917
|
+
function utf8Encode(text) {
|
|
19918
|
+
const bytes = [];
|
|
19919
|
+
for (const char of text) {
|
|
19920
|
+
const codePoint = char.codePointAt(0);
|
|
19921
|
+
if (codePoint < 128) bytes.push(codePoint);
|
|
19922
|
+
else if (codePoint < 2048) bytes.push(192 | codePoint >> 6, 128 | codePoint & 63);
|
|
19923
|
+
else if (codePoint < 65536) {
|
|
19924
|
+
bytes.push(224 | codePoint >> 12, 128 | codePoint >> 6 & 63, 128 | codePoint & 63);
|
|
19925
|
+
} else {
|
|
19926
|
+
bytes.push(
|
|
19927
|
+
240 | codePoint >> 18,
|
|
19928
|
+
128 | codePoint >> 12 & 63,
|
|
19929
|
+
128 | codePoint >> 6 & 63,
|
|
19930
|
+
128 | codePoint & 63
|
|
19931
|
+
);
|
|
19932
|
+
}
|
|
19933
|
+
}
|
|
19934
|
+
return bytes;
|
|
19935
|
+
}
|
|
19936
|
+
function utf8Decode(bytes) {
|
|
19937
|
+
let text = "";
|
|
19938
|
+
for (let offset = 0; offset < bytes.length; ) {
|
|
19939
|
+
const lead = bytes[offset];
|
|
19940
|
+
let codePoint;
|
|
19941
|
+
let continuations;
|
|
19942
|
+
if (lead < 128) {
|
|
19943
|
+
codePoint = lead;
|
|
19944
|
+
continuations = 0;
|
|
19945
|
+
} else if ((lead & 224) === 192) {
|
|
19946
|
+
codePoint = lead & 31;
|
|
19947
|
+
continuations = 1;
|
|
19948
|
+
} else if ((lead & 240) === 224) {
|
|
19949
|
+
codePoint = lead & 15;
|
|
19950
|
+
continuations = 2;
|
|
19951
|
+
} else if ((lead & 248) === 240) {
|
|
19952
|
+
codePoint = lead & 7;
|
|
19953
|
+
continuations = 3;
|
|
19954
|
+
} else {
|
|
19955
|
+
return null;
|
|
19956
|
+
}
|
|
19957
|
+
if (offset + continuations >= bytes.length) return null;
|
|
19958
|
+
for (let index = 1; index <= continuations; index++) {
|
|
19959
|
+
const byte = bytes[offset + index];
|
|
19960
|
+
if ((byte & 192) !== 128) return null;
|
|
19961
|
+
codePoint = codePoint << 6 | byte & 63;
|
|
19962
|
+
}
|
|
19963
|
+
const overlong = continuations === 1 && codePoint < 128 || continuations === 2 && codePoint < 2048 || continuations === 3 && codePoint < 65536;
|
|
19964
|
+
if (overlong || codePoint > 1114111 || codePoint >= 55296 && codePoint <= 57343) return null;
|
|
19965
|
+
text += String.fromCodePoint(codePoint);
|
|
19966
|
+
offset += continuations + 1;
|
|
19967
|
+
}
|
|
19968
|
+
return text;
|
|
19969
|
+
}
|
|
20600
19970
|
function tokenIdToBytes(tokenId) {
|
|
20601
19971
|
if (tokenId < 0n) throw new Error(`Uniswap V4 tokenId cannot be negative: ${tokenId}`);
|
|
20602
19972
|
const bytes = [];
|
|
@@ -20619,7 +19989,7 @@ function encodePhantomBidDeclaration(declaration) {
|
|
|
20619
19989
|
const version = positions.length > 0 ? DECLARATION_V2 : DECLARATION_V1;
|
|
20620
19990
|
const bytes = [version, chains2.length];
|
|
20621
19991
|
for (const chain of chains2) {
|
|
20622
|
-
const encoded =
|
|
19992
|
+
const encoded = utf8Encode(chain);
|
|
20623
19993
|
if (encoded.length === 0 || encoded.length > 255) {
|
|
20624
19994
|
throw new Error(`Invalid state machine id in source chain declaration: ${chain}`);
|
|
20625
19995
|
}
|
|
@@ -20637,82 +20007,100 @@ function encodePhantomBidDeclaration(declaration) {
|
|
|
20637
20007
|
}
|
|
20638
20008
|
return u8aToHex(new Uint8Array(bytes));
|
|
20639
20009
|
}
|
|
20640
|
-
function
|
|
20641
|
-
|
|
20642
|
-
|
|
20643
|
-
|
|
20644
|
-
if (bytes.length < 2) return absent;
|
|
20645
|
-
const version = bytes[0];
|
|
20646
|
-
if (version !== DECLARATION_V1 && version !== DECLARATION_V2) return absent;
|
|
20010
|
+
function parseDeclaration(bytes, start) {
|
|
20011
|
+
if (bytes.length - start < 2) return null;
|
|
20012
|
+
const version = bytes[start];
|
|
20013
|
+
if (version !== DECLARATION_V1 && version !== DECLARATION_V2) return null;
|
|
20647
20014
|
const chains2 = [];
|
|
20648
|
-
let offset = 2;
|
|
20649
|
-
for (let entry = 0; entry < bytes[1]; entry++) {
|
|
20650
|
-
if (offset >= bytes.length) return
|
|
20015
|
+
let offset = start + 2;
|
|
20016
|
+
for (let entry = 0; entry < bytes[start + 1]; entry++) {
|
|
20017
|
+
if (offset >= bytes.length) return null;
|
|
20651
20018
|
const length = bytes[offset];
|
|
20652
20019
|
offset += 1;
|
|
20653
|
-
if (length === 0 || offset + length > bytes.length) return
|
|
20654
|
-
|
|
20020
|
+
if (length === 0 || offset + length > bytes.length) return null;
|
|
20021
|
+
const chain = utf8Decode(bytes.subarray(offset, offset + length));
|
|
20022
|
+
if (chain === null) return null;
|
|
20023
|
+
chains2.push(chain);
|
|
20655
20024
|
offset += length;
|
|
20656
20025
|
}
|
|
20657
20026
|
const positions = [];
|
|
20658
20027
|
if (version === DECLARATION_V2) {
|
|
20659
|
-
if (offset >= bytes.length) return
|
|
20028
|
+
if (offset >= bytes.length) return null;
|
|
20660
20029
|
const count = bytes[offset];
|
|
20661
20030
|
offset += 1;
|
|
20662
20031
|
for (let entry = 0; entry < count; entry++) {
|
|
20663
|
-
if (offset >= bytes.length) return
|
|
20032
|
+
if (offset >= bytes.length) return null;
|
|
20664
20033
|
const length = bytes[offset];
|
|
20665
20034
|
offset += 1;
|
|
20666
|
-
if (length === 0 || length > MAX_TOKEN_ID_BYTES || offset + length > bytes.length) return
|
|
20667
|
-
|
|
20668
|
-
for (const byte of bytes.subarray(offset, offset + length)) tokenId = tokenId << 8n | BigInt(byte);
|
|
20669
|
-
positions.push(tokenId);
|
|
20035
|
+
if (length === 0 || length > MAX_TOKEN_ID_BYTES || offset + length > bytes.length) return null;
|
|
20036
|
+
positions.push(bytesToBigInt3(bytes.subarray(offset, offset + length)));
|
|
20670
20037
|
offset += length;
|
|
20671
20038
|
}
|
|
20672
20039
|
}
|
|
20673
|
-
if (offset !== bytes.length) return
|
|
20040
|
+
if (offset !== bytes.length) return null;
|
|
20674
20041
|
return { acceptedSources: chains2, uniswapV4Positions: positions };
|
|
20675
20042
|
}
|
|
20676
|
-
function
|
|
20677
|
-
|
|
20043
|
+
function bytesToBigInt3(bytes) {
|
|
20044
|
+
let value = 0n;
|
|
20045
|
+
for (const byte of bytes) value = value << 8n | BigInt(byte);
|
|
20046
|
+
return value;
|
|
20678
20047
|
}
|
|
20679
|
-
function
|
|
20680
|
-
return
|
|
20048
|
+
function bytesToAddress(bytes) {
|
|
20049
|
+
return u8aToHex(bytes);
|
|
20681
20050
|
}
|
|
20682
|
-
|
|
20683
|
-
|
|
20684
|
-
return amount * (10000n - bps) / 10000n;
|
|
20051
|
+
function hasPermit2Sponsorship(bytes) {
|
|
20052
|
+
return bytes.length >= PERMIT2_SPONSORSHIP_BYTES && bytes[PAYMASTER_DATA_OFFSET] === SIMPLEX_MODE_PERMIT2;
|
|
20685
20053
|
}
|
|
20686
|
-
function
|
|
20687
|
-
|
|
20054
|
+
function parseSponsorship(bytes) {
|
|
20055
|
+
let offset = 0;
|
|
20056
|
+
const take = (length) => {
|
|
20057
|
+
const slice = bytes.subarray(offset, offset + length);
|
|
20058
|
+
offset += length;
|
|
20059
|
+
return slice;
|
|
20060
|
+
};
|
|
20061
|
+
const paymaster = bytesToAddress(take(PAYMASTER_ADDRESS_BYTES));
|
|
20062
|
+
take(2 * PAYMASTER_GAS_LIMIT_BYTES);
|
|
20063
|
+
take(1);
|
|
20064
|
+
const token = bytesToAddress(take(20));
|
|
20065
|
+
const permitAmount = bytesToBigInt3(take(32));
|
|
20066
|
+
const nonce = bytesToBigInt3(take(32));
|
|
20067
|
+
const deadline = bytesToBigInt3(take(32));
|
|
20068
|
+
return { paymaster, token, permitAmount, nonce, deadline };
|
|
20688
20069
|
}
|
|
20689
|
-
var
|
|
20690
|
-
|
|
20691
|
-
|
|
20692
|
-
|
|
20693
|
-
const
|
|
20694
|
-
|
|
20695
|
-
|
|
20696
|
-
|
|
20697
|
-
|
|
20698
|
-
|
|
20699
|
-
|
|
20700
|
-
|
|
20701
|
-
|
|
20702
|
-
|
|
20703
|
-
|
|
20704
|
-
|
|
20705
|
-
|
|
20706
|
-
|
|
20070
|
+
var absentDeclaration = () => ({ acceptedSources: null, uniswapV4Positions: [] });
|
|
20071
|
+
function decodePhantomBidPaymasterAndData(paymasterAndData) {
|
|
20072
|
+
const none = { mode: "none", declaration: absentDeclaration(), sponsorship: null };
|
|
20073
|
+
if (!paymasterAndData || !isHex$1(paymasterAndData)) return none;
|
|
20074
|
+
const bytes = hexToU8a(paymasterAndData);
|
|
20075
|
+
const bare = parseDeclaration(bytes, 0);
|
|
20076
|
+
if (bare) return { mode: "declaration", declaration: bare, sponsorship: null };
|
|
20077
|
+
if (!hasPermit2Sponsorship(bytes)) return none;
|
|
20078
|
+
const sponsorship = parseSponsorship(bytes);
|
|
20079
|
+
const tail = bytes.length > PERMIT2_SPONSORSHIP_BYTES ? parseDeclaration(bytes, PERMIT2_SPONSORSHIP_BYTES) : null;
|
|
20080
|
+
return { mode: "permit2", declaration: tail ?? absentDeclaration(), sponsorship };
|
|
20081
|
+
}
|
|
20082
|
+
function decodePhantomBidDeclaration(paymasterAndData) {
|
|
20083
|
+
return decodePhantomBidPaymasterAndData(paymasterAndData).declaration;
|
|
20084
|
+
}
|
|
20085
|
+
function encodePhantomBidPaymasterAndData(bid) {
|
|
20086
|
+
const declaration = encodePhantomBidDeclaration(bid);
|
|
20087
|
+
const sponsorship = bid.sponsorship;
|
|
20088
|
+
if (!sponsorship || sponsorship === "0x") return declaration;
|
|
20089
|
+
if (!isHex$1(sponsorship)) throw new Error("Phantom bid sponsorship is not hex");
|
|
20090
|
+
const bytes = hexToU8a(sponsorship);
|
|
20091
|
+
if (bytes.length !== PERMIT2_SPONSORSHIP_BYTES || !hasPermit2Sponsorship(bytes)) {
|
|
20092
|
+
throw new Error(
|
|
20093
|
+
`Phantom bid sponsorship must be a ${PERMIT2_SPONSORSHIP_BYTES}-byte Permit2-mode paymasterAndData, got ${bytes.length} bytes`
|
|
20094
|
+
);
|
|
20707
20095
|
}
|
|
20708
|
-
return
|
|
20096
|
+
return `${sponsorship}${declaration.slice(2)}`;
|
|
20097
|
+
}
|
|
20098
|
+
function encodeAcceptedSourceChains(chains2) {
|
|
20099
|
+
return encodePhantomBidDeclaration({ acceptedSourceChains: chains2 });
|
|
20709
20100
|
}
|
|
20710
|
-
function
|
|
20711
|
-
return
|
|
20101
|
+
function decodeAcceptedSourceChains(paymasterAndData) {
|
|
20102
|
+
return decodePhantomBidDeclaration(paymasterAndData).acceptedSources;
|
|
20712
20103
|
}
|
|
20713
|
-
FILL_ORDER_ABI.find(
|
|
20714
|
-
(item) => item?.type === "function" && item?.name === "fillOrder"
|
|
20715
|
-
)?.inputs?.[0];
|
|
20716
20104
|
var TokenGateway = class {
|
|
20717
20105
|
source;
|
|
20718
20106
|
dest;
|
|
@@ -24928,9 +24316,9 @@ async function teleport(teleport_param) {
|
|
|
24928
24316
|
if (scaleEncodedAssetId === null) {
|
|
24929
24317
|
throw new Error("Unknown asset id provided");
|
|
24930
24318
|
}
|
|
24931
|
-
const
|
|
24932
|
-
const destination = convertStateMachineIdToEnum(
|
|
24933
|
-
const recipient = hexToBytes(normalizeAddressForStateMachine(params.recipient,
|
|
24319
|
+
const destinationStateMachine2 = normalizeStateMachineId(params.destination);
|
|
24320
|
+
const destination = convertStateMachineIdToEnum(destinationStateMachine2);
|
|
24321
|
+
const recipient = hexToBytes(normalizeAddressForStateMachine(params.recipient, destinationStateMachine2));
|
|
24934
24322
|
const teleportParams = {
|
|
24935
24323
|
destination,
|
|
24936
24324
|
recepient: Array.from(recipient),
|
|
@@ -25183,6 +24571,6 @@ async function teleportDot(param_) {
|
|
|
25183
24571
|
return stream;
|
|
25184
24572
|
}
|
|
25185
24573
|
|
|
25186
|
-
export { ADDRESS_ZERO2 as ADDRESS_ZERO, BundlerMethod,
|
|
24574
|
+
export { ADDRESS_ZERO2 as ADDRESS_ZERO, BundlerMethod, CONTRACT_VERSION_ABI, ChainConfigService, Chains, CryptoUtils, DEFAULT_ADDRESS, DEFAULT_GRAFFITI, DOMAIN_TYPEHASH, DUMMY_PRIVATE_KEY, ERC20Method, ERC7821_BATCH_MODE, EvmChain, ABI as EvmHostABI, EvmLanguage, FILL_ORDER_SELECTOR, HyperClientStatus, HyperFungibleToken, HyperFungibleTokenABI, HyperFxOrderbook, INCLUSION_TIMEOUT_MS, InsufficientOrderbookLiquidityError, IntentGateway, ABI3 as IntentGatewayABI, IntentOrderStatus, IntentsCoprocessor, IsmpClient, MAX_DECLARED_ENTRIES, MOCK_ADDRESS, ORDERBOOK_DECIMALS, ORDERBOOK_QUERIES, ORDERBOOK_URLS, ORDER_V2_PARAM_TYPE, OrderStatus, OrderStatusChecker, OrderbookQuoteNotConvergedError, OrderbookRequestError, PACKED_USEROP_TYPEHASH, PERMIT2_SPONSORSHIP_BYTES, PLACE_ORDER_SELECTOR, PharosChain, PolkadotHubChain, REQUEST_COMMITMENTS_SLOT, REQUEST_RECEIPTS_SLOT, RESPONSE_COMMITMENTS_SLOT, RESPONSE_RECEIPTS_SLOT, RequestKind, RequestStatus, SELECT_SOLVER_TYPEHASH, STATE_COMMITMENTS_SLOT, SUPPORTED_INTENTS_VERSION, SubstrateChain, Swap, TESTNET_CHAINS, TeleportStatus, TimeoutStatus, TokenGateway, TronChain, USE_ETHERSCAN_CHAINS, UnsupportedLiquidityAssetError, UnsupportedLiquidityChainError, WrappedHyperFungibleTokenABI, __test, adjustDecimals, assertGatewayRelease, bytes20ToBytes32, bytes32ToBytes20, calculateAllowanceMappingLocation, calculateBalanceMappingLocation, chainConfigs, constructRedeemEscrowRequestBody, constructRefundEscrowRequestBody, convertCodecToIGetRequest, convertCodecToIProof, convertIGetRequestToCodec, convertIProofToCodec, convertStateIdToStateMachineId, convertStateMachineEnumToString, convertStateMachineIdToEnum, createEvmChain, createQueryClient, decodeAcceptedSourceChains, decodeERC7821ExecuteBatch, decodeFillOrder, decodePhantomBidDeclaration, decodePhantomBidPaymasterAndData, decodeUserOpScale, deriveHttpUrl, encodeAcceptedSourceChains, encodeERC7821ExecuteBatch, encodeFillOrder, encodeISMPMessage, encodePhantomBidDeclaration, encodePhantomBidPaymasterAndData, encodeStateMachineId, encodeUserOpScale, encodeWithdrawalRequest, estimateGasForPost, fetchPrice, fetchSourceProof, generateRootWithProof, getChainId, getConfigByStateMachineId, getContractCallInput, getContractCallInputs, getGasPriceFromEtherscan, getOrFetchStorageSlot, getOrderPlacedFromTx, getPostRequestEventFromTx, getPostResponseEventFromTx, getRequestCommitment, getStateCommitmentFieldSlot, getStateCommitmentSlot, getStorageSlot, getViemChain, hexToString, hyperbridgeAddress, isCanonicalEvmToken, maxBigInt, normalizeAddressForEvmBytes32, normalizeAddressForStateMachine, normalizeEvmAddress, normalizeEvmChainId, normalizeStateMachineId, orderCommitment, orderbookUrlFor, parseStateMachineId, pharosAtlantic, pharosMainnet, polkadotAssetHubPaseo, polkadotHubMainnet, poolSlug, postRequestCommitment, previewRateFill, queryAssetTeleported, queryGetRequest, queryPostRequest, quoteUniswap, readLegEscrow, readLegPartialFill, requestCommitmentKey, responseCommitmentKey, retryPromise, sortPoolSymbols, supportsRateFills, teleport, teleportDot, transformOrderForContract, tronChainIds, tronNile };
|
|
25187
24575
|
//# sourceMappingURL=index.js.map
|
|
25188
24576
|
//# sourceMappingURL=index.js.map
|