@hyperbridge/sdk 2.4.0 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser/index.d.ts +184 -42
- package/dist/browser/index.js +978 -194
- package/dist/browser/index.js.map +1 -1
- package/dist/node/{IntentGatewayV2-SB851bZs.d.cts → IntentGatewayV2-tYGohDdW.d.cts} +100 -5
- package/dist/node/{IntentGatewayV2-SB851bZs.d.ts → IntentGatewayV2-tYGohDdW.d.ts} +100 -5
- package/dist/node/index.cjs +979 -192
- package/dist/node/index.cjs.map +1 -1
- package/dist/node/index.d.cts +87 -40
- package/dist/node/index.d.ts +87 -40
- package/dist/node/index.js +978 -194
- package/dist/node/index.js.map +1 -1
- package/dist/node/intents-helpers.cjs +518 -7
- package/dist/node/intents-helpers.cjs.map +1 -1
- package/dist/node/intents-helpers.d.cts +52 -10
- package/dist/node/intents-helpers.d.ts +52 -10
- package/dist/node/intents-helpers.js +516 -9
- package/dist/node/intents-helpers.js.map +1 -1
- package/package.json +1 -1
package/dist/node/index.js
CHANGED
|
@@ -2,7 +2,7 @@ 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, decodeAbiParameters, getAddress, encodeAbiParameters, isHex, maxUint256, parseAbiParameters, encodePacked, parseAbiItem, concat, decodeFunctionData, hexToString as hexToString$1, decodeEventLog, parseEventLogs, parseUnits, concatHex, zeroAddress, decodeFunctionResult, formatUnits } from 'viem';
|
|
5
|
+
import { defineChain, keccak256, toHex, createPublicClient, http, hexToBytes, toFunctionSelector, bytesToHex, encodeFunctionData, erc20Abi, bytesToBigInt, pad, toBytes, numberToBytes, decodeAbiParameters, getAddress, encodeAbiParameters, isHex, isAddress, maxUint256, parseAbiParameters, encodePacked, parseAbiItem, concat, decodeFunctionData, hexToString as hexToString$1, decodeEventLog, parseEventLogs, parseUnits, concatHex, zeroAddress, decodeFunctionResult, formatUnits } 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
7
|
import { TronWeb } from 'tronweb';
|
|
8
8
|
import { flatten, zip, capitalize, maxBy, isNil } from 'lodash-es';
|
|
@@ -2479,30 +2479,30 @@ var handlerV2_default = { ABI: ABI2 };
|
|
|
2479
2479
|
function tronAddress(base58) {
|
|
2480
2480
|
return `0x${TronWeb.address.toHex(base58).slice(2)}`;
|
|
2481
2481
|
}
|
|
2482
|
-
var Chains = /* @__PURE__ */ ((
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
return
|
|
2482
|
+
var Chains = /* @__PURE__ */ ((Chains2) => {
|
|
2483
|
+
Chains2["BSC_CHAPEL"] = "EVM-97";
|
|
2484
|
+
Chains2["GNOSIS_CHIADO"] = "EVM-10200";
|
|
2485
|
+
Chains2["HYPERBRIDGE_GARGANTUA"] = "KUSAMA-4009";
|
|
2486
|
+
Chains2["SEPOLIA"] = "EVM-11155111";
|
|
2487
|
+
Chains2["MAINNET"] = "EVM-1";
|
|
2488
|
+
Chains2["BSC_MAINNET"] = "EVM-56";
|
|
2489
|
+
Chains2["ARBITRUM_MAINNET"] = "EVM-42161";
|
|
2490
|
+
Chains2["ARBITRUM_SEPOLIA"] = "EVM-421614";
|
|
2491
|
+
Chains2["BASE_MAINNET"] = "EVM-8453";
|
|
2492
|
+
Chains2["BASE_SEPOLIA"] = "EVM-84532";
|
|
2493
|
+
Chains2["OPTIMISM_MAINNET"] = "EVM-10";
|
|
2494
|
+
Chains2["OPTIMISM_SEPOLIA"] = "EVM-11155420";
|
|
2495
|
+
Chains2["GNOSIS_MAINNET"] = "EVM-100";
|
|
2496
|
+
Chains2["SONEIUM_MAINNET"] = "EVM-1868";
|
|
2497
|
+
Chains2["POLYGON_MAINNET"] = "EVM-137";
|
|
2498
|
+
Chains2["POLKADOT_HUB_MAINNET"] = "EVM-420420419";
|
|
2499
|
+
Chains2["POLYGON_AMOY"] = "EVM-80002";
|
|
2500
|
+
Chains2["POLKADOT_ASSET_HUB_PASEO"] = "EVM-420420417";
|
|
2501
|
+
Chains2["TRON_MAINNET"] = "EVM-728126428";
|
|
2502
|
+
Chains2["TRON_NILE"] = "EVM-3448148188";
|
|
2503
|
+
Chains2["PHAROS_MAINNET"] = "EVM-688600";
|
|
2504
|
+
Chains2["PHAROS_ATLANTIC"] = "EVM-688689";
|
|
2505
|
+
return Chains2;
|
|
2506
2506
|
})(Chains || {});
|
|
2507
2507
|
var polkadotAssetHubPaseo = defineChain({
|
|
2508
2508
|
id: 420420417,
|
|
@@ -2693,7 +2693,7 @@ var chainConfigs = {
|
|
|
2693
2693
|
},
|
|
2694
2694
|
addresses: {
|
|
2695
2695
|
IntentGateway: "0xAe041F7B0CB581876832830baeB6a2Aa2a3C9716",
|
|
2696
|
-
SolverAccount: "
|
|
2696
|
+
SolverAccount: "0xfCd233b937D7622AAc63ced3C9A1A12F4a6B64E3",
|
|
2697
2697
|
TokenGateway: "0xFd413e3AFe560182C4471F4d143A96d3e259B6dE",
|
|
2698
2698
|
Host: "0x620128E2B19193d6Bd244a3AC8D3bBa0541B19c3",
|
|
2699
2699
|
UniswapRouter02: "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D",
|
|
@@ -2709,6 +2709,7 @@ var chainConfigs = {
|
|
|
2709
2709
|
Permit2: "0x000000000022D473030F116dDEE9F6B43aC78BA3",
|
|
2710
2710
|
EntryPointV08: "0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108",
|
|
2711
2711
|
CirclePaymaster: "0x0578cFB241215b77442a541325d6A4E6dFE700Ec",
|
|
2712
|
+
SimplexPaymaster: "0xD4340d7466e040626383cb9cda9307ba8E081149",
|
|
2712
2713
|
Usdt0Oft: "0x6C96dE32CEa08842dcc4058c14d3aaAD7Fa41dee"
|
|
2713
2714
|
},
|
|
2714
2715
|
rpcEnvKey: "ETH_MAINNET",
|
|
@@ -2748,7 +2749,7 @@ var chainConfigs = {
|
|
|
2748
2749
|
},
|
|
2749
2750
|
addresses: {
|
|
2750
2751
|
IntentGateway: "0xAe041F7B0CB581876832830baeB6a2Aa2a3C9716",
|
|
2751
|
-
SolverAccount: "
|
|
2752
|
+
SolverAccount: "0xfCd233b937D7622AAc63ced3C9A1A12F4a6B64E3",
|
|
2752
2753
|
TokenGateway: "0xFd413e3AFe560182C4471F4d143A96d3e259B6dE",
|
|
2753
2754
|
Host: "0x620128E2B19193d6Bd244a3AC8D3bBa0541B19c3",
|
|
2754
2755
|
UniswapRouter02: "0x10ED43C718714eb63d5aA57B78B54704E256024E",
|
|
@@ -2762,7 +2763,8 @@ var chainConfigs = {
|
|
|
2762
2763
|
UniswapV4StateView: "0xd13dd3d6e93f276fafc9db9e6bb47c1180aee0c4",
|
|
2763
2764
|
Calldispatcher: "0xc71251c8b3e7b02697a84363eef6dce8dfbdf333",
|
|
2764
2765
|
Permit2: "0x000000000022D473030F116dDEE9F6B43aC78BA3",
|
|
2765
|
-
EntryPointV08: "0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108"
|
|
2766
|
+
EntryPointV08: "0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108",
|
|
2767
|
+
SimplexPaymaster: "0xeD02f9f0df8F562B89cC5b25867Ad3C2d61252A9"
|
|
2766
2768
|
// "Usdt0Oft": Not available on BSC
|
|
2767
2769
|
},
|
|
2768
2770
|
rpcEnvKey: "BSC_MAINNET",
|
|
@@ -2804,7 +2806,7 @@ var chainConfigs = {
|
|
|
2804
2806
|
},
|
|
2805
2807
|
addresses: {
|
|
2806
2808
|
IntentGateway: "0xAe041F7B0CB581876832830baeB6a2Aa2a3C9716",
|
|
2807
|
-
SolverAccount: "
|
|
2809
|
+
SolverAccount: "0xfCd233b937D7622AAc63ced3C9A1A12F4a6B64E3",
|
|
2808
2810
|
TokenGateway: "0xFd413e3AFe560182C4471F4d143A96d3e259B6dE",
|
|
2809
2811
|
Host: "0x620128E2B19193d6Bd244a3AC8D3bBa0541B19c3",
|
|
2810
2812
|
UniswapRouter02: "0x4752ba5DBc23f44D87826276BF6Fd6b1C372aD24",
|
|
@@ -2820,6 +2822,7 @@ var chainConfigs = {
|
|
|
2820
2822
|
Permit2: "0x000000000022D473030F116dDEE9F6B43aC78BA3",
|
|
2821
2823
|
EntryPointV08: "0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108",
|
|
2822
2824
|
CirclePaymaster: "0x0578cFB241215b77442a541325d6A4E6dFE700Ec",
|
|
2825
|
+
SimplexPaymaster: "0x7281Bccb4f0BCE44F3B8542d1fC5e51c2F5fC08C",
|
|
2823
2826
|
Usdt0Oft: "0x14E4A1B13bf7F943c8ff7C51fb60FA964A298D92"
|
|
2824
2827
|
},
|
|
2825
2828
|
rpcEnvKey: "ARBITRUM_MAINNET",
|
|
@@ -2861,7 +2864,7 @@ var chainConfigs = {
|
|
|
2861
2864
|
},
|
|
2862
2865
|
addresses: {
|
|
2863
2866
|
IntentGateway: "0xAe041F7B0CB581876832830baeB6a2Aa2a3C9716",
|
|
2864
|
-
SolverAccount: "
|
|
2867
|
+
SolverAccount: "0xfCd233b937D7622AAc63ced3C9A1A12F4a6B64E3",
|
|
2865
2868
|
TokenGateway: "0xFd413e3AFe560182C4471F4d143A96d3e259B6dE",
|
|
2866
2869
|
Host: "0x620128E2B19193d6Bd244a3AC8D3bBa0541B19c3",
|
|
2867
2870
|
UniswapRouter02: "0x4752ba5DBc23f44D87826276BF6Fd6b1C372aD24",
|
|
@@ -2874,6 +2877,7 @@ var chainConfigs = {
|
|
|
2874
2877
|
Permit2: "0x000000000022D473030F116dDEE9F6B43aC78BA3",
|
|
2875
2878
|
EntryPointV08: "0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108",
|
|
2876
2879
|
CirclePaymaster: "0x0578cFB241215b77442a541325d6A4E6dFE700Ec",
|
|
2880
|
+
SimplexPaymaster: "0x15b3B03C870c7ef252029c35A12d3b339F5c8d7f",
|
|
2877
2881
|
AerodromeRouter: "0xcF77a3Ba9A5CA399B7c97c74d54e5b1Beb874E43",
|
|
2878
2882
|
UniswapV4PositionManager: "0x7c5f5a4bbd8fd63184577525326123b519429bdc",
|
|
2879
2883
|
UniswapV4PoolManager: "0x498581ff718922c3f8e6a244956af099b2652b2b",
|
|
@@ -2920,7 +2924,7 @@ var chainConfigs = {
|
|
|
2920
2924
|
},
|
|
2921
2925
|
addresses: {
|
|
2922
2926
|
IntentGateway: "0xAe041F7B0CB581876832830baeB6a2Aa2a3C9716",
|
|
2923
|
-
SolverAccount: "
|
|
2927
|
+
SolverAccount: "0xfCd233b937D7622AAc63ced3C9A1A12F4a6B64E3",
|
|
2924
2928
|
TokenGateway: "0x8b536105b6Fae2aE9199f5146D3C57Dfe53b614E",
|
|
2925
2929
|
Host: "0x620128E2B19193d6Bd244a3AC8D3bBa0541B19c3",
|
|
2926
2930
|
UniswapRouter02: "0xd2f9496824951D5237cC71245D659E48d0d5f9E8",
|
|
@@ -2936,6 +2940,7 @@ var chainConfigs = {
|
|
|
2936
2940
|
Permit2: "0x000000000022D473030F116dDEE9F6B43aC78BA3",
|
|
2937
2941
|
EntryPointV08: "0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108",
|
|
2938
2942
|
CirclePaymaster: "0x0578cFB241215b77442a541325d6A4E6dFE700Ec",
|
|
2943
|
+
SimplexPaymaster: "0xe99acFe0f5fC4C8ea54A187D8D3b05f136150095",
|
|
2939
2944
|
Usdt0Oft: "0x6BA10300f0DC58B7a1e4c0e41f5daBb7D7829e13"
|
|
2940
2945
|
},
|
|
2941
2946
|
rpcEnvKey: "POLYGON_MAINNET",
|
|
@@ -3031,7 +3036,7 @@ var chainConfigs = {
|
|
|
3031
3036
|
},
|
|
3032
3037
|
addresses: {
|
|
3033
3038
|
IntentGateway: "0xAe041F7B0CB581876832830baeB6a2Aa2a3C9716",
|
|
3034
|
-
SolverAccount: "
|
|
3039
|
+
SolverAccount: "0xfCd233b937D7622AAc63ced3C9A1A12F4a6B64E3",
|
|
3035
3040
|
TokenGateway: "0xFd413e3AFe560182C4471F4d143A96d3e259B6dE",
|
|
3036
3041
|
Host: "0x620128E2B19193d6Bd244a3AC8D3bBa0541B19c3",
|
|
3037
3042
|
UniswapRouter02: "0x4A7b5Da61326A6379179b40d00F57E5bbDC962c2",
|
|
@@ -3066,7 +3071,7 @@ var chainConfigs = {
|
|
|
3066
3071
|
},
|
|
3067
3072
|
addresses: {
|
|
3068
3073
|
IntentGateway: "0xAe041F7B0CB581876832830baeB6a2Aa2a3C9716",
|
|
3069
|
-
SolverAccount: "
|
|
3074
|
+
SolverAccount: "0xfCd233b937D7622AAc63ced3C9A1A12F4a6B64E3",
|
|
3070
3075
|
TokenGateway: "0xFd413e3AFe560182C4471F4d143A96d3e259B6dE",
|
|
3071
3076
|
Host: "0x620128E2B19193d6Bd244a3AC8D3bBa0541B19c3",
|
|
3072
3077
|
UniswapRouter02: "0xB2e26652e4BAd1e56055A051f922E06760cA0BFE",
|
|
@@ -3221,7 +3226,7 @@ var chainConfigs = {
|
|
|
3221
3226
|
},
|
|
3222
3227
|
addresses: {
|
|
3223
3228
|
IntentGateway: "0xAe041F7B0CB581876832830baeB6a2Aa2a3C9716",
|
|
3224
|
-
SolverAccount: "
|
|
3229
|
+
SolverAccount: "0xfCd233b937D7622AAc63ced3C9A1A12F4a6B64E3",
|
|
3225
3230
|
Host: "0x620128E2B19193d6Bd244a3AC8D3bBa0541B19c3",
|
|
3226
3231
|
Calldispatcher: "0xE2C7e576E26E0bE7aC97c6fE925bcDAbD87c4bEd"
|
|
3227
3232
|
},
|
|
@@ -5107,6 +5112,24 @@ var ChainConfigService = class {
|
|
|
5107
5112
|
getAssetAddress(chain, symbol) {
|
|
5108
5113
|
return this.getConfig(chain)?.assets?.[symbol];
|
|
5109
5114
|
}
|
|
5115
|
+
/**
|
|
5116
|
+
* Resolves configured token metadata from an address on a specific chain.
|
|
5117
|
+
* This is used by SDK helpers that accept token addresses rather than caller-
|
|
5118
|
+
* supplied symbols or decimals.
|
|
5119
|
+
*/
|
|
5120
|
+
getAssetMetadataByAddress(chain, address) {
|
|
5121
|
+
const config = this.getConfig(chain);
|
|
5122
|
+
if (!config?.assets) return;
|
|
5123
|
+
const normalizedAddress = address.toLowerCase();
|
|
5124
|
+
for (const [symbol, configuredAddress] of Object.entries(config.assets)) {
|
|
5125
|
+
if (configuredAddress.toLowerCase() !== normalizedAddress) continue;
|
|
5126
|
+
return {
|
|
5127
|
+
symbol,
|
|
5128
|
+
address: configuredAddress,
|
|
5129
|
+
decimals: config.tokenDecimals?.[symbol]
|
|
5130
|
+
};
|
|
5131
|
+
}
|
|
5132
|
+
}
|
|
5110
5133
|
getUsdtAsset(chain) {
|
|
5111
5134
|
return this.getConfig(chain)?.assets?.USDT ?? "0x";
|
|
5112
5135
|
}
|
|
@@ -5213,6 +5236,9 @@ var ChainConfigService = class {
|
|
|
5213
5236
|
getCirclePaymasterAddress(chain) {
|
|
5214
5237
|
return this.getConfig(chain)?.addresses.CirclePaymaster;
|
|
5215
5238
|
}
|
|
5239
|
+
getSimplexPaymasterAddress(chain) {
|
|
5240
|
+
return this.getConfig(chain)?.addresses.SimplexPaymaster;
|
|
5241
|
+
}
|
|
5216
5242
|
getHyperbridgeAddress() {
|
|
5217
5243
|
return hyperbridgeAddress;
|
|
5218
5244
|
}
|
|
@@ -7033,6 +7059,16 @@ var ExpectedError = class _ExpectedError extends Error {
|
|
|
7033
7059
|
return error instanceof _ExpectedError;
|
|
7034
7060
|
}
|
|
7035
7061
|
};
|
|
7062
|
+
var MISSING_CONSENSUS_UPDATE_TIME_MESSAGE = "Consensus update time not found";
|
|
7063
|
+
var MissingConsensusUpdateTimeError = class _MissingConsensusUpdateTimeError extends Error {
|
|
7064
|
+
constructor(message = MISSING_CONSENSUS_UPDATE_TIME_MESSAGE, options) {
|
|
7065
|
+
super(message, options);
|
|
7066
|
+
this.name = "Hyperbridge/SDK/MissingConsensusUpdateTimeError";
|
|
7067
|
+
}
|
|
7068
|
+
static isError(error) {
|
|
7069
|
+
return error instanceof _MissingConsensusUpdateTimeError || error instanceof Error && error.message.toLowerCase().includes(MISSING_CONSENSUS_UPDATE_TIME_MESSAGE.toLowerCase());
|
|
7070
|
+
}
|
|
7071
|
+
};
|
|
7036
7072
|
|
|
7037
7073
|
// src/configs/constants.ts
|
|
7038
7074
|
var ISMP_PREFIX = ":child_storage:default:ISMPv2";
|
|
@@ -7346,8 +7382,15 @@ var SubstrateChain = class _SubstrateChain {
|
|
|
7346
7382
|
id: stateMachineId,
|
|
7347
7383
|
height: Number(stateMachineHeight.height)
|
|
7348
7384
|
};
|
|
7349
|
-
|
|
7350
|
-
|
|
7385
|
+
try {
|
|
7386
|
+
const updateTime = await this.rpcClient.call("ismp_queryStateMachineUpdateTime", [payload]);
|
|
7387
|
+
return BigInt(updateTime);
|
|
7388
|
+
} catch (error) {
|
|
7389
|
+
if (MissingConsensusUpdateTimeError.isError(error)) {
|
|
7390
|
+
throw new MissingConsensusUpdateTimeError(MISSING_CONSENSUS_UPDATE_TIME_MESSAGE, { cause: error });
|
|
7391
|
+
}
|
|
7392
|
+
throw error;
|
|
7393
|
+
}
|
|
7351
7394
|
}
|
|
7352
7395
|
/**
|
|
7353
7396
|
* Get the challenge period for a given state machine id.
|
|
@@ -7780,7 +7823,7 @@ var IntentsCoprocessor = class _IntentsCoprocessor {
|
|
|
7780
7823
|
*/
|
|
7781
7824
|
async sendExtrinsicWithRetries(extrinsic, maxRetries, timeoutMs) {
|
|
7782
7825
|
const keyPair = this.getKeyPair();
|
|
7783
|
-
|
|
7826
|
+
const baseTip = 1000000000n;
|
|
7784
7827
|
let attempt = 0;
|
|
7785
7828
|
while (attempt < maxRetries) {
|
|
7786
7829
|
const currentTip = baseTip * BigInt(2 ** attempt);
|
|
@@ -8093,26 +8136,76 @@ var IntentsCoprocessor = class _IntentsCoprocessor {
|
|
|
8093
8136
|
};
|
|
8094
8137
|
}
|
|
8095
8138
|
/**
|
|
8096
|
-
*
|
|
8097
|
-
|
|
8098
|
-
|
|
8099
|
-
|
|
8100
|
-
|
|
8101
|
-
const
|
|
8102
|
-
|
|
8103
|
-
|
|
8104
|
-
|
|
8105
|
-
|
|
8106
|
-
|
|
8107
|
-
|
|
8108
|
-
|
|
8109
|
-
|
|
8110
|
-
|
|
8111
|
-
|
|
8112
|
-
|
|
8139
|
+
* Reads the PhantomOrderRegistered events emitted in a single block.
|
|
8140
|
+
*/
|
|
8141
|
+
async getPhantomOrdersInBlock(blockNumber) {
|
|
8142
|
+
const blockHash = await this.api.rpc.chain.getBlockHash(blockNumber);
|
|
8143
|
+
const apiAt = await this.api.at(blockHash);
|
|
8144
|
+
const records = await apiAt.query.system.events();
|
|
8145
|
+
const orders = [];
|
|
8146
|
+
for (const { event } of records) {
|
|
8147
|
+
if (event.section !== "intentsCoprocessor" || event.method !== "PhantomOrderRegistered") continue;
|
|
8148
|
+
const [commitment, chain, createdAt, tokenA, tokenB, standardAmount] = event.data;
|
|
8149
|
+
orders.push({
|
|
8150
|
+
commitment: commitment.toHex(),
|
|
8151
|
+
chain: new TextDecoder().decode(hexToU8a(chain.toHex())),
|
|
8152
|
+
createdAt: createdAt.toNumber(),
|
|
8153
|
+
tokenA: tokenA.toHex(),
|
|
8154
|
+
tokenB: tokenB.toHex(),
|
|
8155
|
+
standardAmount: BigInt(standardAmount.toString())
|
|
8156
|
+
});
|
|
8157
|
+
}
|
|
8158
|
+
return orders;
|
|
8159
|
+
}
|
|
8160
|
+
/**
|
|
8161
|
+
* Polls for newly registered phantom orders, invoking the callback once per order.
|
|
8162
|
+
*
|
|
8163
|
+
* Each tick reads the current head and scans every block between the last one processed and that
|
|
8164
|
+
* head, so the block cursor — not the connection — determines what has been seen. This replaced a
|
|
8165
|
+
* system.events subscription, which was only as reliable as its socket: polkadot-js reconnects
|
|
8166
|
+
* the transport but does not reliably re-establish storage subscriptions, and anything emitted
|
|
8167
|
+
* while disconnected was lost silently. With a bid window measured in a handful of blocks, that
|
|
8168
|
+
* meant silently missed bids.
|
|
8169
|
+
*
|
|
8170
|
+
* Scanning a block range is gap-free rather than merely self-healing: an outage delays orders but
|
|
8171
|
+
* cannot drop them, because the cursor only advances past a block whose events were actually
|
|
8172
|
+
* read. Recovery replays the backlog.
|
|
8173
|
+
*
|
|
8174
|
+
* Returns a function that stops polling.
|
|
8175
|
+
*/
|
|
8176
|
+
pollPhantomOrders(callback, options = {}) {
|
|
8177
|
+
const { intervalMs = 6e3, maxBlocksPerPoll = 500, lookbackBlocks = 0, onError } = options;
|
|
8178
|
+
let cursor = null;
|
|
8179
|
+
let inFlight = false;
|
|
8180
|
+
let stopped = false;
|
|
8181
|
+
const tick = async () => {
|
|
8182
|
+
if (inFlight || stopped) return;
|
|
8183
|
+
inFlight = true;
|
|
8184
|
+
try {
|
|
8185
|
+
const head = (await this.api.rpc.chain.getHeader()).number.toNumber();
|
|
8186
|
+
if (cursor === null) {
|
|
8187
|
+
cursor = Math.max(head - 1 - lookbackBlocks, -1);
|
|
8188
|
+
}
|
|
8189
|
+
if (head <= cursor) return;
|
|
8190
|
+
const to = Math.min(head, cursor + maxBlocksPerPoll);
|
|
8191
|
+
for (let blockNumber = cursor + 1; blockNumber <= to; blockNumber++) {
|
|
8192
|
+
if (stopped) return;
|
|
8193
|
+
const orders = await this.getPhantomOrdersInBlock(blockNumber);
|
|
8194
|
+
for (const order of orders) callback(order);
|
|
8195
|
+
cursor = blockNumber;
|
|
8196
|
+
}
|
|
8197
|
+
} catch (err) {
|
|
8198
|
+
onError?.(err);
|
|
8199
|
+
} finally {
|
|
8200
|
+
inFlight = false;
|
|
8113
8201
|
}
|
|
8114
|
-
}
|
|
8115
|
-
|
|
8202
|
+
};
|
|
8203
|
+
void tick();
|
|
8204
|
+
const timer = setInterval(() => void tick(), intervalMs);
|
|
8205
|
+
return () => {
|
|
8206
|
+
stopped = true;
|
|
8207
|
+
clearInterval(timer);
|
|
8208
|
+
};
|
|
8116
8209
|
}
|
|
8117
8210
|
};
|
|
8118
8211
|
var TronChain = class _TronChain {
|
|
@@ -9245,7 +9338,12 @@ function sleep(ms) {
|
|
|
9245
9338
|
async function waitForChallengePeriod(chain, stateMachineHeight) {
|
|
9246
9339
|
const challengePeriod = await chain.challengePeriod(stateMachineHeight.id);
|
|
9247
9340
|
if (challengePeriod === BigInt(0)) return;
|
|
9248
|
-
const updateTime = await chain.stateMachineUpdateTime(stateMachineHeight)
|
|
9341
|
+
const updateTime = await retryPromise(() => chain.stateMachineUpdateTime(stateMachineHeight), {
|
|
9342
|
+
maxRetries: 3,
|
|
9343
|
+
backoffMs: 500,
|
|
9344
|
+
logMessage: "Fetching consensus update time while waiting for the challenge period",
|
|
9345
|
+
shouldRetry: (error) => !MissingConsensusUpdateTimeError.isError(error)
|
|
9346
|
+
});
|
|
9249
9347
|
let currentTimestamp = await chain.timestamp();
|
|
9250
9348
|
let timeElapsed = currentTimestamp - updateTime;
|
|
9251
9349
|
if (timeElapsed > challengePeriod) return;
|
|
@@ -9392,6 +9490,10 @@ function normalizeAddressForEvmBytes32(address) {
|
|
|
9392
9490
|
if (address.length === 66) return address;
|
|
9393
9491
|
return bytes20ToBytes32(address);
|
|
9394
9492
|
}
|
|
9493
|
+
function normalizeEvmAddress(address, field = "address") {
|
|
9494
|
+
if (!isAddress(address)) throw new TypeError(`${field} must be a valid EVM address`);
|
|
9495
|
+
return address.toLowerCase();
|
|
9496
|
+
}
|
|
9395
9497
|
function normalizeAddressForStateMachine(address, stateMachineId) {
|
|
9396
9498
|
return isEvmChain(normalizeStateMachineId(stateMachineId)) ? normalizeAddressForEvmBytes32(address) : address;
|
|
9397
9499
|
}
|
|
@@ -9399,14 +9501,16 @@ var DEFAULT_LOGGER = createConsola({
|
|
|
9399
9501
|
level: LogLevels.silent
|
|
9400
9502
|
});
|
|
9401
9503
|
async function retryPromise(operation, retryConfig) {
|
|
9402
|
-
const { logger = DEFAULT_LOGGER, logMessage = "Retry operation failed" } = retryConfig;
|
|
9504
|
+
const { logger = DEFAULT_LOGGER, logMessage = "Retry operation failed", shouldRetry } = retryConfig;
|
|
9403
9505
|
let lastError;
|
|
9404
9506
|
for (let i = 0; i < retryConfig.maxRetries; i++) {
|
|
9405
9507
|
try {
|
|
9406
9508
|
return await operation();
|
|
9407
9509
|
} catch (error) {
|
|
9510
|
+
if (shouldRetry && !shouldRetry(error)) throw error;
|
|
9408
9511
|
logger.trace(`Retrying(${i}) > ${logMessage}`);
|
|
9409
9512
|
lastError = error;
|
|
9513
|
+
if (i === retryConfig.maxRetries - 1) break;
|
|
9410
9514
|
await new Promise((resolve) => setTimeout(resolve, retryConfig.backoffMs * 2 ** i));
|
|
9411
9515
|
}
|
|
9412
9516
|
}
|
|
@@ -11450,6 +11554,82 @@ query OrderStatus($commitment: String!) {
|
|
|
11450
11554
|
}
|
|
11451
11555
|
}
|
|
11452
11556
|
}`;
|
|
11557
|
+
var LATEST_PHANTOM_ORDER_PRICE_SNAPSHOT = `
|
|
11558
|
+
query LatestPhantomOrderPriceSnapshot($tokenA: String!, $tokenB: String!) {
|
|
11559
|
+
phantomOrderPriceSnapshots(
|
|
11560
|
+
filter: {
|
|
11561
|
+
and: [
|
|
11562
|
+
{ tokenA: { equalTo: $tokenA } }
|
|
11563
|
+
{ tokenB: { equalTo: $tokenB } }
|
|
11564
|
+
{ medianPrice: { isNull: false } }
|
|
11565
|
+
]
|
|
11566
|
+
}
|
|
11567
|
+
orderBy: BLOCK_NUMBER_DESC
|
|
11568
|
+
first: 1
|
|
11569
|
+
) {
|
|
11570
|
+
nodes {
|
|
11571
|
+
commitment
|
|
11572
|
+
tokenA
|
|
11573
|
+
tokenB
|
|
11574
|
+
standardAmount
|
|
11575
|
+
blockNumber
|
|
11576
|
+
medianPrice
|
|
11577
|
+
lowestPrice
|
|
11578
|
+
highestPrice
|
|
11579
|
+
bidCount
|
|
11580
|
+
snapshotTime
|
|
11581
|
+
}
|
|
11582
|
+
}
|
|
11583
|
+
}`;
|
|
11584
|
+
var LATEST_PHANTOM_ORDER_LIQUIDITY_SNAPSHOT = `
|
|
11585
|
+
query LatestPhantomOrderLiquiditySnapshot($tokenA: String!, $tokenB: String!) {
|
|
11586
|
+
phantomOrderPriceSnapshots(
|
|
11587
|
+
filter: {
|
|
11588
|
+
and: [
|
|
11589
|
+
{ tokenA: { equalTo: $tokenA } }
|
|
11590
|
+
{ tokenB: { equalTo: $tokenB } }
|
|
11591
|
+
]
|
|
11592
|
+
}
|
|
11593
|
+
orderBy: SNAPSHOT_TIME_DESC
|
|
11594
|
+
first: 1
|
|
11595
|
+
) {
|
|
11596
|
+
nodes {
|
|
11597
|
+
commitment
|
|
11598
|
+
tokenA
|
|
11599
|
+
tokenB
|
|
11600
|
+
snapshotTime
|
|
11601
|
+
}
|
|
11602
|
+
}
|
|
11603
|
+
}`;
|
|
11604
|
+
var LIQUIDITY_PROVIDER_BALANCES = `
|
|
11605
|
+
query LiquidityProviderBalanceAggregates($commitment: String!, $tokenAddress: String!) {
|
|
11606
|
+
liquidityProviderBalances(
|
|
11607
|
+
filter: {
|
|
11608
|
+
and: [
|
|
11609
|
+
{ commitment: { equalTo: $commitment } }
|
|
11610
|
+
{ tokenAddress: { equalTo: $tokenAddress } }
|
|
11611
|
+
]
|
|
11612
|
+
}
|
|
11613
|
+
) {
|
|
11614
|
+
aggregates {
|
|
11615
|
+
sum {
|
|
11616
|
+
balance
|
|
11617
|
+
}
|
|
11618
|
+
distinctCount {
|
|
11619
|
+
providerId
|
|
11620
|
+
}
|
|
11621
|
+
}
|
|
11622
|
+
groupedAggregates(groupBy: [CHAIN, TOKEN_ADDRESS]) {
|
|
11623
|
+
keys
|
|
11624
|
+
sum {
|
|
11625
|
+
balance
|
|
11626
|
+
}
|
|
11627
|
+
distinctCount {
|
|
11628
|
+
providerId
|
|
11629
|
+
}
|
|
11630
|
+
}
|
|
11631
|
+
}
|
|
11632
|
+
}`;
|
|
11453
11633
|
var TOKEN_GATEWAY_ASSET_TELEPORTED_STATUS = `
|
|
11454
11634
|
query TokenGatewayAssetTeleportedStatus($commitment: String!) {
|
|
11455
11635
|
tokenGatewayAssetTeleportedV2s(
|
|
@@ -11511,6 +11691,29 @@ async function queryAssetTeleported(params) {
|
|
|
11511
11691
|
function queryGetRequest(params) {
|
|
11512
11692
|
return _queryGetRequestInternal(params);
|
|
11513
11693
|
}
|
|
11694
|
+
async function _queryLatestPhantomOrderPriceSnapshot(params) {
|
|
11695
|
+
const response = await params.queryClient.request(
|
|
11696
|
+
LATEST_PHANTOM_ORDER_PRICE_SNAPSHOT,
|
|
11697
|
+
{
|
|
11698
|
+
tokenA: params.tokenA.toLowerCase(),
|
|
11699
|
+
tokenB: params.tokenB.toLowerCase()
|
|
11700
|
+
}
|
|
11701
|
+
);
|
|
11702
|
+
const snapshot = response.phantomOrderPriceSnapshots.nodes[0];
|
|
11703
|
+
if (!snapshot?.medianPrice) return;
|
|
11704
|
+
return {
|
|
11705
|
+
commitment: snapshot.commitment,
|
|
11706
|
+
tokenA: snapshot.tokenA,
|
|
11707
|
+
tokenB: snapshot.tokenB,
|
|
11708
|
+
standardAmount: BigInt(snapshot.standardAmount),
|
|
11709
|
+
blockNumber: BigInt(snapshot.blockNumber),
|
|
11710
|
+
medianPrice: BigInt(snapshot.medianPrice),
|
|
11711
|
+
lowestPrice: snapshot.lowestPrice === null ? void 0 : BigInt(snapshot.lowestPrice),
|
|
11712
|
+
highestPrice: snapshot.highestPrice === null ? void 0 : BigInt(snapshot.highestPrice),
|
|
11713
|
+
bidCount: snapshot.bidCount,
|
|
11714
|
+
snapshotTime: new Date(snapshot.snapshotTime)
|
|
11715
|
+
};
|
|
11716
|
+
}
|
|
11514
11717
|
async function _queryTokenGatewayAssetTeleportedInternal(params) {
|
|
11515
11718
|
const { commitmentHash, queryClient: client, logger = DEFAULT_LOGGER } = params;
|
|
11516
11719
|
const response = await retryPromise(
|
|
@@ -12011,6 +12214,7 @@ function createCancellationStorage(options = {}) {
|
|
|
12011
12214
|
const decoded = decodeIProof(value);
|
|
12012
12215
|
return decoded;
|
|
12013
12216
|
}
|
|
12217
|
+
if (key2.includes("postCommitment")) return value;
|
|
12014
12218
|
throw new Error(`Unknown storage key type: ${key2}`);
|
|
12015
12219
|
};
|
|
12016
12220
|
const setItem = async (key2, value) => {
|
|
@@ -12024,6 +12228,10 @@ function createCancellationStorage(options = {}) {
|
|
|
12024
12228
|
await baseStorage.setItem(key2, encoded);
|
|
12025
12229
|
return;
|
|
12026
12230
|
}
|
|
12231
|
+
if (key2.includes("postCommitment") && typeof value === "string") {
|
|
12232
|
+
await baseStorage.setItem(key2, value);
|
|
12233
|
+
return;
|
|
12234
|
+
}
|
|
12027
12235
|
throw new Error(`Unknown storage key type: ${key2}`);
|
|
12028
12236
|
};
|
|
12029
12237
|
const removeItem = async (key2) => {
|
|
@@ -12037,11 +12245,25 @@ function createCancellationStorage(options = {}) {
|
|
|
12037
12245
|
});
|
|
12038
12246
|
}
|
|
12039
12247
|
var STORAGE_KEYS = Object.freeze({
|
|
12040
|
-
destProof: (orderId) => `cancel-order:${orderId}:destProof`,
|
|
12041
|
-
getRequest: (orderId) => `cancel-order:${orderId}:getRequest`,
|
|
12042
|
-
sourceProof: (orderId) => `cancel-order:${orderId}:sourceProof`,
|
|
12043
|
-
postCommitment: (orderId) => `cancel-order:${orderId}:postCommitment`
|
|
12248
|
+
destProof: (orderId, source, destination) => `cancel-order:${cancellationScope(orderId, source, destination)}:destProof`,
|
|
12249
|
+
getRequest: (orderId, source, destination) => `cancel-order:${cancellationScope(orderId, source, destination)}:getRequest`,
|
|
12250
|
+
sourceProof: (orderId, source, destination) => `cancel-order:${cancellationScope(orderId, source, destination)}:sourceProof`,
|
|
12251
|
+
postCommitment: (orderId, source, destination) => `cancel-order:${cancellationScope(orderId, source, destination)}:postCommitment`
|
|
12044
12252
|
});
|
|
12253
|
+
var LEGACY_STORAGE_KEYS = Object.freeze({
|
|
12254
|
+
destProof: (orderId, source, destination) => `cancel-order:${legacyCancellationScope(orderId, source, destination)}:destProof`,
|
|
12255
|
+
getRequest: (orderId, source, destination) => `cancel-order:${legacyCancellationScope(orderId, source, destination)}:getRequest`,
|
|
12256
|
+
sourceProof: (orderId, source, destination) => `cancel-order:${legacyCancellationScope(orderId, source, destination)}:sourceProof`,
|
|
12257
|
+
postCommitment: (orderId, source, destination) => `cancel-order:${legacyCancellationScope(orderId, source, destination)}:postCommitment`
|
|
12258
|
+
});
|
|
12259
|
+
function cancellationScope(orderId, source, destination) {
|
|
12260
|
+
if (!source || !destination) return orderId;
|
|
12261
|
+
return `${orderId}:${encodeURIComponent(normalizeStateMachineId(source))}:${encodeURIComponent(normalizeStateMachineId(destination))}`;
|
|
12262
|
+
}
|
|
12263
|
+
function legacyCancellationScope(orderId, source, destination) {
|
|
12264
|
+
if (!source || !destination) return orderId;
|
|
12265
|
+
return `${orderId}:${encodeURIComponent(source)}:${encodeURIComponent(destination)}`;
|
|
12266
|
+
}
|
|
12045
12267
|
function createUsedUserOpsStorage(options = {}) {
|
|
12046
12268
|
options.env ?? detectEnvironment();
|
|
12047
12269
|
const driver = loadDriver({ options }) ?? inMemoryDriver();
|
|
@@ -15207,6 +15429,29 @@ async function convertFeeTokenToWei(ctx, feeTokenAmount, feeTokenIn, evmChainID)
|
|
|
15207
15429
|
}
|
|
15208
15430
|
|
|
15209
15431
|
// src/protocols/intents/OrderPlacer.ts
|
|
15432
|
+
function deriveCanonicalPlacedOrder(order, args) {
|
|
15433
|
+
const canonicalOrder = {
|
|
15434
|
+
...order,
|
|
15435
|
+
user: args.user,
|
|
15436
|
+
source: args.source,
|
|
15437
|
+
destination: args.destination,
|
|
15438
|
+
deadline: args.deadline,
|
|
15439
|
+
nonce: args.nonce,
|
|
15440
|
+
fees: args.fees,
|
|
15441
|
+
session: args.session,
|
|
15442
|
+
predispatch: {
|
|
15443
|
+
assets: args.predispatch.map((asset) => ({ ...asset })),
|
|
15444
|
+
call: order.predispatch.call
|
|
15445
|
+
},
|
|
15446
|
+
inputs: args.inputs.map((asset) => ({ ...asset })),
|
|
15447
|
+
output: {
|
|
15448
|
+
beneficiary: args.beneficiary,
|
|
15449
|
+
assets: args.outputs.map((asset) => ({ ...asset })),
|
|
15450
|
+
call: order.output.call
|
|
15451
|
+
}
|
|
15452
|
+
};
|
|
15453
|
+
return { ...canonicalOrder, id: orderCommitment(canonicalOrder) };
|
|
15454
|
+
}
|
|
15210
15455
|
var OrderPlacer = class {
|
|
15211
15456
|
/**
|
|
15212
15457
|
* @param ctx - Shared IntentsV2 context providing the source chain client,
|
|
@@ -15223,17 +15468,16 @@ var OrderPlacer = class {
|
|
|
15223
15468
|
* 1. Yields `{ to, data, sessionPrivateKey }` — the caller must sign a
|
|
15224
15469
|
* transaction sending `data` to `to` and pass the signed transaction back
|
|
15225
15470
|
* via `gen.next(signedTx)`.
|
|
15226
|
-
* 2. Returns `{ order, transactionHash }` — the finalized order
|
|
15227
|
-
*
|
|
15228
|
-
* transaction hash.
|
|
15471
|
+
* 2. Returns `{ order, transactionHash }` — the finalized order rebuilt from
|
|
15472
|
+
* the canonical `OrderPlaced` fields with its computed `id`, plus the
|
|
15473
|
+
* placement transaction hash.
|
|
15229
15474
|
*
|
|
15230
15475
|
* A fresh ephemeral session key is generated for every call. The key is
|
|
15231
15476
|
* stored immediately (without a commitment) so it can be retrieved by
|
|
15232
15477
|
* address, then updated with the commitment once the `OrderPlaced` event
|
|
15233
|
-
* confirms the
|
|
15478
|
+
* confirms the canonical order.
|
|
15234
15479
|
*
|
|
15235
|
-
* @param order - The order to place.
|
|
15236
|
-
* with the generated session key address before yielding.
|
|
15480
|
+
* @param order - The order to place. It is not mutated.
|
|
15237
15481
|
* @param graffiti - Optional bytes32 tag for orderflow attribution /
|
|
15238
15482
|
* revenue share. Defaults to {@link DEFAULT_GRAFFITI} (bytes32 zero).
|
|
15239
15483
|
* @yields `{ to, data, sessionPrivateKey }` — target contract address,
|
|
@@ -15248,7 +15492,7 @@ var OrderPlacer = class {
|
|
|
15248
15492
|
const account = privateKeyToAccount(privateKey);
|
|
15249
15493
|
const sessionKeyAddress = account.address;
|
|
15250
15494
|
const createdAt = Date.now();
|
|
15251
|
-
order
|
|
15495
|
+
const placementOrder = { ...order, session: sessionKeyAddress };
|
|
15252
15496
|
await this.ctx.sessionKeyStorage.setSessionKeyByAddress(sessionKeyAddress, {
|
|
15253
15497
|
privateKey,
|
|
15254
15498
|
address: sessionKeyAddress,
|
|
@@ -15257,7 +15501,7 @@ var OrderPlacer = class {
|
|
|
15257
15501
|
const data = encodeFunctionData({
|
|
15258
15502
|
abi: ABI3,
|
|
15259
15503
|
functionName: "placeOrder",
|
|
15260
|
-
args: [transformOrderForContract(
|
|
15504
|
+
args: [transformOrderForContract(placementOrder), graffiti]
|
|
15261
15505
|
});
|
|
15262
15506
|
const intentGatewayAddress = this.ctx.source.configService.getIntentGatewayAddress(
|
|
15263
15507
|
normalizeStateMachineId(order.source)
|
|
@@ -15277,20 +15521,15 @@ var OrderPlacer = class {
|
|
|
15277
15521
|
if (!orderPlacedEvent) {
|
|
15278
15522
|
throw new Error("OrderPlaced event not found in transaction receipt");
|
|
15279
15523
|
}
|
|
15280
|
-
|
|
15281
|
-
order.inputs = orderPlacedEvent.args.inputs.map((input) => ({
|
|
15282
|
-
token: input.token,
|
|
15283
|
-
amount: input.amount
|
|
15284
|
-
}));
|
|
15285
|
-
order.id = orderCommitment(order);
|
|
15524
|
+
const finalizedOrder = deriveCanonicalPlacedOrder(placementOrder, orderPlacedEvent.args);
|
|
15286
15525
|
const sessionKeyData = {
|
|
15287
15526
|
privateKey,
|
|
15288
15527
|
address: sessionKeyAddress,
|
|
15289
|
-
commitment:
|
|
15528
|
+
commitment: finalizedOrder.id,
|
|
15290
15529
|
createdAt
|
|
15291
15530
|
};
|
|
15292
15531
|
await this.ctx.sessionKeyStorage.setSessionKeyByAddress(sessionKeyAddress, sessionKeyData);
|
|
15293
|
-
return { order, receipt };
|
|
15532
|
+
return { order: finalizedOrder, receipt };
|
|
15294
15533
|
}
|
|
15295
15534
|
};
|
|
15296
15535
|
|
|
@@ -15620,7 +15859,7 @@ var OrderExecutor = class {
|
|
|
15620
15859
|
}
|
|
15621
15860
|
}
|
|
15622
15861
|
};
|
|
15623
|
-
var OrderCanceller = class {
|
|
15862
|
+
var OrderCanceller = class _OrderCanceller {
|
|
15624
15863
|
/**
|
|
15625
15864
|
* @param ctx - Shared IntentsV2 context providing the source and destination
|
|
15626
15865
|
* chain clients, config service, and cancellation storage.
|
|
@@ -15629,6 +15868,9 @@ var OrderCanceller = class {
|
|
|
15629
15868
|
this.ctx = ctx;
|
|
15630
15869
|
}
|
|
15631
15870
|
ctx;
|
|
15871
|
+
static DEFAULT_MAX_RECOVERY_RESTARTS = 1;
|
|
15872
|
+
static PROOF_FRESHNESS_MAX_RETRIES = 3;
|
|
15873
|
+
static PROOF_FRESHNESS_BACKOFF_MS = 500;
|
|
15632
15874
|
logger = createConsola({
|
|
15633
15875
|
level: LogLevels.info,
|
|
15634
15876
|
formatOptions: { columns: 80, colors: true, compact: true, date: false }
|
|
@@ -15660,11 +15902,14 @@ var OrderCanceller = class {
|
|
|
15660
15902
|
* @returns The native token dispatch fee in wei.
|
|
15661
15903
|
*/
|
|
15662
15904
|
async quoteCancelFromSource(order) {
|
|
15663
|
-
if (order.source === order.destination) return { nativeValue: 0n, relayerFee: 0n };
|
|
15664
15905
|
const sourceStateMachine = normalizeStateMachineId(order.source);
|
|
15906
|
+
const destStateMachine = normalizeStateMachineId(order.destination);
|
|
15907
|
+
if (sourceStateMachine === destStateMachine) {
|
|
15908
|
+
return { nativeValue: 0n, relayerFee: 0n };
|
|
15909
|
+
}
|
|
15665
15910
|
const height = order.deadline + 1n;
|
|
15666
15911
|
const destIntentGateway = this.ctx.dest.configService.getIntentGatewayAddress(
|
|
15667
|
-
|
|
15912
|
+
destStateMachine
|
|
15668
15913
|
);
|
|
15669
15914
|
const slotHash = await this.ctx.dest.client.readContract({
|
|
15670
15915
|
abi: ABI3,
|
|
@@ -15676,8 +15921,8 @@ var OrderCanceller = class {
|
|
|
15676
15921
|
const context = encodeWithdrawalRequest(order, order.user);
|
|
15677
15922
|
const getRequest = {
|
|
15678
15923
|
source: sourceStateMachine,
|
|
15679
|
-
dest:
|
|
15680
|
-
from: this.ctx.source.configService.getIntentGatewayAddress(
|
|
15924
|
+
dest: destStateMachine,
|
|
15925
|
+
from: this.ctx.source.configService.getIntentGatewayAddress(destStateMachine),
|
|
15681
15926
|
nonce: await this.ctx.source.getHostNonce(),
|
|
15682
15927
|
height,
|
|
15683
15928
|
keys: [key],
|
|
@@ -15694,7 +15939,9 @@ var OrderCanceller = class {
|
|
|
15694
15939
|
* cancellation is complete.
|
|
15695
15940
|
*
|
|
15696
15941
|
* Delegates to `cancelOrderFromSource` or `cancelOrderFromDest` based on
|
|
15697
|
-
* the `from` parameter.
|
|
15942
|
+
* the `from` parameter. If Hyperbridge has pruned consensus data needed for
|
|
15943
|
+
* source-side GET recovery, clears its stale checkpoint and restarts the
|
|
15944
|
+
* source-side stream internally.
|
|
15698
15945
|
*
|
|
15699
15946
|
* @param order - The order to cancel.
|
|
15700
15947
|
* @param indexerClient - Indexer client used to stream ISMP request status
|
|
@@ -15704,12 +15951,32 @@ var OrderCanceller = class {
|
|
|
15704
15951
|
* cancellation lifecycle.
|
|
15705
15952
|
*/
|
|
15706
15953
|
async *cancelOrder(order, indexerClient, options = {}) {
|
|
15707
|
-
const
|
|
15954
|
+
const sourceStateMachine = normalizeStateMachineId(order.source);
|
|
15955
|
+
const destStateMachine = normalizeStateMachineId(order.destination);
|
|
15956
|
+
const isSameChain = sourceStateMachine === destStateMachine;
|
|
15708
15957
|
if (options.from === "destination" && !isSameChain) {
|
|
15709
15958
|
yield* this.cancelOrderFromDest(order, indexerClient);
|
|
15710
15959
|
return;
|
|
15711
15960
|
}
|
|
15712
|
-
|
|
15961
|
+
let recoveryRestarts = 0;
|
|
15962
|
+
while (true) {
|
|
15963
|
+
try {
|
|
15964
|
+
yield* this.cancelOrderFromSource(order, indexerClient);
|
|
15965
|
+
return;
|
|
15966
|
+
} catch (error) {
|
|
15967
|
+
if (!MissingConsensusUpdateTimeError.isError(error)) throw error;
|
|
15968
|
+
if (recoveryRestarts >= _OrderCanceller.DEFAULT_MAX_RECOVERY_RESTARTS) {
|
|
15969
|
+
throw new Error(
|
|
15970
|
+
`Cancellation recovery stopped after ${recoveryRestarts} restart(s): Hyperbridge no longer retains a required consensus update.`
|
|
15971
|
+
);
|
|
15972
|
+
}
|
|
15973
|
+
recoveryRestarts += 1;
|
|
15974
|
+
this.logger.warn(
|
|
15975
|
+
`Restarting cancellation recovery (${recoveryRestarts}/${_OrderCanceller.DEFAULT_MAX_RECOVERY_RESTARTS}) after a required consensus update was pruned`
|
|
15976
|
+
);
|
|
15977
|
+
await this.clearGetRecoveryCache(order);
|
|
15978
|
+
}
|
|
15979
|
+
}
|
|
15713
15980
|
}
|
|
15714
15981
|
/**
|
|
15715
15982
|
* Async generator that cancels an order by initiating the cancel from the
|
|
@@ -15735,11 +16002,10 @@ var OrderCanceller = class {
|
|
|
15735
16002
|
* @throws If the cancel transaction does not contain the expected on-chain event.
|
|
15736
16003
|
*/
|
|
15737
16004
|
async *cancelOrderFromSource(order, indexerClient) {
|
|
15738
|
-
const
|
|
15739
|
-
const
|
|
15740
|
-
const
|
|
15741
|
-
|
|
15742
|
-
);
|
|
16005
|
+
const sourceStateMachine = normalizeStateMachineId(order.source);
|
|
16006
|
+
const destStateMachine = normalizeStateMachineId(order.destination);
|
|
16007
|
+
const isSameChain = sourceStateMachine === destStateMachine;
|
|
16008
|
+
const intentGatewayAddress = this.ctx.source.configService.getIntentGatewayAddress(sourceStateMachine);
|
|
15743
16009
|
if (isSameChain) {
|
|
15744
16010
|
const data = encodeFunctionData({
|
|
15745
16011
|
abi: ABI3,
|
|
@@ -15768,18 +16034,37 @@ var OrderCanceller = class {
|
|
|
15768
16034
|
};
|
|
15769
16035
|
return;
|
|
15770
16036
|
}
|
|
16037
|
+
const storageKeys = this.recoveryStorageKeys(order);
|
|
16038
|
+
const legacyStorageKeys = this.legacyRecoveryStorageKeys(order);
|
|
15771
16039
|
const hyperbridge = indexerClient.hyperbridge;
|
|
15772
|
-
const sourceStateMachine = normalizeStateMachineId(order.source);
|
|
15773
16040
|
const sourceConsensusStateId = this.ctx.source.configService.getConsensusStateId(sourceStateMachine);
|
|
15774
|
-
let destIProof = await this.
|
|
16041
|
+
let destIProof = await this.getRecoveryItem(
|
|
16042
|
+
storageKeys.destProof,
|
|
16043
|
+
legacyStorageKeys.map((keys) => keys.destProof)
|
|
16044
|
+
);
|
|
15775
16045
|
if (!destIProof) {
|
|
15776
16046
|
destIProof = yield* this.fetchDestinationProof(order, indexerClient);
|
|
15777
|
-
await this.ctx.cancellationStorage.setItem(
|
|
16047
|
+
await this.ctx.cancellationStorage.setItem(storageKeys.destProof, destIProof);
|
|
15778
16048
|
} else {
|
|
15779
|
-
|
|
16049
|
+
let refreshed = false;
|
|
16050
|
+
try {
|
|
16051
|
+
await this.assertProofFresh(hyperbridge, destIProof);
|
|
16052
|
+
} catch (error) {
|
|
16053
|
+
if (!MissingConsensusUpdateTimeError.isError(error)) throw error;
|
|
16054
|
+
await this.removeRecoveryItems(
|
|
16055
|
+
storageKeys.destProof,
|
|
16056
|
+
...legacyStorageKeys.map((keys) => keys.destProof)
|
|
16057
|
+
);
|
|
16058
|
+
destIProof = yield* this.fetchDestinationProof(order, indexerClient);
|
|
16059
|
+
await this.ctx.cancellationStorage.setItem(storageKeys.destProof, destIProof);
|
|
16060
|
+
refreshed = true;
|
|
16061
|
+
}
|
|
16062
|
+
if (!refreshed) yield { status: "DESTINATION_FINALIZED", proof: destIProof };
|
|
15780
16063
|
}
|
|
15781
|
-
|
|
15782
|
-
|
|
16064
|
+
await this.assertProofFresh(hyperbridge, destIProof);
|
|
16065
|
+
let getRequest = await this.getRecoveryItem(
|
|
16066
|
+
storageKeys.getRequest,
|
|
16067
|
+
legacyStorageKeys.map((keys) => keys.getRequest)
|
|
15783
16068
|
);
|
|
15784
16069
|
if (!getRequest) {
|
|
15785
16070
|
const quote = await this.quoteCancelFromSource(order);
|
|
@@ -15799,7 +16084,7 @@ var OrderCanceller = class {
|
|
|
15799
16084
|
const request = events.find((e) => e.eventName === "GetRequestEvent");
|
|
15800
16085
|
if (!request) throw new Error("GetRequest missing");
|
|
15801
16086
|
getRequest = request.args;
|
|
15802
|
-
await this.ctx.cancellationStorage.setItem(
|
|
16087
|
+
await this.ctx.cancellationStorage.setItem(storageKeys.getRequest, getRequest);
|
|
15803
16088
|
yield {
|
|
15804
16089
|
status: "CANCEL_STARTED",
|
|
15805
16090
|
receipt
|
|
@@ -15818,8 +16103,9 @@ var OrderCanceller = class {
|
|
|
15818
16103
|
metadata: statusUpdate.metadata
|
|
15819
16104
|
};
|
|
15820
16105
|
const sourceHeight = BigInt(statusUpdate.metadata.blockNumber);
|
|
15821
|
-
let sourceIProof = await this.
|
|
15822
|
-
|
|
16106
|
+
let sourceIProof = await this.getRecoveryItem(
|
|
16107
|
+
storageKeys.sourceProof,
|
|
16108
|
+
legacyStorageKeys.map((keys) => keys.sourceProof)
|
|
15823
16109
|
);
|
|
15824
16110
|
if (!sourceIProof) {
|
|
15825
16111
|
sourceIProof = await fetchSourceProof(
|
|
@@ -15829,8 +16115,9 @@ var OrderCanceller = class {
|
|
|
15829
16115
|
sourceConsensusStateId,
|
|
15830
16116
|
sourceHeight
|
|
15831
16117
|
);
|
|
15832
|
-
await this.ctx.cancellationStorage.setItem(
|
|
16118
|
+
await this.ctx.cancellationStorage.setItem(storageKeys.sourceProof, sourceIProof);
|
|
15833
16119
|
}
|
|
16120
|
+
await this.assertProofFresh(hyperbridge, sourceIProof);
|
|
15834
16121
|
await waitForChallengePeriod(hyperbridge, {
|
|
15835
16122
|
height: sourceIProof.height,
|
|
15836
16123
|
id: {
|
|
@@ -15838,6 +16125,10 @@ var OrderCanceller = class {
|
|
|
15838
16125
|
consensusStateId: sourceConsensusStateId
|
|
15839
16126
|
}
|
|
15840
16127
|
});
|
|
16128
|
+
await Promise.all([
|
|
16129
|
+
this.assertProofFresh(hyperbridge, sourceIProof),
|
|
16130
|
+
this.assertProofFresh(hyperbridge, destIProof)
|
|
16131
|
+
]);
|
|
15841
16132
|
const getRequestMessage = {
|
|
15842
16133
|
kind: "GetRequest",
|
|
15843
16134
|
requests: [getRequest],
|
|
@@ -15859,9 +16150,12 @@ var OrderCanceller = class {
|
|
|
15859
16150
|
status: "HYPERBRIDGE_FINALIZED",
|
|
15860
16151
|
metadata: statusUpdate.metadata
|
|
15861
16152
|
};
|
|
15862
|
-
await this.
|
|
15863
|
-
|
|
15864
|
-
|
|
16153
|
+
await this.removeRecoveryItems(
|
|
16154
|
+
storageKeys.destProof,
|
|
16155
|
+
storageKeys.getRequest,
|
|
16156
|
+
storageKeys.sourceProof,
|
|
16157
|
+
...legacyStorageKeys.flatMap((keys) => [keys.destProof, keys.getRequest, keys.sourceProof])
|
|
16158
|
+
);
|
|
15865
16159
|
return;
|
|
15866
16160
|
}
|
|
15867
16161
|
}
|
|
@@ -15878,9 +16172,11 @@ var OrderCanceller = class {
|
|
|
15878
16172
|
* @returns The native token dispatch fee in wei.
|
|
15879
16173
|
*/
|
|
15880
16174
|
async quoteCancelFromDest(order) {
|
|
15881
|
-
if (order.source === order.destination) return { nativeValue: 0n, relayerFee: 0n };
|
|
15882
|
-
const destStateMachine = normalizeStateMachineId(order.destination);
|
|
15883
16175
|
const sourceStateMachine = normalizeStateMachineId(order.source);
|
|
16176
|
+
const destStateMachine = normalizeStateMachineId(order.destination);
|
|
16177
|
+
if (sourceStateMachine === destStateMachine) {
|
|
16178
|
+
return { nativeValue: 0n, relayerFee: 0n };
|
|
16179
|
+
}
|
|
15884
16180
|
const destIntentGateway = this.ctx.dest.configService.getIntentGatewayAddress(destStateMachine);
|
|
15885
16181
|
const sourceIntentGateway = this.ctx.source.configService.getIntentGatewayAddress(sourceStateMachine);
|
|
15886
16182
|
const relayerFee = await this.estimateRelayerFee(sourceStateMachine, destStateMachine);
|
|
@@ -15918,11 +16214,13 @@ var OrderCanceller = class {
|
|
|
15918
16214
|
* @throws If the cancel transaction does not contain a `PostRequestEvent`.
|
|
15919
16215
|
*/
|
|
15920
16216
|
async *cancelOrderFromDest(order, indexerClient) {
|
|
15921
|
-
const
|
|
16217
|
+
const storageKeys = this.recoveryStorageKeys(order);
|
|
15922
16218
|
const destStateMachine = normalizeStateMachineId(order.destination);
|
|
15923
16219
|
const intentGatewayAddress = this.ctx.dest.configService.getIntentGatewayAddress(destStateMachine);
|
|
15924
|
-
|
|
15925
|
-
|
|
16220
|
+
const legacyStorageKeys = this.legacyRecoveryStorageKeys(order);
|
|
16221
|
+
let commitment = await this.getRecoveryItem(
|
|
16222
|
+
storageKeys.postCommitment,
|
|
16223
|
+
legacyStorageKeys.map((keys) => keys.postCommitment)
|
|
15926
16224
|
);
|
|
15927
16225
|
if (!commitment) {
|
|
15928
16226
|
const quote = await this.quoteCancelFromDest(order);
|
|
@@ -15947,7 +16245,7 @@ var OrderCanceller = class {
|
|
|
15947
16245
|
if (!postEvent) throw new Error("PostRequestEvent not found in cancel transaction receipt");
|
|
15948
16246
|
const postArgs = postEvent.args;
|
|
15949
16247
|
commitment = postRequestCommitment(postArgs).commitment;
|
|
15950
|
-
await this.ctx.cancellationStorage.setItem(
|
|
16248
|
+
await this.ctx.cancellationStorage.setItem(storageKeys.postCommitment, commitment);
|
|
15951
16249
|
}
|
|
15952
16250
|
const statusStream = indexerClient.postRequestStatusStream(commitment);
|
|
15953
16251
|
for await (const statusUpdate of statusStream) {
|
|
@@ -15981,7 +16279,10 @@ var OrderCanceller = class {
|
|
|
15981
16279
|
if (refundEvents.length === 0) {
|
|
15982
16280
|
throw new Error("EscrowRefunded event not found in source-chain delivery receipt");
|
|
15983
16281
|
}
|
|
15984
|
-
await this.
|
|
16282
|
+
await this.removeRecoveryItems(
|
|
16283
|
+
storageKeys.postCommitment,
|
|
16284
|
+
...legacyStorageKeys.map((keys) => keys.postCommitment)
|
|
16285
|
+
);
|
|
15985
16286
|
yield {
|
|
15986
16287
|
status: "CANCELLATION_COMPLETE",
|
|
15987
16288
|
blockNumber: statusUpdate.metadata.blockNumber,
|
|
@@ -16024,7 +16325,7 @@ var OrderCanceller = class {
|
|
|
16024
16325
|
const intentGatewayV2Address = this.ctx.dest.configService.getIntentGatewayAddress(
|
|
16025
16326
|
this.ctx.dest.config.stateMachineId
|
|
16026
16327
|
);
|
|
16027
|
-
const orderId = order
|
|
16328
|
+
const orderId = this.orderId(order);
|
|
16028
16329
|
const slotHash = await this.ctx.dest.client.readContract({
|
|
16029
16330
|
abi: ABI3,
|
|
16030
16331
|
address: intentGatewayV2Address,
|
|
@@ -16041,6 +16342,7 @@ var OrderCanceller = class {
|
|
|
16041
16342
|
yield { status: "DESTINATION_FINALIZED", proof };
|
|
16042
16343
|
return proof;
|
|
16043
16344
|
} catch (e) {
|
|
16345
|
+
if (MissingConsensusUpdateTimeError.isError(e)) throw e;
|
|
16044
16346
|
lastFailedHeight = latestHeight;
|
|
16045
16347
|
await sleep(1e4);
|
|
16046
16348
|
}
|
|
@@ -16071,6 +16373,7 @@ var OrderCanceller = class {
|
|
|
16071
16373
|
this.logger.info(`Unsigned GET ${commitment} submitted; waiting for Hyperbridge response receipt`);
|
|
16072
16374
|
await sleep(3e4);
|
|
16073
16375
|
} catch (error) {
|
|
16376
|
+
if (MissingConsensusUpdateTimeError.isError(error)) throw error;
|
|
16074
16377
|
this.logger.warn(
|
|
16075
16378
|
`Unsigned GET submit failed for ${commitment}; polling response receipt before failing: ${String(error)}`
|
|
16076
16379
|
);
|
|
@@ -16079,14 +16382,128 @@ var OrderCanceller = class {
|
|
|
16079
16382
|
await this.pollDeliveredReceipt(hyperbridge, commitment);
|
|
16080
16383
|
this.logger.info(`Confirmed Hyperbridge GET delivery for ${commitment}`);
|
|
16081
16384
|
} catch (error) {
|
|
16385
|
+
if (MissingConsensusUpdateTimeError.isError(error)) throw error;
|
|
16082
16386
|
const message2 = `Failed to deliver GET request to Hyperbridge; no response receipt found for ${commitment}: ${String(error)}`;
|
|
16083
16387
|
this.logger.error(message2);
|
|
16084
16388
|
throw new Error(message2);
|
|
16085
16389
|
}
|
|
16086
16390
|
}
|
|
16391
|
+
/** Verify that Hyperbridge still retains the consensus update for a proof. */
|
|
16392
|
+
async assertProofFresh(hyperbridge, proof) {
|
|
16393
|
+
await retryPromise(
|
|
16394
|
+
() => hyperbridge.stateMachineUpdateTime({
|
|
16395
|
+
height: proof.height,
|
|
16396
|
+
id: {
|
|
16397
|
+
stateId: parseStateMachineId(proof.stateMachine).stateId,
|
|
16398
|
+
consensusStateId: proof.consensusStateId
|
|
16399
|
+
}
|
|
16400
|
+
}),
|
|
16401
|
+
{
|
|
16402
|
+
maxRetries: _OrderCanceller.PROOF_FRESHNESS_MAX_RETRIES,
|
|
16403
|
+
backoffMs: _OrderCanceller.PROOF_FRESHNESS_BACKOFF_MS,
|
|
16404
|
+
logger: this.logger,
|
|
16405
|
+
logMessage: `Checking consensus update time for proof at height ${proof.height}`,
|
|
16406
|
+
shouldRetry: (error) => !MissingConsensusUpdateTimeError.isError(error)
|
|
16407
|
+
}
|
|
16408
|
+
);
|
|
16409
|
+
}
|
|
16410
|
+
/**
|
|
16411
|
+
* Drops the source-initiated GET recovery checkpoint after Hyperbridge prunes
|
|
16412
|
+
* a consensus update required by that recovery attempt.
|
|
16413
|
+
*/
|
|
16414
|
+
async clearGetRecoveryCache(order) {
|
|
16415
|
+
const keys = this.recoveryStorageKeys(order);
|
|
16416
|
+
const legacyStorageKeys = this.legacyRecoveryStorageKeys(order);
|
|
16417
|
+
await this.removeRecoveryItems(
|
|
16418
|
+
keys.destProof,
|
|
16419
|
+
keys.sourceProof,
|
|
16420
|
+
keys.getRequest,
|
|
16421
|
+
...legacyStorageKeys.flatMap((legacyKeys) => [
|
|
16422
|
+
legacyKeys.destProof,
|
|
16423
|
+
legacyKeys.sourceProof,
|
|
16424
|
+
legacyKeys.getRequest
|
|
16425
|
+
])
|
|
16426
|
+
);
|
|
16427
|
+
}
|
|
16428
|
+
/**
|
|
16429
|
+
* Returns the pair-scoped storage keys used to resume cancellation recovery
|
|
16430
|
+
* for an order.
|
|
16431
|
+
*
|
|
16432
|
+
* @param order - The order whose source/destination recovery state is stored.
|
|
16433
|
+
*/
|
|
16434
|
+
recoveryStorageKeys(order) {
|
|
16435
|
+
const orderId = this.orderId(order);
|
|
16436
|
+
return {
|
|
16437
|
+
destProof: STORAGE_KEYS.destProof(orderId, order.source, order.destination),
|
|
16438
|
+
getRequest: STORAGE_KEYS.getRequest(orderId, order.source, order.destination),
|
|
16439
|
+
sourceProof: STORAGE_KEYS.sourceProof(orderId, order.source, order.destination),
|
|
16440
|
+
postCommitment: STORAGE_KEYS.postCommitment(orderId, order.source, order.destination)
|
|
16441
|
+
};
|
|
16442
|
+
}
|
|
16443
|
+
/** Older SDK key shapes, checked once and migrated to the normalized pair-scoped key. */
|
|
16444
|
+
legacyRecoveryStorageKeys(order) {
|
|
16445
|
+
const orderId = this.orderId(order);
|
|
16446
|
+
return [
|
|
16447
|
+
{
|
|
16448
|
+
destProof: LEGACY_STORAGE_KEYS.destProof(orderId, order.source, order.destination),
|
|
16449
|
+
getRequest: LEGACY_STORAGE_KEYS.getRequest(orderId, order.source, order.destination),
|
|
16450
|
+
sourceProof: LEGACY_STORAGE_KEYS.sourceProof(orderId, order.source, order.destination),
|
|
16451
|
+
postCommitment: LEGACY_STORAGE_KEYS.postCommitment(orderId, order.source, order.destination)
|
|
16452
|
+
},
|
|
16453
|
+
{
|
|
16454
|
+
destProof: LEGACY_STORAGE_KEYS.destProof(orderId),
|
|
16455
|
+
getRequest: LEGACY_STORAGE_KEYS.getRequest(orderId),
|
|
16456
|
+
sourceProof: LEGACY_STORAGE_KEYS.sourceProof(orderId),
|
|
16457
|
+
postCommitment: LEGACY_STORAGE_KEYS.postCommitment(orderId)
|
|
16458
|
+
}
|
|
16459
|
+
];
|
|
16460
|
+
}
|
|
16461
|
+
async getRecoveryItem(currentKey, legacyKeys) {
|
|
16462
|
+
const current = await this.ctx.cancellationStorage.getItem(currentKey);
|
|
16463
|
+
if (current) return current;
|
|
16464
|
+
for (const legacyKey of new Set(legacyKeys)) {
|
|
16465
|
+
if (legacyKey === currentKey) continue;
|
|
16466
|
+
const legacy = await this.ctx.cancellationStorage.getItem(legacyKey);
|
|
16467
|
+
if (!legacy) continue;
|
|
16468
|
+
await this.ctx.cancellationStorage.setItem(currentKey, legacy);
|
|
16469
|
+
await this.ctx.cancellationStorage.removeItem(legacyKey);
|
|
16470
|
+
return legacy;
|
|
16471
|
+
}
|
|
16472
|
+
return null;
|
|
16473
|
+
}
|
|
16474
|
+
async removeRecoveryItems(...keys) {
|
|
16475
|
+
await Promise.all(
|
|
16476
|
+
[...new Set(keys)].map((key) => this.ctx.cancellationStorage.removeItem(key))
|
|
16477
|
+
);
|
|
16478
|
+
}
|
|
16479
|
+
/**
|
|
16480
|
+
* Returns the order identifier required to persist or clear recovery state.
|
|
16481
|
+
*
|
|
16482
|
+
* @param order - The order being cancelled.
|
|
16483
|
+
* @throws If the order has no identifier.
|
|
16484
|
+
*/
|
|
16485
|
+
orderId(order) {
|
|
16486
|
+
if (!order.id) throw new Error("An order id is required to recover cancellation");
|
|
16487
|
+
return order.id;
|
|
16488
|
+
}
|
|
16489
|
+
/**
|
|
16490
|
+
* Reads the Hyperbridge response receipt for a GET request commitment.
|
|
16491
|
+
*
|
|
16492
|
+
* @param hyperbridge - Hyperbridge chain client used to query the receipt.
|
|
16493
|
+
* @param commitment - Commitment of the GET request.
|
|
16494
|
+
* @returns The receipt commitment when delivered, otherwise `undefined`.
|
|
16495
|
+
*/
|
|
16087
16496
|
async queryDeliveredReceipt(hyperbridge, commitment) {
|
|
16088
16497
|
return hyperbridge.queryResponseReceipt(commitment);
|
|
16089
16498
|
}
|
|
16499
|
+
/**
|
|
16500
|
+
* Polls Hyperbridge until it records a response receipt for the GET request.
|
|
16501
|
+
*
|
|
16502
|
+
* @param hyperbridge - Hyperbridge chain client used to query the receipt.
|
|
16503
|
+
* @param commitment - Commitment of the GET request.
|
|
16504
|
+
* @returns The delivered response receipt commitment.
|
|
16505
|
+
* @throws If no receipt is observed within the configured retry limit.
|
|
16506
|
+
*/
|
|
16090
16507
|
async pollDeliveredReceipt(hyperbridge, commitment) {
|
|
16091
16508
|
this.logger.info(`Polling Hyperbridge GET response receipt for ${commitment}`);
|
|
16092
16509
|
return retryPromise(
|
|
@@ -17299,6 +17716,178 @@ var OrderStatusChecker = class {
|
|
|
17299
17716
|
return true;
|
|
17300
17717
|
}
|
|
17301
17718
|
};
|
|
17719
|
+
var COMMITMENT_PATTERN = /^0x[0-9a-f]{64}$/i;
|
|
17720
|
+
var LiquidityEngine = class {
|
|
17721
|
+
/**
|
|
17722
|
+
* @param queryClient - Nexus GraphQL client attached to the gateway.
|
|
17723
|
+
* @param chainConfigService - Resolves token decimals for formatted results.
|
|
17724
|
+
*/
|
|
17725
|
+
constructor(queryClient, chainConfigService) {
|
|
17726
|
+
this.queryClient = queryClient;
|
|
17727
|
+
this.chainConfigService = chainConfigService;
|
|
17728
|
+
}
|
|
17729
|
+
queryClient;
|
|
17730
|
+
chainConfigService;
|
|
17731
|
+
/**
|
|
17732
|
+
* Retrieves the newest directional Phantom snapshot for a pair and its
|
|
17733
|
+
* indexed output-token liquidity.
|
|
17734
|
+
*
|
|
17735
|
+
* Nexus filters balances to the canonical output token, then aggregates them
|
|
17736
|
+
* overall and by chain. The returned amounts are decimal strings: the total
|
|
17737
|
+
* uses the canonical Base output-token decimals, while each chain group uses
|
|
17738
|
+
* that chain's token decimals. They describe `snapshotTime`, not live
|
|
17739
|
+
* reservations or fill guarantees.
|
|
17740
|
+
*
|
|
17741
|
+
* @param params - Canonical Phantom-market input and output token addresses.
|
|
17742
|
+
* @returns The latest snapshot, or `undefined` if Nexus has no snapshot for
|
|
17743
|
+
* the directional pair.
|
|
17744
|
+
* @throws {InvalidAvailableLiquiditySnapshotError} If Nexus returns malformed
|
|
17745
|
+
* or internally inconsistent snapshot data.
|
|
17746
|
+
*/
|
|
17747
|
+
async getAvailableLiquiditySnapshot(params) {
|
|
17748
|
+
const tokenIn = normalizeEvmAddress(params.tokenIn, "tokenIn");
|
|
17749
|
+
const tokenOut = normalizeEvmAddress(params.tokenOut, "tokenOut");
|
|
17750
|
+
const response = await this.queryClient.request(
|
|
17751
|
+
LATEST_PHANTOM_ORDER_LIQUIDITY_SNAPSHOT,
|
|
17752
|
+
{ tokenA: tokenIn, tokenB: tokenOut }
|
|
17753
|
+
);
|
|
17754
|
+
const node = response?.phantomOrderPriceSnapshots?.nodes?.[0];
|
|
17755
|
+
if (!node) return;
|
|
17756
|
+
const commitment = node.commitment.toLowerCase();
|
|
17757
|
+
if (!COMMITMENT_PATTERN.test(commitment)) {
|
|
17758
|
+
throw new InvalidAvailableLiquiditySnapshotError(commitment || "<missing>", "commitment is not bytes32 hex");
|
|
17759
|
+
}
|
|
17760
|
+
if (node.tokenA.toLowerCase() !== tokenIn || node.tokenB.toLowerCase() !== tokenOut) {
|
|
17761
|
+
throw new InvalidAvailableLiquiditySnapshotError(commitment, "snapshot token pair does not match the query");
|
|
17762
|
+
}
|
|
17763
|
+
const snapshotTime = new Date(dateStringtoTimestamp(node.snapshotTime));
|
|
17764
|
+
if (Number.isNaN(snapshotTime.getTime())) {
|
|
17765
|
+
throw new InvalidAvailableLiquiditySnapshotError(commitment, "snapshotTime is invalid");
|
|
17766
|
+
}
|
|
17767
|
+
const { totalLiquidity, providerCount, liquidityByChain } = await this.querySnapshotLiquidityAggregates({
|
|
17768
|
+
commitment,
|
|
17769
|
+
tokenAddress: tokenOut
|
|
17770
|
+
});
|
|
17771
|
+
return {
|
|
17772
|
+
totalLiquidity: this.formatLiquidity(totalLiquidity, "EVM-8453" /* BASE_MAINNET */, tokenOut, commitment),
|
|
17773
|
+
providerCount,
|
|
17774
|
+
tokenAddress: tokenOut,
|
|
17775
|
+
snapshotTime,
|
|
17776
|
+
liquidityByChain: liquidityByChain.map((group) => ({
|
|
17777
|
+
...group,
|
|
17778
|
+
totalLiquidity: this.formatLiquidity(group.totalLiquidity, group.chain, group.tokenAddress, commitment)
|
|
17779
|
+
}))
|
|
17780
|
+
};
|
|
17781
|
+
}
|
|
17782
|
+
/**
|
|
17783
|
+
* Requests server-side sums and distinct provider counts for one immutable
|
|
17784
|
+
* snapshot/output-token pair, including chain-level aggregate groups.
|
|
17785
|
+
*
|
|
17786
|
+
* `commitment` uniquely identifies the selected snapshot
|
|
17787
|
+
*/
|
|
17788
|
+
async querySnapshotLiquidityAggregates(params) {
|
|
17789
|
+
const response = await this.queryClient.request(
|
|
17790
|
+
LIQUIDITY_PROVIDER_BALANCES,
|
|
17791
|
+
{ commitment: params.commitment, tokenAddress: params.tokenAddress }
|
|
17792
|
+
);
|
|
17793
|
+
const connection = response?.liquidityProviderBalances;
|
|
17794
|
+
const aggregates = connection?.aggregates;
|
|
17795
|
+
if (!connection || !aggregates) {
|
|
17796
|
+
throw new InvalidAvailableLiquiditySnapshotError(
|
|
17797
|
+
params.commitment,
|
|
17798
|
+
"liquidityProviderBalances aggregates are missing"
|
|
17799
|
+
);
|
|
17800
|
+
}
|
|
17801
|
+
const totalLiquidity = parseSnapshotBigInt(aggregates.sum.balance ?? "0", params.commitment, "total balance");
|
|
17802
|
+
const providerCount = parseProviderCount(aggregates.distinctCount.providerId, params.commitment, "total");
|
|
17803
|
+
const liquidityByChain = connection.groupedAggregates.map((group, index) => {
|
|
17804
|
+
const [chain, tokenAddress] = group.keys;
|
|
17805
|
+
if (!chain?.trim() || !tokenAddress) {
|
|
17806
|
+
throw new InvalidAvailableLiquiditySnapshotError(
|
|
17807
|
+
params.commitment,
|
|
17808
|
+
`liquidity group ${index} has invalid keys`
|
|
17809
|
+
);
|
|
17810
|
+
}
|
|
17811
|
+
const normalizedTokenAddress = normalizeIndexedLiquidityAddress(
|
|
17812
|
+
tokenAddress,
|
|
17813
|
+
params.commitment,
|
|
17814
|
+
`liquidity group ${index} tokenAddress`
|
|
17815
|
+
);
|
|
17816
|
+
if (normalizedTokenAddress !== params.tokenAddress) {
|
|
17817
|
+
throw new InvalidAvailableLiquiditySnapshotError(
|
|
17818
|
+
params.commitment,
|
|
17819
|
+
`liquidity group ${index} tokenAddress does not match the snapshot output token`
|
|
17820
|
+
);
|
|
17821
|
+
}
|
|
17822
|
+
return {
|
|
17823
|
+
chain: chain.trim(),
|
|
17824
|
+
tokenAddress: normalizedTokenAddress,
|
|
17825
|
+
totalLiquidity: parseSnapshotBigInt(
|
|
17826
|
+
group.sum.balance ?? "0",
|
|
17827
|
+
params.commitment,
|
|
17828
|
+
`liquidity group ${index} balance`
|
|
17829
|
+
),
|
|
17830
|
+
providerCount: parseProviderCount(
|
|
17831
|
+
group.distinctCount.providerId,
|
|
17832
|
+
params.commitment,
|
|
17833
|
+
`liquidity group ${index}`
|
|
17834
|
+
)
|
|
17835
|
+
};
|
|
17836
|
+
});
|
|
17837
|
+
const groupedTotal = liquidityByChain.reduce((sum, group) => sum + group.totalLiquidity, 0n);
|
|
17838
|
+
if (groupedTotal !== totalLiquidity) {
|
|
17839
|
+
throw new InvalidAvailableLiquiditySnapshotError(
|
|
17840
|
+
params.commitment,
|
|
17841
|
+
"grouped liquidity does not match the total liquidity"
|
|
17842
|
+
);
|
|
17843
|
+
}
|
|
17844
|
+
return { totalLiquidity, providerCount, liquidityByChain };
|
|
17845
|
+
}
|
|
17846
|
+
/** Formats a raw amount using the configured decimals for its chain/token. */
|
|
17847
|
+
formatLiquidity(amount, chain, tokenAddress, commitment) {
|
|
17848
|
+
const decimals = this.chainConfigService.getAssetMetadataByAddress(chain, tokenAddress)?.decimals;
|
|
17849
|
+
if (decimals === void 0) {
|
|
17850
|
+
throw new InvalidAvailableLiquiditySnapshotError(
|
|
17851
|
+
commitment,
|
|
17852
|
+
`token decimals are not configured for ${tokenAddress} on ${chain}`
|
|
17853
|
+
);
|
|
17854
|
+
}
|
|
17855
|
+
return formatUnits(amount, decimals);
|
|
17856
|
+
}
|
|
17857
|
+
};
|
|
17858
|
+
var InvalidAvailableLiquiditySnapshotError = class extends Error {
|
|
17859
|
+
/** Creates an error that identifies the invalid snapshot and field/reason. */
|
|
17860
|
+
constructor(commitment, reason) {
|
|
17861
|
+
super(`Invalid available-liquidity snapshot ${commitment}: ${reason}`);
|
|
17862
|
+
this.name = "InvalidAvailableLiquiditySnapshotError";
|
|
17863
|
+
}
|
|
17864
|
+
};
|
|
17865
|
+
function parseSnapshotBigInt(value, commitment, field) {
|
|
17866
|
+
try {
|
|
17867
|
+
const amount = BigInt(value);
|
|
17868
|
+
if (amount < 0n) {
|
|
17869
|
+
throw new InvalidAvailableLiquiditySnapshotError(commitment, `${field} cannot be negative`);
|
|
17870
|
+
}
|
|
17871
|
+
return amount;
|
|
17872
|
+
} catch (error) {
|
|
17873
|
+
if (error instanceof InvalidAvailableLiquiditySnapshotError) throw error;
|
|
17874
|
+
throw new InvalidAvailableLiquiditySnapshotError(commitment, `${field} is not an integer`);
|
|
17875
|
+
}
|
|
17876
|
+
}
|
|
17877
|
+
function parseProviderCount(value, commitment, field) {
|
|
17878
|
+
const count = Number(value);
|
|
17879
|
+
if (!Number.isSafeInteger(count) || count < 0) {
|
|
17880
|
+
throw new InvalidAvailableLiquiditySnapshotError(commitment, `${field} provider count is invalid`);
|
|
17881
|
+
}
|
|
17882
|
+
return count;
|
|
17883
|
+
}
|
|
17884
|
+
function normalizeIndexedLiquidityAddress(address, commitment, field) {
|
|
17885
|
+
try {
|
|
17886
|
+
return normalizeEvmAddress(address, field);
|
|
17887
|
+
} catch {
|
|
17888
|
+
throw new InvalidAvailableLiquiditySnapshotError(commitment, `${field} is not a valid EVM address`);
|
|
17889
|
+
}
|
|
17890
|
+
}
|
|
17302
17891
|
|
|
17303
17892
|
// src/protocols/intents/quote/types.ts
|
|
17304
17893
|
var UnsupportedIntentQuoteStrategyError = class extends Error {
|
|
@@ -17310,15 +17899,67 @@ var UnsupportedIntentQuoteStrategyError = class extends Error {
|
|
|
17310
17899
|
var UnsupportedIntentQuotePairError = class extends Error {
|
|
17311
17900
|
constructor(params) {
|
|
17312
17901
|
super(
|
|
17313
|
-
`No Uniswap v4 pool config found for ${params.tokenIn
|
|
17902
|
+
`No ${params.quoteSource ?? "Uniswap v4 pool config"} found for ${params.tokenIn} -> ${params.tokenOut} on ${params.source} -> ${params.destination}`
|
|
17314
17903
|
);
|
|
17315
17904
|
this.name = "UnsupportedIntentQuotePairError";
|
|
17316
17905
|
}
|
|
17317
17906
|
};
|
|
17907
|
+
var PhantomSnapshotUnavailableError = class extends Error {
|
|
17908
|
+
constructor(tokenA, tokenB) {
|
|
17909
|
+
super(`No Phantom order price snapshot found for ${tokenA} -> ${tokenB}`);
|
|
17910
|
+
this.name = "PhantomSnapshotUnavailableError";
|
|
17911
|
+
}
|
|
17912
|
+
};
|
|
17913
|
+
var InvalidPhantomSnapshotError = class extends Error {
|
|
17914
|
+
constructor(commitment, reason) {
|
|
17915
|
+
super(`Invalid Phantom order price snapshot ${commitment}: ${reason}`);
|
|
17916
|
+
this.name = "InvalidPhantomSnapshotError";
|
|
17917
|
+
}
|
|
17918
|
+
};
|
|
17919
|
+
var BPS_DENOMINATOR = 10000n;
|
|
17920
|
+
function validateQuoteParams(params) {
|
|
17921
|
+
const hasAmountIn = params.amountIn !== void 0;
|
|
17922
|
+
const hasAmountOut = params.amountOut !== void 0;
|
|
17923
|
+
if (hasAmountIn === hasAmountOut) throw new Error("Provide exactly one of amountIn or amountOut");
|
|
17924
|
+
if (params.amountIn !== void 0 && params.amountIn <= 0n) throw new Error("amountIn must be greater than zero");
|
|
17925
|
+
if (params.amountOut !== void 0 && params.amountOut <= 0n) throw new Error("amountOut must be greater than zero");
|
|
17926
|
+
if (params.tokenIn.toLowerCase() === params.tokenOut.toLowerCase()) {
|
|
17927
|
+
throw new Error("tokenIn and tokenOut cannot be the same");
|
|
17928
|
+
}
|
|
17929
|
+
}
|
|
17930
|
+
async function readProtocolFeeBps(chainConfigService, source) {
|
|
17931
|
+
const gatewayAddress = chainConfigService.getIntentGatewayAddress(source.stateMachineId);
|
|
17932
|
+
if (!gatewayAddress || gatewayAddress === "0x" || gatewayAddress === zeroAddress) {
|
|
17933
|
+
throw new Error(`IntentGatewayV2 is not configured for chain ${source.stateMachineId}`);
|
|
17934
|
+
}
|
|
17935
|
+
const gatewayParams = await source.client.readContract({
|
|
17936
|
+
address: gatewayAddress,
|
|
17937
|
+
abi: IntentGatewayV2_default.ABI,
|
|
17938
|
+
functionName: "params"
|
|
17939
|
+
});
|
|
17940
|
+
const protocolFeeBps = Array.isArray(gatewayParams) ? BigInt(gatewayParams[4]) : BigInt(gatewayParams.protocolFeeBps ?? 0);
|
|
17941
|
+
if (protocolFeeBps < 0n || protocolFeeBps >= BPS_DENOMINATOR) {
|
|
17942
|
+
throw new Error(`Invalid IntentGateway protocol fee: ${protocolFeeBps} bps`);
|
|
17943
|
+
}
|
|
17944
|
+
return protocolFeeBps;
|
|
17945
|
+
}
|
|
17946
|
+
function deductProtocolFee(amount, protocolFeeBps) {
|
|
17947
|
+
if (protocolFeeBps <= 0n) return amount;
|
|
17948
|
+
const fee = amount * protocolFeeBps / BPS_DENOMINATOR;
|
|
17949
|
+
return amount - fee;
|
|
17950
|
+
}
|
|
17951
|
+
function grossUpForProtocolFee(netAmount, protocolFeeBps) {
|
|
17952
|
+
if (protocolFeeBps <= 0n) return netAmount;
|
|
17953
|
+
if (protocolFeeBps >= BPS_DENOMINATOR) throw new Error("protocolFeeBps must be less than 10,000");
|
|
17954
|
+
return divCeil(netAmount * BPS_DENOMINATOR, BPS_DENOMINATOR - protocolFeeBps);
|
|
17955
|
+
}
|
|
17956
|
+
function divCeil(numerator, denominator) {
|
|
17957
|
+
if (denominator <= 0n) throw new Error("denominator must be greater than zero");
|
|
17958
|
+
return (numerator + denominator - 1n) / denominator;
|
|
17959
|
+
}
|
|
17318
17960
|
|
|
17319
17961
|
// src/protocols/intents/quote/uniswapV4.ts
|
|
17320
17962
|
var UNISWAP_INTENT_QUOTE_CHAIN = "EVM-8453" /* BASE_MAINNET */;
|
|
17321
|
-
var BPS_DENOMINATOR = 10000n;
|
|
17322
17963
|
var UniswapV4IntentQuoteStrategy = class {
|
|
17323
17964
|
constructor(chainConfigService) {
|
|
17324
17965
|
this.chainConfigService = chainConfigService;
|
|
@@ -17326,10 +17967,10 @@ var UniswapV4IntentQuoteStrategy = class {
|
|
|
17326
17967
|
chainConfigService;
|
|
17327
17968
|
baseQuoteClient;
|
|
17328
17969
|
async quote(params, source, destination) {
|
|
17329
|
-
|
|
17330
|
-
const protocolFeeBps = await
|
|
17970
|
+
validateQuoteParams(params);
|
|
17971
|
+
const protocolFeeBps = await readProtocolFeeBps(this.chainConfigService, source);
|
|
17331
17972
|
const quoteClient = this.resolveQuoteClient(source, destination);
|
|
17332
|
-
const poolConfig = this.resolvePoolConfig(params, source.stateMachineId,
|
|
17973
|
+
const poolConfig = this.resolvePoolConfig(params, source.stateMachineId, destination.stateMachineId);
|
|
17333
17974
|
return params.amountIn !== void 0 ? this.quoteExactInput({ params, client: quoteClient, protocolFeeBps, poolConfig }) : this.quoteExactOutput({ params, client: quoteClient, protocolFeeBps, poolConfig });
|
|
17334
17975
|
}
|
|
17335
17976
|
resolveQuoteClient(source, destination) {
|
|
@@ -17345,34 +17986,11 @@ var UniswapV4IntentQuoteStrategy = class {
|
|
|
17345
17986
|
this.baseQuoteClient = baseQuoteClient;
|
|
17346
17987
|
return baseQuoteClient;
|
|
17347
17988
|
}
|
|
17348
|
-
validateQuoteParams(params) {
|
|
17349
|
-
const hasAmountIn = params.amountIn !== void 0;
|
|
17350
|
-
const hasAmountOut = params.amountOut !== void 0;
|
|
17351
|
-
if (hasAmountIn === hasAmountOut) throw new Error("Provide exactly one of amountIn or amountOut");
|
|
17352
|
-
if (hasAmountIn && params.amountIn <= 0n) throw new Error("amountIn must be greater than zero");
|
|
17353
|
-
if (hasAmountOut && params.amountOut <= 0n) throw new Error("amountOut must be greater than zero");
|
|
17354
|
-
if (params.tokenIn.address.toLowerCase() === params.tokenOut.address.toLowerCase()) {
|
|
17355
|
-
throw new Error("tokenIn and tokenOut cannot be the same");
|
|
17356
|
-
}
|
|
17357
|
-
}
|
|
17358
|
-
async readProtocolFeeBps(client, chain) {
|
|
17359
|
-
const gatewayAddress = this.chainConfigService.getIntentGatewayAddress(chain);
|
|
17360
|
-
if (!gatewayAddress || gatewayAddress === "0x" || gatewayAddress === zeroAddress) {
|
|
17361
|
-
throw new Error(`IntentGatewayV2 is not configured for chain ${chain}`);
|
|
17362
|
-
}
|
|
17363
|
-
const gatewayParams = await client.readContract({
|
|
17364
|
-
address: gatewayAddress,
|
|
17365
|
-
abi: IntentGatewayV2_default.ABI,
|
|
17366
|
-
functionName: "params"
|
|
17367
|
-
});
|
|
17368
|
-
if (isGatewayParamsTuple(gatewayParams)) return BigInt(gatewayParams[4]);
|
|
17369
|
-
return BigInt(gatewayParams.protocolFeeBps ?? 0);
|
|
17370
|
-
}
|
|
17371
17989
|
resolvePoolConfig(params, source, destination) {
|
|
17372
17990
|
const override = params.uniswapV4?.poolKey;
|
|
17373
17991
|
if (override) {
|
|
17374
17992
|
const poolKey = normalizePoolKey(override);
|
|
17375
|
-
const tokenInForQuote = getAddress(override.currencyIn ?? params.tokenIn
|
|
17993
|
+
const tokenInForQuote = getAddress(override.currencyIn ?? params.tokenIn);
|
|
17376
17994
|
if (tokenInForQuote !== poolKey.currency0 && tokenInForQuote !== poolKey.currency1) {
|
|
17377
17995
|
throw new Error(
|
|
17378
17996
|
`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.`
|
|
@@ -17380,11 +17998,11 @@ var UniswapV4IntentQuoteStrategy = class {
|
|
|
17380
17998
|
}
|
|
17381
17999
|
return {
|
|
17382
18000
|
poolKey,
|
|
17383
|
-
quoterAddress: this.resolveQuoterAddress(
|
|
18001
|
+
quoterAddress: this.resolveQuoterAddress(UNISWAP_INTENT_QUOTE_CHAIN, override.quoterAddress),
|
|
17384
18002
|
tokenInForQuote
|
|
17385
18003
|
};
|
|
17386
18004
|
}
|
|
17387
|
-
const poolConfig = this.resolveConfiguredPool(params, destination);
|
|
18005
|
+
const poolConfig = this.resolveConfiguredPool(params, source, destination, UNISWAP_INTENT_QUOTE_CHAIN);
|
|
17388
18006
|
if (poolConfig) return poolConfig;
|
|
17389
18007
|
throw new UnsupportedIntentQuotePairError({
|
|
17390
18008
|
source,
|
|
@@ -17393,12 +18011,12 @@ var UniswapV4IntentQuoteStrategy = class {
|
|
|
17393
18011
|
tokenOut: params.tokenOut
|
|
17394
18012
|
});
|
|
17395
18013
|
}
|
|
17396
|
-
resolveConfiguredPool(params,
|
|
17397
|
-
for (const pool of this.chainConfigService.getUniswapV4PoolConfigs(
|
|
17398
|
-
const resolvedPool = this.resolveConfiguredPoolTokens(
|
|
18014
|
+
resolveConfiguredPool(params, sourceChain, destinationChain, quoteChain) {
|
|
18015
|
+
for (const pool of this.chainConfigService.getUniswapV4PoolConfigs(quoteChain)) {
|
|
18016
|
+
const resolvedPool = this.resolveConfiguredPoolTokens(quoteChain, pool);
|
|
17399
18017
|
if (!resolvedPool) continue;
|
|
17400
|
-
const tokenInForQuote = matchPoolToken(params.tokenIn, resolvedPool);
|
|
17401
|
-
const tokenOutForQuote = matchPoolToken(params.tokenOut, resolvedPool);
|
|
18018
|
+
const tokenInForQuote = this.matchPoolToken(params.tokenIn, sourceChain, resolvedPool);
|
|
18019
|
+
const tokenOutForQuote = this.matchPoolToken(params.tokenOut, destinationChain, resolvedPool);
|
|
17402
18020
|
if (!tokenInForQuote || !tokenOutForQuote || tokenInForQuote.symbol === tokenOutForQuote.symbol) continue;
|
|
17403
18021
|
const { currency0, currency1 } = sortCurrencies(resolvedPool[0].address, resolvedPool[1].address);
|
|
17404
18022
|
return {
|
|
@@ -17409,7 +18027,7 @@ var UniswapV4IntentQuoteStrategy = class {
|
|
|
17409
18027
|
tickSpacing: pool.tickSpacing,
|
|
17410
18028
|
hooks: getAddress(pool.hooks ?? zeroAddress)
|
|
17411
18029
|
},
|
|
17412
|
-
quoterAddress: this.resolveQuoterAddress(
|
|
18030
|
+
quoterAddress: this.resolveQuoterAddress(quoteChain),
|
|
17413
18031
|
tokenInForQuote: tokenInForQuote.address
|
|
17414
18032
|
};
|
|
17415
18033
|
}
|
|
@@ -17432,8 +18050,18 @@ var UniswapV4IntentQuoteStrategy = class {
|
|
|
17432
18050
|
if (!address || address === "0x") return null;
|
|
17433
18051
|
return { symbol, address: getAddress(address) };
|
|
17434
18052
|
}
|
|
18053
|
+
matchPoolToken(tokenAddress, orderChain, poolTokens) {
|
|
18054
|
+
const addressMatch = poolTokens.find(
|
|
18055
|
+
(poolToken) => poolToken.address.toLowerCase() === tokenAddress.toLowerCase()
|
|
18056
|
+
);
|
|
18057
|
+
if (addressMatch) return addressMatch;
|
|
18058
|
+
const metadata = this.chainConfigService.getAssetMetadataByAddress(orderChain, tokenAddress);
|
|
18059
|
+
if (!metadata) return null;
|
|
18060
|
+
return poolTokens.find((poolToken) => poolToken.symbol === metadata.symbol) ?? null;
|
|
18061
|
+
}
|
|
17435
18062
|
async quoteExactInput(args) {
|
|
17436
18063
|
const amountIn = args.params.amountIn;
|
|
18064
|
+
if (amountIn === void 0) throw new Error("amountIn is required for an exact-input quote");
|
|
17437
18065
|
const swapAmountIn = deductProtocolFee(amountIn, args.protocolFeeBps);
|
|
17438
18066
|
const amountOut = await this.readV4QuoteExactInput(args.client, args.poolConfig, swapAmountIn);
|
|
17439
18067
|
return {
|
|
@@ -17451,6 +18079,7 @@ var UniswapV4IntentQuoteStrategy = class {
|
|
|
17451
18079
|
}
|
|
17452
18080
|
async quoteExactOutput(args) {
|
|
17453
18081
|
const amountOut = args.params.amountOut;
|
|
18082
|
+
if (amountOut === void 0) throw new Error("amountOut is required for an exact-output quote");
|
|
17454
18083
|
const swapAmountIn = await this.readV4QuoteExactOutput(args.client, args.poolConfig, amountOut);
|
|
17455
18084
|
const amountIn = grossUpForProtocolFee(swapAmountIn, args.protocolFeeBps);
|
|
17456
18085
|
return {
|
|
@@ -17529,34 +18158,133 @@ function sortCurrencies(tokenIn, tokenOut) {
|
|
|
17529
18158
|
const output = getAddress(tokenOut);
|
|
17530
18159
|
return BigInt(input) < BigInt(output) ? { currency0: input, currency1: output } : { currency0: output, currency1: input };
|
|
17531
18160
|
}
|
|
17532
|
-
function matchPoolToken(token, poolTokens) {
|
|
17533
|
-
const tokenAddress = token.address.toLowerCase();
|
|
17534
|
-
const addressMatch = poolTokens.find((poolToken) => poolToken.address.toLowerCase() === tokenAddress);
|
|
17535
|
-
if (addressMatch) return addressMatch;
|
|
17536
|
-
const tokenSymbol = token.symbol?.toUpperCase();
|
|
17537
|
-
if (!tokenSymbol) return null;
|
|
17538
|
-
return poolTokens.find((poolToken) => poolToken.symbol.toUpperCase() === tokenSymbol) ?? null;
|
|
17539
|
-
}
|
|
17540
18161
|
function getZeroForOne(tokenIn, poolKey) {
|
|
17541
18162
|
return getAddress(tokenIn).toLowerCase() === getAddress(poolKey.currency0).toLowerCase();
|
|
17542
18163
|
}
|
|
17543
|
-
|
|
17544
|
-
|
|
17545
|
-
|
|
17546
|
-
|
|
17547
|
-
|
|
17548
|
-
|
|
17549
|
-
|
|
17550
|
-
}
|
|
17551
|
-
|
|
17552
|
-
|
|
17553
|
-
|
|
18164
|
+
|
|
18165
|
+
// src/protocols/intents/quote/phantomSnapshot.ts
|
|
18166
|
+
var PHANTOM_INTENT_QUOTE_CHAIN = "EVM-8453" /* BASE_MAINNET */;
|
|
18167
|
+
var BASE_SNAPSHOT_ASSET_BY_ORDER_ASSET = {
|
|
18168
|
+
USDC: "USDC",
|
|
18169
|
+
USDT: "USDC",
|
|
18170
|
+
cNGN: "cNGN"
|
|
18171
|
+
};
|
|
18172
|
+
var SUPPORTED_BASE_SNAPSHOT_PAIRS = /* @__PURE__ */ new Set(["USDC:cNGN", "cNGN:USDC"]);
|
|
18173
|
+
var PhantomSnapshotIntentQuoteStrategy = class {
|
|
18174
|
+
constructor(chainConfigService, getQueryClient) {
|
|
18175
|
+
this.chainConfigService = chainConfigService;
|
|
18176
|
+
this.getQueryClient = getQueryClient;
|
|
18177
|
+
this.pairResolver = new PhantomSnapshotPairResolver(chainConfigService);
|
|
18178
|
+
}
|
|
18179
|
+
chainConfigService;
|
|
18180
|
+
getQueryClient;
|
|
18181
|
+
pairResolver;
|
|
18182
|
+
async quote(params, source, destination) {
|
|
18183
|
+
validateQuoteParams(params);
|
|
18184
|
+
const pair = this.pairResolver.resolve(params, source.stateMachineId, destination.stateMachineId);
|
|
18185
|
+
if (!pair) {
|
|
18186
|
+
throw new UnsupportedIntentQuotePairError({
|
|
18187
|
+
source: source.stateMachineId,
|
|
18188
|
+
destination: destination.stateMachineId,
|
|
18189
|
+
tokenIn: params.tokenIn,
|
|
18190
|
+
tokenOut: params.tokenOut,
|
|
18191
|
+
quoteSource: "Phantom snapshot pair"
|
|
18192
|
+
});
|
|
18193
|
+
}
|
|
18194
|
+
const queryClient = this.getQueryClient();
|
|
18195
|
+
const [protocolFeeBps, snapshot] = await Promise.all([
|
|
18196
|
+
readProtocolFeeBps(this.chainConfigService, source),
|
|
18197
|
+
_queryLatestPhantomOrderPriceSnapshot({
|
|
18198
|
+
tokenA: pair.tokenA,
|
|
18199
|
+
tokenB: pair.tokenB,
|
|
18200
|
+
queryClient
|
|
18201
|
+
})
|
|
18202
|
+
]);
|
|
18203
|
+
if (!snapshot) throw new PhantomSnapshotUnavailableError(pair.tokenA, pair.tokenB);
|
|
18204
|
+
this.validateSnapshot(snapshot);
|
|
18205
|
+
return this.quoteSnapshot(params, protocolFeeBps, snapshot);
|
|
18206
|
+
}
|
|
18207
|
+
quoteSnapshot(params, protocolFeeBps, snapshot) {
|
|
18208
|
+
if (params.amountIn !== void 0) {
|
|
18209
|
+
const netAmountIn2 = deductProtocolFee(params.amountIn, protocolFeeBps);
|
|
18210
|
+
const amountOut = netAmountIn2 * snapshot.medianPrice / snapshot.standardAmount;
|
|
18211
|
+
if (amountOut <= 0n) {
|
|
18212
|
+
throw new InvalidPhantomSnapshotError(snapshot.commitment, "quote rounds down to zero output");
|
|
18213
|
+
}
|
|
18214
|
+
return this.buildResult("EXACT_INPUT", params.amountIn, amountOut, protocolFeeBps, snapshot);
|
|
18215
|
+
}
|
|
18216
|
+
if (params.amountOut === void 0) throw new Error("Quote amount is missing after validation");
|
|
18217
|
+
const netAmountIn = divCeil(params.amountOut * snapshot.standardAmount, snapshot.medianPrice);
|
|
18218
|
+
const amountIn = grossUpForProtocolFee(netAmountIn, protocolFeeBps);
|
|
18219
|
+
return this.buildResult("EXACT_OUTPUT", amountIn, params.amountOut, protocolFeeBps, snapshot);
|
|
18220
|
+
}
|
|
18221
|
+
buildResult(tradeType, amountIn, amountOut, protocolFeeBps, snapshot) {
|
|
18222
|
+
return {
|
|
18223
|
+
strategy: "phantom_snapshot",
|
|
18224
|
+
tradeType,
|
|
18225
|
+
amountIn,
|
|
18226
|
+
amountOut,
|
|
18227
|
+
quoteMetadata: {
|
|
18228
|
+
quoteChain: PHANTOM_INTENT_QUOTE_CHAIN,
|
|
18229
|
+
commitment: snapshot.commitment,
|
|
18230
|
+
tokenA: snapshot.tokenA,
|
|
18231
|
+
tokenB: snapshot.tokenB,
|
|
18232
|
+
standardAmount: snapshot.standardAmount,
|
|
18233
|
+
medianPrice: snapshot.medianPrice,
|
|
18234
|
+
lowestPrice: snapshot.lowestPrice,
|
|
18235
|
+
highestPrice: snapshot.highestPrice,
|
|
18236
|
+
blockNumber: snapshot.blockNumber,
|
|
18237
|
+
snapshotTime: snapshot.snapshotTime,
|
|
18238
|
+
bidCount: snapshot.bidCount,
|
|
18239
|
+
protocolFeeBps
|
|
18240
|
+
}
|
|
18241
|
+
};
|
|
18242
|
+
}
|
|
18243
|
+
validateSnapshot(snapshot) {
|
|
18244
|
+
if (snapshot.standardAmount <= 0n) {
|
|
18245
|
+
throw new InvalidPhantomSnapshotError(snapshot.commitment, "standardAmount must be greater than zero");
|
|
18246
|
+
}
|
|
18247
|
+
if (snapshot.medianPrice <= 0n) {
|
|
18248
|
+
throw new InvalidPhantomSnapshotError(snapshot.commitment, "medianPrice must be greater than zero");
|
|
18249
|
+
}
|
|
18250
|
+
if (snapshot.bidCount <= 0) {
|
|
18251
|
+
throw new InvalidPhantomSnapshotError(snapshot.commitment, "bidCount must be greater than zero");
|
|
18252
|
+
}
|
|
18253
|
+
if (Number.isNaN(snapshot.snapshotTime.getTime())) {
|
|
18254
|
+
throw new InvalidPhantomSnapshotError(snapshot.commitment, "snapshotTime is invalid");
|
|
18255
|
+
}
|
|
18256
|
+
}
|
|
18257
|
+
};
|
|
18258
|
+
var PhantomSnapshotPairResolver = class {
|
|
18259
|
+
constructor(chainConfigService) {
|
|
18260
|
+
this.chainConfigService = chainConfigService;
|
|
18261
|
+
}
|
|
18262
|
+
chainConfigService;
|
|
18263
|
+
resolve(params, sourceStateMachineId, destinationStateMachineId) {
|
|
18264
|
+
const tokenIn = this.resolveBaseSnapshotToken(sourceStateMachineId, params.tokenIn);
|
|
18265
|
+
const tokenOut = this.resolveBaseSnapshotToken(destinationStateMachineId, params.tokenOut);
|
|
18266
|
+
if (!tokenIn || !tokenOut || !isSupportedSnapshotPair(tokenIn.symbol, tokenOut.symbol)) return;
|
|
18267
|
+
return { tokenA: tokenIn.address, tokenB: tokenOut.address };
|
|
18268
|
+
}
|
|
18269
|
+
resolveBaseSnapshotToken(chain, tokenAddress) {
|
|
18270
|
+
const orderAsset = this.chainConfigService.getAssetMetadataByAddress(chain, tokenAddress)?.symbol;
|
|
18271
|
+
if (!orderAsset) return;
|
|
18272
|
+
const snapshotAsset = BASE_SNAPSHOT_ASSET_BY_ORDER_ASSET[orderAsset];
|
|
18273
|
+
if (!snapshotAsset) return;
|
|
18274
|
+
const address = this.chainConfigService.getAssetAddress(PHANTOM_INTENT_QUOTE_CHAIN, snapshotAsset);
|
|
18275
|
+
if (!isConfiguredAddress(address)) return;
|
|
18276
|
+
return { symbol: snapshotAsset, address };
|
|
18277
|
+
}
|
|
18278
|
+
};
|
|
18279
|
+
function isSupportedSnapshotPair(tokenA, tokenB) {
|
|
18280
|
+
return SUPPORTED_BASE_SNAPSHOT_PAIRS.has(`${tokenA}:${tokenB}`);
|
|
17554
18281
|
}
|
|
17555
|
-
function
|
|
17556
|
-
return (
|
|
18282
|
+
function isConfiguredAddress(address) {
|
|
18283
|
+
return Boolean(address && address !== "0x" && !/^0x0{40}$/i.test(address));
|
|
17557
18284
|
}
|
|
17558
18285
|
|
|
17559
18286
|
// src/protocols/intents/IntentGateway.ts
|
|
18287
|
+
var CROSS_CHAIN_ORDER_FEE_GAS_BUMP = 600000n;
|
|
17560
18288
|
var IntentGateway = class _IntentGateway {
|
|
17561
18289
|
/** EVM chain on which orders are placed and escrowed. */
|
|
17562
18290
|
source;
|
|
@@ -17584,6 +18312,8 @@ var IntentGateway = class _IntentGateway {
|
|
|
17584
18312
|
gasEstimator;
|
|
17585
18313
|
/** Quote strategies for pricing orders before placement, keyed by strategy name. */
|
|
17586
18314
|
quoteStrategies;
|
|
18315
|
+
/** Resolves order tokens to canonical Phantom snapshot market pairs. */
|
|
18316
|
+
phantomSnapshotPairResolver;
|
|
17587
18317
|
/**
|
|
17588
18318
|
* Private constructor — use {@link IntentGateway.create} instead.
|
|
17589
18319
|
*
|
|
@@ -17627,7 +18357,12 @@ var IntentGateway = class _IntentGateway {
|
|
|
17627
18357
|
this.bidManager = bidManager;
|
|
17628
18358
|
this.gasEstimator = gasEstimator;
|
|
17629
18359
|
this._crypto = crypto;
|
|
18360
|
+
this.phantomSnapshotPairResolver = new PhantomSnapshotPairResolver(dest.configService);
|
|
17630
18361
|
this.quoteStrategies = {
|
|
18362
|
+
phantom_snapshot: new PhantomSnapshotIntentQuoteStrategy(
|
|
18363
|
+
dest.configService,
|
|
18364
|
+
() => this.requireIndexer().queryClient
|
|
18365
|
+
),
|
|
17631
18366
|
uniswap_v4: new UniswapV4IntentQuoteStrategy(dest.configService)
|
|
17632
18367
|
};
|
|
17633
18368
|
}
|
|
@@ -17677,37 +18412,69 @@ var IntentGateway = class _IntentGateway {
|
|
|
17677
18412
|
/**
|
|
17678
18413
|
* Quotes an intent between this gateway's source and destination chains.
|
|
17679
18414
|
*
|
|
17680
|
-
*
|
|
17681
|
-
*
|
|
18415
|
+
* Uses the latest directional Phantom order price snapshot from the attached
|
|
18416
|
+
* indexer by default. Pass `strategy: "uniswap_v4"` only when explicitly
|
|
18417
|
+
* requesting a Uniswap quote. Provide exactly one of `amountIn` or `amountOut`.
|
|
17682
18418
|
*
|
|
17683
|
-
*
|
|
17684
|
-
*
|
|
18419
|
+
* Both built-in strategies resolve their canonical market on Base,
|
|
18420
|
+
* regardless of this gateway's destination chain. Returned
|
|
17685
18421
|
* `amountIn`/`amountOut` already account for the gateway's protocol fee
|
|
17686
18422
|
* (`quoteMetadata.protocolFeeBps`), which the gateway deducts from order
|
|
17687
|
-
* inputs;
|
|
18423
|
+
* inputs; use the returned amounts directly when placing the order.
|
|
17688
18424
|
*
|
|
17689
18425
|
* @param params - Token pair, amount, and optional strategy/pool overrides.
|
|
17690
18426
|
* @returns The quoted amounts plus strategy-specific metadata.
|
|
17691
18427
|
* @throws {UnsupportedIntentQuoteStrategyError} For unknown strategies.
|
|
17692
|
-
* @throws {UnsupportedIntentQuotePairError} When
|
|
18428
|
+
* @throws {UnsupportedIntentQuotePairError} When the selected strategy does not support the pair.
|
|
18429
|
+
* @throws {PhantomSnapshotUnavailableError} When an eligible cNGN pair has no snapshot.
|
|
17693
18430
|
*/
|
|
17694
18431
|
async quoteIntent(params) {
|
|
17695
|
-
const
|
|
18432
|
+
const source = { stateMachineId: this.source.config.stateMachineId, client: this.source.client };
|
|
18433
|
+
const destination = { stateMachineId: this.dest.config.stateMachineId, client: this.dest.client };
|
|
18434
|
+
const strategy = params.strategy ?? "phantom_snapshot";
|
|
17696
18435
|
const handler = this.quoteStrategies[strategy];
|
|
17697
18436
|
if (!handler) throw new UnsupportedIntentQuoteStrategyError(strategy);
|
|
17698
|
-
return handler.quote(
|
|
17699
|
-
|
|
17700
|
-
|
|
17701
|
-
|
|
17702
|
-
|
|
18437
|
+
return handler.quote({ ...params, strategy }, source, destination);
|
|
18438
|
+
}
|
|
18439
|
+
/**
|
|
18440
|
+
* Returns the output-token liquidity measured in the latest directional
|
|
18441
|
+
* Phantom snapshot for this gateway's source and destination.
|
|
18442
|
+
*
|
|
18443
|
+
* Pair resolution uses the same canonical Base market as {@link quoteIntent}.
|
|
18444
|
+
* The snapshot itself determines the output token and chain to aggregate. The
|
|
18445
|
+
* amount is in the token's smallest unit and reflects the indexer's
|
|
18446
|
+
* `snapshotTime`; it is not a live reservation or fill guarantee.
|
|
18447
|
+
*
|
|
18448
|
+
* Requires a prior call to {@link withQueryClient}.
|
|
18449
|
+
*/
|
|
18450
|
+
async queryAvailableLiquidity(params) {
|
|
18451
|
+
const { queryClient } = this.requireIndexer();
|
|
18452
|
+
const sourceStateMachineId = this.source.config.stateMachineId;
|
|
18453
|
+
const destinationStateMachineId = this.dest.config.stateMachineId;
|
|
18454
|
+
const pair = this.phantomSnapshotPairResolver.resolve(params, sourceStateMachineId, destinationStateMachineId);
|
|
18455
|
+
if (!pair) {
|
|
18456
|
+
throw new UnsupportedIntentQuotePairError({
|
|
18457
|
+
source: sourceStateMachineId,
|
|
18458
|
+
destination: destinationStateMachineId,
|
|
18459
|
+
tokenIn: params.tokenIn,
|
|
18460
|
+
tokenOut: params.tokenOut,
|
|
18461
|
+
quoteSource: "Phantom snapshot pair"
|
|
18462
|
+
});
|
|
18463
|
+
}
|
|
18464
|
+
return new LiquidityEngine(queryClient, this.dest.configService).getAvailableLiquiditySnapshot({
|
|
18465
|
+
tokenIn: pair.tokenA,
|
|
18466
|
+
tokenOut: pair.tokenB
|
|
18467
|
+
});
|
|
17703
18468
|
}
|
|
17704
18469
|
/**
|
|
17705
18470
|
* Bidirectional async generator that orchestrates the full order lifecycle:
|
|
17706
18471
|
* placement, fee estimation, bid collection, and execution.
|
|
17707
18472
|
*
|
|
17708
18473
|
* **Yield/receive protocol:**
|
|
17709
|
-
* 1. If `order.fees` is unset or zero, estimates gas and sets
|
|
17710
|
-
*
|
|
18474
|
+
* 1. If `order.fees` is unset or zero, estimates gas on an internal copy and sets
|
|
18475
|
+
* same-chain fees to twice the estimate. Cross-chain orders retain a 1% buffer
|
|
18476
|
+
* and include an additional 600k-gas fee uplift, while the wei cost used for
|
|
18477
|
+
* the `value` field receives a 2% buffer.
|
|
17711
18478
|
* 2. Yields `AWAITING_PLACE_ORDER` with `{ to, data, value, sessionPrivateKey }`.
|
|
17712
18479
|
* The caller must sign the transaction and pass it back via `gen.next(signedTx)`.
|
|
17713
18480
|
* 3. Yields `ORDER_PLACED` with the finalised order and transaction hash once
|
|
@@ -17715,8 +18482,8 @@ var IntentGateway = class _IntentGateway {
|
|
|
17715
18482
|
* 4. Delegates to {@link OrderExecutor.executeOrder} and forwards all
|
|
17716
18483
|
* subsequent status updates until the order is filled, exhausted, or fails.
|
|
17717
18484
|
*
|
|
17718
|
-
* @param order - The order to place and execute. `order.fees`
|
|
17719
|
-
*
|
|
18485
|
+
* @param order - The order to place and execute. It is not mutated. `order.fees`
|
|
18486
|
+
* may be 0; fees are estimated automatically if so.
|
|
17720
18487
|
* @param graffiti - Optional bytes32 tag for orderflow attribution /
|
|
17721
18488
|
* revenue share. Defaults to {@link DEFAULT_GRAFFITI}.
|
|
17722
18489
|
* @param options - Optional tuning parameters:
|
|
@@ -17729,20 +18496,28 @@ var IntentGateway = class _IntentGateway {
|
|
|
17729
18496
|
* estimation returns zero.
|
|
17730
18497
|
*/
|
|
17731
18498
|
async *execute(order, graffiti = DEFAULT_GRAFFITI, options) {
|
|
18499
|
+
const executionOrder = { ...order };
|
|
17732
18500
|
let value;
|
|
17733
|
-
if (!
|
|
18501
|
+
if (!executionOrder.fees || executionOrder.fees === 0n) {
|
|
17734
18502
|
const estimate = await this.gasEstimator.estimateFillOrder({
|
|
17735
|
-
order,
|
|
18503
|
+
order: executionOrder,
|
|
17736
18504
|
maxPriorityFeePerGasBumpPercent: options?.maxPriorityFeePerGasBumpPercent,
|
|
17737
18505
|
maxFeePerGasBumpPercent: options?.maxFeePerGasBumpPercent
|
|
17738
18506
|
});
|
|
17739
18507
|
if (estimate.totalGasCostWei === 0n || estimate.totalGasInFeeToken === 0n) {
|
|
17740
18508
|
throw new Error("Gas estimation failed");
|
|
17741
18509
|
}
|
|
18510
|
+
const isSameChain = this.source.config.stateMachineId === this.dest.config.stateMachineId;
|
|
17742
18511
|
value = estimate.totalGasCostWei + estimate.totalGasCostWei * 2n / 100n;
|
|
17743
|
-
|
|
18512
|
+
const crossChainFeeBump = isSameChain ? 0n : await convertGasToFeeToken(
|
|
18513
|
+
this.ctx,
|
|
18514
|
+
CROSS_CHAIN_ORDER_FEE_GAS_BUMP,
|
|
18515
|
+
"source",
|
|
18516
|
+
this.source.config.stateMachineId
|
|
18517
|
+
);
|
|
18518
|
+
executionOrder.fees = isSameChain ? estimate.totalGasInFeeToken * 2n : estimate.totalGasInFeeToken + (crossChainFeeBump + estimate.totalGasInFeeToken * 1n / 100n);
|
|
17744
18519
|
}
|
|
17745
|
-
const placeOrderGen = this.orderPlacer.placeOrder(
|
|
18520
|
+
const placeOrderGen = this.orderPlacer.placeOrder(executionOrder, graffiti);
|
|
17746
18521
|
const placeOrderFirst = await placeOrderGen.next();
|
|
17747
18522
|
if (placeOrderFirst.done) {
|
|
17748
18523
|
throw new Error("placeOrder generator completed without yielding");
|
|
@@ -17853,13 +18628,20 @@ var IntentGateway = class _IntentGateway {
|
|
|
17853
18628
|
const gen = this.execute(order, graffiti, options);
|
|
17854
18629
|
try {
|
|
17855
18630
|
let input;
|
|
18631
|
+
let finalizedOrder;
|
|
17856
18632
|
while (true) {
|
|
17857
18633
|
const { value, done } = await gen.next(input);
|
|
17858
18634
|
input = void 0;
|
|
17859
18635
|
if (done) break;
|
|
17860
|
-
if (value.status === "
|
|
18636
|
+
if (value.status === "ORDER_PLACED") {
|
|
18637
|
+
finalizedOrder = value.order;
|
|
17861
18638
|
yield value;
|
|
17862
|
-
|
|
18639
|
+
} else if (value.status === "BIDS_RECEIVED") {
|
|
18640
|
+
if (!finalizedOrder) {
|
|
18641
|
+
throw new Error("Received bids before the order was finalized");
|
|
18642
|
+
}
|
|
18643
|
+
yield value;
|
|
18644
|
+
input = await this.autoSelect(finalizedOrder, value.bids);
|
|
17863
18645
|
} else if (value.status === "AWAITING_PLACE_ORDER") {
|
|
17864
18646
|
input = yield value;
|
|
17865
18647
|
} else {
|
|
@@ -18121,7 +18903,9 @@ var IntentGateway = class _IntentGateway {
|
|
|
18121
18903
|
}
|
|
18122
18904
|
requireIndexer() {
|
|
18123
18905
|
if (!this.indexer) {
|
|
18124
|
-
throw new Error(
|
|
18906
|
+
throw new Error(
|
|
18907
|
+
"IntentGateway: call withQueryClient(queryClient) before using indexer-backed methods or Phantom quotes"
|
|
18908
|
+
);
|
|
18125
18909
|
}
|
|
18126
18910
|
return this.indexer;
|
|
18127
18911
|
}
|
|
@@ -22635,6 +23419,6 @@ async function teleportDot(param_) {
|
|
|
22635
23419
|
return stream;
|
|
22636
23420
|
}
|
|
22637
23421
|
|
|
22638
|
-
export { ADDRESS_ZERO2 as ADDRESS_ZERO, BundlerMethod, ChainConfigService, Chains, CryptoUtils, DEFAULT_ADDRESS, DEFAULT_GRAFFITI, DOMAIN_TYPEHASH, DUMMY_PRIVATE_KEY, ERC20Method, ERC7821_BATCH_MODE, EvmChain, ABI as EvmHostABI, EvmLanguage, HyperClientStatus, HyperFungibleToken, HyperFungibleTokenABI, IntentGateway, ABI3 as IntentGatewayABI, IntentOrderStatus, IntentsCoprocessor, IsmpClient, MOCK_ADDRESS, ORDER_V2_PARAM_TYPE, OrderStatus, OrderStatusChecker, PACKED_USEROP_TYPEHASH, 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, SubstrateChain, Swap, TESTNET_CHAINS, TeleportStatus, TimeoutStatus, TokenGateway, TronChain, USE_ETHERSCAN_CHAINS, UnsupportedIntentQuotePairError, UnsupportedIntentQuoteStrategyError, WrappedHyperFungibleTokenABI, __test, adjustDecimals, bytes20ToBytes32, bytes32ToBytes20, calculateAllowanceMappingLocation, calculateBalanceMappingLocation, chainConfigs, constructRedeemEscrowRequestBody, constructRefundEscrowRequestBody, convertCodecToIGetRequest, convertCodecToIProof, convertIGetRequestToCodec, convertIProofToCodec, convertStateIdToStateMachineId, convertStateMachineEnumToString, convertStateMachineIdToEnum, createEvmChain, createQueryClient, decodeERC7821ExecuteBatch, decodeUserOpScale, encodeERC7821ExecuteBatch, encodeISMPMessage, encodeStateMachineId, encodeUserOpScale, encodeWithdrawalRequest, estimateGasForPost, fetchPrice, fetchSourceProof, generateRootWithProof, getChainId, getConfigByStateMachineId, getContractCallInput, getContractCallInputs, getGasPriceFromEtherscan, getOrFetchStorageSlot, getOrderPlacedFromTx, getPostRequestEventFromTx, getPostResponseEventFromTx, getRequestCommitment, getStateCommitmentFieldSlot, getStateCommitmentSlot, getStorageSlot, getViemChain, hexToString, hyperbridgeAddress, maxBigInt, normalizeAddressForEvmBytes32, normalizeAddressForStateMachine, normalizeEvmChainId, normalizeStateMachineId, orderCommitment, parseStateMachineId, pharosAtlantic, pharosMainnet, polkadotAssetHubPaseo, polkadotHubMainnet, postRequestCommitment, queryAssetTeleported, queryGetRequest, queryPostRequest, quoteUniswap, requestCommitmentKey, responseCommitmentKey, retryPromise, teleport, teleportDot, transformOrderForContract, tronChainIds, tronNile };
|
|
23422
|
+
export { ADDRESS_ZERO2 as ADDRESS_ZERO, BundlerMethod, ChainConfigService, Chains, CryptoUtils, DEFAULT_ADDRESS, DEFAULT_GRAFFITI, DOMAIN_TYPEHASH, DUMMY_PRIVATE_KEY, ERC20Method, ERC7821_BATCH_MODE, EvmChain, ABI as EvmHostABI, EvmLanguage, HyperClientStatus, HyperFungibleToken, HyperFungibleTokenABI, IntentGateway, ABI3 as IntentGatewayABI, IntentOrderStatus, IntentsCoprocessor, InvalidPhantomSnapshotError, IsmpClient, MOCK_ADDRESS, ORDER_V2_PARAM_TYPE, OrderStatus, OrderStatusChecker, PACKED_USEROP_TYPEHASH, PLACE_ORDER_SELECTOR, PhantomSnapshotUnavailableError, PharosChain, PolkadotHubChain, REQUEST_COMMITMENTS_SLOT, REQUEST_RECEIPTS_SLOT, RESPONSE_COMMITMENTS_SLOT, RESPONSE_RECEIPTS_SLOT, RequestKind, RequestStatus, SELECT_SOLVER_TYPEHASH, STATE_COMMITMENTS_SLOT, SubstrateChain, Swap, TESTNET_CHAINS, TeleportStatus, TimeoutStatus, TokenGateway, TronChain, USE_ETHERSCAN_CHAINS, UnsupportedIntentQuotePairError, UnsupportedIntentQuoteStrategyError, WrappedHyperFungibleTokenABI, __test, adjustDecimals, bytes20ToBytes32, bytes32ToBytes20, calculateAllowanceMappingLocation, calculateBalanceMappingLocation, chainConfigs, constructRedeemEscrowRequestBody, constructRefundEscrowRequestBody, convertCodecToIGetRequest, convertCodecToIProof, convertIGetRequestToCodec, convertIProofToCodec, convertStateIdToStateMachineId, convertStateMachineEnumToString, convertStateMachineIdToEnum, createEvmChain, createQueryClient, decodeERC7821ExecuteBatch, decodeUserOpScale, encodeERC7821ExecuteBatch, encodeISMPMessage, encodeStateMachineId, encodeUserOpScale, encodeWithdrawalRequest, estimateGasForPost, fetchPrice, fetchSourceProof, generateRootWithProof, getChainId, getConfigByStateMachineId, getContractCallInput, getContractCallInputs, getGasPriceFromEtherscan, getOrFetchStorageSlot, getOrderPlacedFromTx, getPostRequestEventFromTx, getPostResponseEventFromTx, getRequestCommitment, getStateCommitmentFieldSlot, getStateCommitmentSlot, getStorageSlot, getViemChain, hexToString, hyperbridgeAddress, maxBigInt, normalizeAddressForEvmBytes32, normalizeAddressForStateMachine, normalizeEvmAddress, normalizeEvmChainId, normalizeStateMachineId, orderCommitment, parseStateMachineId, pharosAtlantic, pharosMainnet, polkadotAssetHubPaseo, polkadotHubMainnet, postRequestCommitment, queryAssetTeleported, queryGetRequest, queryPostRequest, quoteUniswap, requestCommitmentKey, responseCommitmentKey, retryPromise, teleport, teleportDot, transformOrderForContract, tronChainIds, tronNile };
|
|
22639
23423
|
//# sourceMappingURL=index.js.map
|
|
22640
23424
|
//# sourceMappingURL=index.js.map
|