@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.cjs
CHANGED
|
@@ -2490,30 +2490,30 @@ var handlerV2_default = { ABI: ABI2 };
|
|
|
2490
2490
|
function tronAddress(base58) {
|
|
2491
2491
|
return `0x${tronweb.TronWeb.address.toHex(base58).slice(2)}`;
|
|
2492
2492
|
}
|
|
2493
|
-
var Chains = /* @__PURE__ */ ((
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
return
|
|
2493
|
+
var Chains = /* @__PURE__ */ ((Chains2) => {
|
|
2494
|
+
Chains2["BSC_CHAPEL"] = "EVM-97";
|
|
2495
|
+
Chains2["GNOSIS_CHIADO"] = "EVM-10200";
|
|
2496
|
+
Chains2["HYPERBRIDGE_GARGANTUA"] = "KUSAMA-4009";
|
|
2497
|
+
Chains2["SEPOLIA"] = "EVM-11155111";
|
|
2498
|
+
Chains2["MAINNET"] = "EVM-1";
|
|
2499
|
+
Chains2["BSC_MAINNET"] = "EVM-56";
|
|
2500
|
+
Chains2["ARBITRUM_MAINNET"] = "EVM-42161";
|
|
2501
|
+
Chains2["ARBITRUM_SEPOLIA"] = "EVM-421614";
|
|
2502
|
+
Chains2["BASE_MAINNET"] = "EVM-8453";
|
|
2503
|
+
Chains2["BASE_SEPOLIA"] = "EVM-84532";
|
|
2504
|
+
Chains2["OPTIMISM_MAINNET"] = "EVM-10";
|
|
2505
|
+
Chains2["OPTIMISM_SEPOLIA"] = "EVM-11155420";
|
|
2506
|
+
Chains2["GNOSIS_MAINNET"] = "EVM-100";
|
|
2507
|
+
Chains2["SONEIUM_MAINNET"] = "EVM-1868";
|
|
2508
|
+
Chains2["POLYGON_MAINNET"] = "EVM-137";
|
|
2509
|
+
Chains2["POLKADOT_HUB_MAINNET"] = "EVM-420420419";
|
|
2510
|
+
Chains2["POLYGON_AMOY"] = "EVM-80002";
|
|
2511
|
+
Chains2["POLKADOT_ASSET_HUB_PASEO"] = "EVM-420420417";
|
|
2512
|
+
Chains2["TRON_MAINNET"] = "EVM-728126428";
|
|
2513
|
+
Chains2["TRON_NILE"] = "EVM-3448148188";
|
|
2514
|
+
Chains2["PHAROS_MAINNET"] = "EVM-688600";
|
|
2515
|
+
Chains2["PHAROS_ATLANTIC"] = "EVM-688689";
|
|
2516
|
+
return Chains2;
|
|
2517
2517
|
})(Chains || {});
|
|
2518
2518
|
var polkadotAssetHubPaseo = viem.defineChain({
|
|
2519
2519
|
id: 420420417,
|
|
@@ -2704,7 +2704,7 @@ var chainConfigs = {
|
|
|
2704
2704
|
},
|
|
2705
2705
|
addresses: {
|
|
2706
2706
|
IntentGateway: "0xAe041F7B0CB581876832830baeB6a2Aa2a3C9716",
|
|
2707
|
-
SolverAccount: "
|
|
2707
|
+
SolverAccount: "0xfCd233b937D7622AAc63ced3C9A1A12F4a6B64E3",
|
|
2708
2708
|
TokenGateway: "0xFd413e3AFe560182C4471F4d143A96d3e259B6dE",
|
|
2709
2709
|
Host: "0x620128E2B19193d6Bd244a3AC8D3bBa0541B19c3",
|
|
2710
2710
|
UniswapRouter02: "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D",
|
|
@@ -2720,6 +2720,7 @@ var chainConfigs = {
|
|
|
2720
2720
|
Permit2: "0x000000000022D473030F116dDEE9F6B43aC78BA3",
|
|
2721
2721
|
EntryPointV08: "0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108",
|
|
2722
2722
|
CirclePaymaster: "0x0578cFB241215b77442a541325d6A4E6dFE700Ec",
|
|
2723
|
+
SimplexPaymaster: "0xD4340d7466e040626383cb9cda9307ba8E081149",
|
|
2723
2724
|
Usdt0Oft: "0x6C96dE32CEa08842dcc4058c14d3aaAD7Fa41dee"
|
|
2724
2725
|
},
|
|
2725
2726
|
rpcEnvKey: "ETH_MAINNET",
|
|
@@ -2759,7 +2760,7 @@ var chainConfigs = {
|
|
|
2759
2760
|
},
|
|
2760
2761
|
addresses: {
|
|
2761
2762
|
IntentGateway: "0xAe041F7B0CB581876832830baeB6a2Aa2a3C9716",
|
|
2762
|
-
SolverAccount: "
|
|
2763
|
+
SolverAccount: "0xfCd233b937D7622AAc63ced3C9A1A12F4a6B64E3",
|
|
2763
2764
|
TokenGateway: "0xFd413e3AFe560182C4471F4d143A96d3e259B6dE",
|
|
2764
2765
|
Host: "0x620128E2B19193d6Bd244a3AC8D3bBa0541B19c3",
|
|
2765
2766
|
UniswapRouter02: "0x10ED43C718714eb63d5aA57B78B54704E256024E",
|
|
@@ -2773,7 +2774,8 @@ var chainConfigs = {
|
|
|
2773
2774
|
UniswapV4StateView: "0xd13dd3d6e93f276fafc9db9e6bb47c1180aee0c4",
|
|
2774
2775
|
Calldispatcher: "0xc71251c8b3e7b02697a84363eef6dce8dfbdf333",
|
|
2775
2776
|
Permit2: "0x000000000022D473030F116dDEE9F6B43aC78BA3",
|
|
2776
|
-
EntryPointV08: "0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108"
|
|
2777
|
+
EntryPointV08: "0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108",
|
|
2778
|
+
SimplexPaymaster: "0xeD02f9f0df8F562B89cC5b25867Ad3C2d61252A9"
|
|
2777
2779
|
// "Usdt0Oft": Not available on BSC
|
|
2778
2780
|
},
|
|
2779
2781
|
rpcEnvKey: "BSC_MAINNET",
|
|
@@ -2815,7 +2817,7 @@ var chainConfigs = {
|
|
|
2815
2817
|
},
|
|
2816
2818
|
addresses: {
|
|
2817
2819
|
IntentGateway: "0xAe041F7B0CB581876832830baeB6a2Aa2a3C9716",
|
|
2818
|
-
SolverAccount: "
|
|
2820
|
+
SolverAccount: "0xfCd233b937D7622AAc63ced3C9A1A12F4a6B64E3",
|
|
2819
2821
|
TokenGateway: "0xFd413e3AFe560182C4471F4d143A96d3e259B6dE",
|
|
2820
2822
|
Host: "0x620128E2B19193d6Bd244a3AC8D3bBa0541B19c3",
|
|
2821
2823
|
UniswapRouter02: "0x4752ba5DBc23f44D87826276BF6Fd6b1C372aD24",
|
|
@@ -2831,6 +2833,7 @@ var chainConfigs = {
|
|
|
2831
2833
|
Permit2: "0x000000000022D473030F116dDEE9F6B43aC78BA3",
|
|
2832
2834
|
EntryPointV08: "0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108",
|
|
2833
2835
|
CirclePaymaster: "0x0578cFB241215b77442a541325d6A4E6dFE700Ec",
|
|
2836
|
+
SimplexPaymaster: "0x7281Bccb4f0BCE44F3B8542d1fC5e51c2F5fC08C",
|
|
2834
2837
|
Usdt0Oft: "0x14E4A1B13bf7F943c8ff7C51fb60FA964A298D92"
|
|
2835
2838
|
},
|
|
2836
2839
|
rpcEnvKey: "ARBITRUM_MAINNET",
|
|
@@ -2872,7 +2875,7 @@ var chainConfigs = {
|
|
|
2872
2875
|
},
|
|
2873
2876
|
addresses: {
|
|
2874
2877
|
IntentGateway: "0xAe041F7B0CB581876832830baeB6a2Aa2a3C9716",
|
|
2875
|
-
SolverAccount: "
|
|
2878
|
+
SolverAccount: "0xfCd233b937D7622AAc63ced3C9A1A12F4a6B64E3",
|
|
2876
2879
|
TokenGateway: "0xFd413e3AFe560182C4471F4d143A96d3e259B6dE",
|
|
2877
2880
|
Host: "0x620128E2B19193d6Bd244a3AC8D3bBa0541B19c3",
|
|
2878
2881
|
UniswapRouter02: "0x4752ba5DBc23f44D87826276BF6Fd6b1C372aD24",
|
|
@@ -2885,6 +2888,7 @@ var chainConfigs = {
|
|
|
2885
2888
|
Permit2: "0x000000000022D473030F116dDEE9F6B43aC78BA3",
|
|
2886
2889
|
EntryPointV08: "0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108",
|
|
2887
2890
|
CirclePaymaster: "0x0578cFB241215b77442a541325d6A4E6dFE700Ec",
|
|
2891
|
+
SimplexPaymaster: "0x15b3B03C870c7ef252029c35A12d3b339F5c8d7f",
|
|
2888
2892
|
AerodromeRouter: "0xcF77a3Ba9A5CA399B7c97c74d54e5b1Beb874E43",
|
|
2889
2893
|
UniswapV4PositionManager: "0x7c5f5a4bbd8fd63184577525326123b519429bdc",
|
|
2890
2894
|
UniswapV4PoolManager: "0x498581ff718922c3f8e6a244956af099b2652b2b",
|
|
@@ -2931,7 +2935,7 @@ var chainConfigs = {
|
|
|
2931
2935
|
},
|
|
2932
2936
|
addresses: {
|
|
2933
2937
|
IntentGateway: "0xAe041F7B0CB581876832830baeB6a2Aa2a3C9716",
|
|
2934
|
-
SolverAccount: "
|
|
2938
|
+
SolverAccount: "0xfCd233b937D7622AAc63ced3C9A1A12F4a6B64E3",
|
|
2935
2939
|
TokenGateway: "0x8b536105b6Fae2aE9199f5146D3C57Dfe53b614E",
|
|
2936
2940
|
Host: "0x620128E2B19193d6Bd244a3AC8D3bBa0541B19c3",
|
|
2937
2941
|
UniswapRouter02: "0xd2f9496824951D5237cC71245D659E48d0d5f9E8",
|
|
@@ -2947,6 +2951,7 @@ var chainConfigs = {
|
|
|
2947
2951
|
Permit2: "0x000000000022D473030F116dDEE9F6B43aC78BA3",
|
|
2948
2952
|
EntryPointV08: "0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108",
|
|
2949
2953
|
CirclePaymaster: "0x0578cFB241215b77442a541325d6A4E6dFE700Ec",
|
|
2954
|
+
SimplexPaymaster: "0xe99acFe0f5fC4C8ea54A187D8D3b05f136150095",
|
|
2950
2955
|
Usdt0Oft: "0x6BA10300f0DC58B7a1e4c0e41f5daBb7D7829e13"
|
|
2951
2956
|
},
|
|
2952
2957
|
rpcEnvKey: "POLYGON_MAINNET",
|
|
@@ -3042,7 +3047,7 @@ var chainConfigs = {
|
|
|
3042
3047
|
},
|
|
3043
3048
|
addresses: {
|
|
3044
3049
|
IntentGateway: "0xAe041F7B0CB581876832830baeB6a2Aa2a3C9716",
|
|
3045
|
-
SolverAccount: "
|
|
3050
|
+
SolverAccount: "0xfCd233b937D7622AAc63ced3C9A1A12F4a6B64E3",
|
|
3046
3051
|
TokenGateway: "0xFd413e3AFe560182C4471F4d143A96d3e259B6dE",
|
|
3047
3052
|
Host: "0x620128E2B19193d6Bd244a3AC8D3bBa0541B19c3",
|
|
3048
3053
|
UniswapRouter02: "0x4A7b5Da61326A6379179b40d00F57E5bbDC962c2",
|
|
@@ -3077,7 +3082,7 @@ var chainConfigs = {
|
|
|
3077
3082
|
},
|
|
3078
3083
|
addresses: {
|
|
3079
3084
|
IntentGateway: "0xAe041F7B0CB581876832830baeB6a2Aa2a3C9716",
|
|
3080
|
-
SolverAccount: "
|
|
3085
|
+
SolverAccount: "0xfCd233b937D7622AAc63ced3C9A1A12F4a6B64E3",
|
|
3081
3086
|
TokenGateway: "0xFd413e3AFe560182C4471F4d143A96d3e259B6dE",
|
|
3082
3087
|
Host: "0x620128E2B19193d6Bd244a3AC8D3bBa0541B19c3",
|
|
3083
3088
|
UniswapRouter02: "0xB2e26652e4BAd1e56055A051f922E06760cA0BFE",
|
|
@@ -3232,7 +3237,7 @@ var chainConfigs = {
|
|
|
3232
3237
|
},
|
|
3233
3238
|
addresses: {
|
|
3234
3239
|
IntentGateway: "0xAe041F7B0CB581876832830baeB6a2Aa2a3C9716",
|
|
3235
|
-
SolverAccount: "
|
|
3240
|
+
SolverAccount: "0xfCd233b937D7622AAc63ced3C9A1A12F4a6B64E3",
|
|
3236
3241
|
Host: "0x620128E2B19193d6Bd244a3AC8D3bBa0541B19c3",
|
|
3237
3242
|
Calldispatcher: "0xE2C7e576E26E0bE7aC97c6fE925bcDAbD87c4bEd"
|
|
3238
3243
|
},
|
|
@@ -5118,6 +5123,24 @@ var ChainConfigService = class {
|
|
|
5118
5123
|
getAssetAddress(chain, symbol) {
|
|
5119
5124
|
return this.getConfig(chain)?.assets?.[symbol];
|
|
5120
5125
|
}
|
|
5126
|
+
/**
|
|
5127
|
+
* Resolves configured token metadata from an address on a specific chain.
|
|
5128
|
+
* This is used by SDK helpers that accept token addresses rather than caller-
|
|
5129
|
+
* supplied symbols or decimals.
|
|
5130
|
+
*/
|
|
5131
|
+
getAssetMetadataByAddress(chain, address) {
|
|
5132
|
+
const config = this.getConfig(chain);
|
|
5133
|
+
if (!config?.assets) return;
|
|
5134
|
+
const normalizedAddress = address.toLowerCase();
|
|
5135
|
+
for (const [symbol, configuredAddress] of Object.entries(config.assets)) {
|
|
5136
|
+
if (configuredAddress.toLowerCase() !== normalizedAddress) continue;
|
|
5137
|
+
return {
|
|
5138
|
+
symbol,
|
|
5139
|
+
address: configuredAddress,
|
|
5140
|
+
decimals: config.tokenDecimals?.[symbol]
|
|
5141
|
+
};
|
|
5142
|
+
}
|
|
5143
|
+
}
|
|
5121
5144
|
getUsdtAsset(chain) {
|
|
5122
5145
|
return this.getConfig(chain)?.assets?.USDT ?? "0x";
|
|
5123
5146
|
}
|
|
@@ -5224,6 +5247,9 @@ var ChainConfigService = class {
|
|
|
5224
5247
|
getCirclePaymasterAddress(chain) {
|
|
5225
5248
|
return this.getConfig(chain)?.addresses.CirclePaymaster;
|
|
5226
5249
|
}
|
|
5250
|
+
getSimplexPaymasterAddress(chain) {
|
|
5251
|
+
return this.getConfig(chain)?.addresses.SimplexPaymaster;
|
|
5252
|
+
}
|
|
5227
5253
|
getHyperbridgeAddress() {
|
|
5228
5254
|
return hyperbridgeAddress;
|
|
5229
5255
|
}
|
|
@@ -7044,6 +7070,16 @@ var ExpectedError = class _ExpectedError extends Error {
|
|
|
7044
7070
|
return error instanceof _ExpectedError;
|
|
7045
7071
|
}
|
|
7046
7072
|
};
|
|
7073
|
+
var MISSING_CONSENSUS_UPDATE_TIME_MESSAGE = "Consensus update time not found";
|
|
7074
|
+
var MissingConsensusUpdateTimeError = class _MissingConsensusUpdateTimeError extends Error {
|
|
7075
|
+
constructor(message = MISSING_CONSENSUS_UPDATE_TIME_MESSAGE, options) {
|
|
7076
|
+
super(message, options);
|
|
7077
|
+
this.name = "Hyperbridge/SDK/MissingConsensusUpdateTimeError";
|
|
7078
|
+
}
|
|
7079
|
+
static isError(error) {
|
|
7080
|
+
return error instanceof _MissingConsensusUpdateTimeError || error instanceof Error && error.message.toLowerCase().includes(MISSING_CONSENSUS_UPDATE_TIME_MESSAGE.toLowerCase());
|
|
7081
|
+
}
|
|
7082
|
+
};
|
|
7047
7083
|
|
|
7048
7084
|
// src/configs/constants.ts
|
|
7049
7085
|
var ISMP_PREFIX = ":child_storage:default:ISMPv2";
|
|
@@ -7357,8 +7393,15 @@ var SubstrateChain = class _SubstrateChain {
|
|
|
7357
7393
|
id: stateMachineId,
|
|
7358
7394
|
height: Number(stateMachineHeight.height)
|
|
7359
7395
|
};
|
|
7360
|
-
|
|
7361
|
-
|
|
7396
|
+
try {
|
|
7397
|
+
const updateTime = await this.rpcClient.call("ismp_queryStateMachineUpdateTime", [payload]);
|
|
7398
|
+
return BigInt(updateTime);
|
|
7399
|
+
} catch (error) {
|
|
7400
|
+
if (MissingConsensusUpdateTimeError.isError(error)) {
|
|
7401
|
+
throw new MissingConsensusUpdateTimeError(MISSING_CONSENSUS_UPDATE_TIME_MESSAGE, { cause: error });
|
|
7402
|
+
}
|
|
7403
|
+
throw error;
|
|
7404
|
+
}
|
|
7362
7405
|
}
|
|
7363
7406
|
/**
|
|
7364
7407
|
* Get the challenge period for a given state machine id.
|
|
@@ -7791,7 +7834,7 @@ var IntentsCoprocessor = class _IntentsCoprocessor {
|
|
|
7791
7834
|
*/
|
|
7792
7835
|
async sendExtrinsicWithRetries(extrinsic, maxRetries, timeoutMs) {
|
|
7793
7836
|
const keyPair = this.getKeyPair();
|
|
7794
|
-
|
|
7837
|
+
const baseTip = 1000000000n;
|
|
7795
7838
|
let attempt = 0;
|
|
7796
7839
|
while (attempt < maxRetries) {
|
|
7797
7840
|
const currentTip = baseTip * BigInt(2 ** attempt);
|
|
@@ -8104,26 +8147,76 @@ var IntentsCoprocessor = class _IntentsCoprocessor {
|
|
|
8104
8147
|
};
|
|
8105
8148
|
}
|
|
8106
8149
|
/**
|
|
8107
|
-
*
|
|
8108
|
-
|
|
8109
|
-
|
|
8110
|
-
|
|
8111
|
-
|
|
8112
|
-
const
|
|
8113
|
-
|
|
8114
|
-
|
|
8115
|
-
|
|
8116
|
-
|
|
8117
|
-
|
|
8118
|
-
|
|
8119
|
-
|
|
8120
|
-
|
|
8121
|
-
|
|
8122
|
-
|
|
8123
|
-
|
|
8150
|
+
* Reads the PhantomOrderRegistered events emitted in a single block.
|
|
8151
|
+
*/
|
|
8152
|
+
async getPhantomOrdersInBlock(blockNumber) {
|
|
8153
|
+
const blockHash = await this.api.rpc.chain.getBlockHash(blockNumber);
|
|
8154
|
+
const apiAt = await this.api.at(blockHash);
|
|
8155
|
+
const records = await apiAt.query.system.events();
|
|
8156
|
+
const orders = [];
|
|
8157
|
+
for (const { event } of records) {
|
|
8158
|
+
if (event.section !== "intentsCoprocessor" || event.method !== "PhantomOrderRegistered") continue;
|
|
8159
|
+
const [commitment, chain, createdAt, tokenA, tokenB, standardAmount] = event.data;
|
|
8160
|
+
orders.push({
|
|
8161
|
+
commitment: commitment.toHex(),
|
|
8162
|
+
chain: new TextDecoder().decode(util.hexToU8a(chain.toHex())),
|
|
8163
|
+
createdAt: createdAt.toNumber(),
|
|
8164
|
+
tokenA: tokenA.toHex(),
|
|
8165
|
+
tokenB: tokenB.toHex(),
|
|
8166
|
+
standardAmount: BigInt(standardAmount.toString())
|
|
8167
|
+
});
|
|
8168
|
+
}
|
|
8169
|
+
return orders;
|
|
8170
|
+
}
|
|
8171
|
+
/**
|
|
8172
|
+
* Polls for newly registered phantom orders, invoking the callback once per order.
|
|
8173
|
+
*
|
|
8174
|
+
* Each tick reads the current head and scans every block between the last one processed and that
|
|
8175
|
+
* head, so the block cursor — not the connection — determines what has been seen. This replaced a
|
|
8176
|
+
* system.events subscription, which was only as reliable as its socket: polkadot-js reconnects
|
|
8177
|
+
* the transport but does not reliably re-establish storage subscriptions, and anything emitted
|
|
8178
|
+
* while disconnected was lost silently. With a bid window measured in a handful of blocks, that
|
|
8179
|
+
* meant silently missed bids.
|
|
8180
|
+
*
|
|
8181
|
+
* Scanning a block range is gap-free rather than merely self-healing: an outage delays orders but
|
|
8182
|
+
* cannot drop them, because the cursor only advances past a block whose events were actually
|
|
8183
|
+
* read. Recovery replays the backlog.
|
|
8184
|
+
*
|
|
8185
|
+
* Returns a function that stops polling.
|
|
8186
|
+
*/
|
|
8187
|
+
pollPhantomOrders(callback, options = {}) {
|
|
8188
|
+
const { intervalMs = 6e3, maxBlocksPerPoll = 500, lookbackBlocks = 0, onError } = options;
|
|
8189
|
+
let cursor = null;
|
|
8190
|
+
let inFlight = false;
|
|
8191
|
+
let stopped = false;
|
|
8192
|
+
const tick = async () => {
|
|
8193
|
+
if (inFlight || stopped) return;
|
|
8194
|
+
inFlight = true;
|
|
8195
|
+
try {
|
|
8196
|
+
const head = (await this.api.rpc.chain.getHeader()).number.toNumber();
|
|
8197
|
+
if (cursor === null) {
|
|
8198
|
+
cursor = Math.max(head - 1 - lookbackBlocks, -1);
|
|
8199
|
+
}
|
|
8200
|
+
if (head <= cursor) return;
|
|
8201
|
+
const to = Math.min(head, cursor + maxBlocksPerPoll);
|
|
8202
|
+
for (let blockNumber = cursor + 1; blockNumber <= to; blockNumber++) {
|
|
8203
|
+
if (stopped) return;
|
|
8204
|
+
const orders = await this.getPhantomOrdersInBlock(blockNumber);
|
|
8205
|
+
for (const order of orders) callback(order);
|
|
8206
|
+
cursor = blockNumber;
|
|
8207
|
+
}
|
|
8208
|
+
} catch (err) {
|
|
8209
|
+
onError?.(err);
|
|
8210
|
+
} finally {
|
|
8211
|
+
inFlight = false;
|
|
8124
8212
|
}
|
|
8125
|
-
}
|
|
8126
|
-
|
|
8213
|
+
};
|
|
8214
|
+
void tick();
|
|
8215
|
+
const timer = setInterval(() => void tick(), intervalMs);
|
|
8216
|
+
return () => {
|
|
8217
|
+
stopped = true;
|
|
8218
|
+
clearInterval(timer);
|
|
8219
|
+
};
|
|
8127
8220
|
}
|
|
8128
8221
|
};
|
|
8129
8222
|
var TronChain = class _TronChain {
|
|
@@ -9256,7 +9349,12 @@ function sleep(ms) {
|
|
|
9256
9349
|
async function waitForChallengePeriod(chain, stateMachineHeight) {
|
|
9257
9350
|
const challengePeriod = await chain.challengePeriod(stateMachineHeight.id);
|
|
9258
9351
|
if (challengePeriod === BigInt(0)) return;
|
|
9259
|
-
const updateTime = await chain.stateMachineUpdateTime(stateMachineHeight)
|
|
9352
|
+
const updateTime = await retryPromise(() => chain.stateMachineUpdateTime(stateMachineHeight), {
|
|
9353
|
+
maxRetries: 3,
|
|
9354
|
+
backoffMs: 500,
|
|
9355
|
+
logMessage: "Fetching consensus update time while waiting for the challenge period",
|
|
9356
|
+
shouldRetry: (error) => !MissingConsensusUpdateTimeError.isError(error)
|
|
9357
|
+
});
|
|
9260
9358
|
let currentTimestamp = await chain.timestamp();
|
|
9261
9359
|
let timeElapsed = currentTimestamp - updateTime;
|
|
9262
9360
|
if (timeElapsed > challengePeriod) return;
|
|
@@ -9403,6 +9501,10 @@ function normalizeAddressForEvmBytes32(address) {
|
|
|
9403
9501
|
if (address.length === 66) return address;
|
|
9404
9502
|
return bytes20ToBytes32(address);
|
|
9405
9503
|
}
|
|
9504
|
+
function normalizeEvmAddress(address, field = "address") {
|
|
9505
|
+
if (!viem.isAddress(address)) throw new TypeError(`${field} must be a valid EVM address`);
|
|
9506
|
+
return address.toLowerCase();
|
|
9507
|
+
}
|
|
9406
9508
|
function normalizeAddressForStateMachine(address, stateMachineId) {
|
|
9407
9509
|
return isEvmChain(normalizeStateMachineId(stateMachineId)) ? normalizeAddressForEvmBytes32(address) : address;
|
|
9408
9510
|
}
|
|
@@ -9410,14 +9512,16 @@ var DEFAULT_LOGGER = consola.createConsola({
|
|
|
9410
9512
|
level: consola.LogLevels.silent
|
|
9411
9513
|
});
|
|
9412
9514
|
async function retryPromise(operation, retryConfig) {
|
|
9413
|
-
const { logger = DEFAULT_LOGGER, logMessage = "Retry operation failed" } = retryConfig;
|
|
9515
|
+
const { logger = DEFAULT_LOGGER, logMessage = "Retry operation failed", shouldRetry } = retryConfig;
|
|
9414
9516
|
let lastError;
|
|
9415
9517
|
for (let i = 0; i < retryConfig.maxRetries; i++) {
|
|
9416
9518
|
try {
|
|
9417
9519
|
return await operation();
|
|
9418
9520
|
} catch (error) {
|
|
9521
|
+
if (shouldRetry && !shouldRetry(error)) throw error;
|
|
9419
9522
|
logger.trace(`Retrying(${i}) > ${logMessage}`);
|
|
9420
9523
|
lastError = error;
|
|
9524
|
+
if (i === retryConfig.maxRetries - 1) break;
|
|
9421
9525
|
await new Promise((resolve) => setTimeout(resolve, retryConfig.backoffMs * 2 ** i));
|
|
9422
9526
|
}
|
|
9423
9527
|
}
|
|
@@ -11461,6 +11565,82 @@ query OrderStatus($commitment: String!) {
|
|
|
11461
11565
|
}
|
|
11462
11566
|
}
|
|
11463
11567
|
}`;
|
|
11568
|
+
var LATEST_PHANTOM_ORDER_PRICE_SNAPSHOT = `
|
|
11569
|
+
query LatestPhantomOrderPriceSnapshot($tokenA: String!, $tokenB: String!) {
|
|
11570
|
+
phantomOrderPriceSnapshots(
|
|
11571
|
+
filter: {
|
|
11572
|
+
and: [
|
|
11573
|
+
{ tokenA: { equalTo: $tokenA } }
|
|
11574
|
+
{ tokenB: { equalTo: $tokenB } }
|
|
11575
|
+
{ medianPrice: { isNull: false } }
|
|
11576
|
+
]
|
|
11577
|
+
}
|
|
11578
|
+
orderBy: BLOCK_NUMBER_DESC
|
|
11579
|
+
first: 1
|
|
11580
|
+
) {
|
|
11581
|
+
nodes {
|
|
11582
|
+
commitment
|
|
11583
|
+
tokenA
|
|
11584
|
+
tokenB
|
|
11585
|
+
standardAmount
|
|
11586
|
+
blockNumber
|
|
11587
|
+
medianPrice
|
|
11588
|
+
lowestPrice
|
|
11589
|
+
highestPrice
|
|
11590
|
+
bidCount
|
|
11591
|
+
snapshotTime
|
|
11592
|
+
}
|
|
11593
|
+
}
|
|
11594
|
+
}`;
|
|
11595
|
+
var LATEST_PHANTOM_ORDER_LIQUIDITY_SNAPSHOT = `
|
|
11596
|
+
query LatestPhantomOrderLiquiditySnapshot($tokenA: String!, $tokenB: String!) {
|
|
11597
|
+
phantomOrderPriceSnapshots(
|
|
11598
|
+
filter: {
|
|
11599
|
+
and: [
|
|
11600
|
+
{ tokenA: { equalTo: $tokenA } }
|
|
11601
|
+
{ tokenB: { equalTo: $tokenB } }
|
|
11602
|
+
]
|
|
11603
|
+
}
|
|
11604
|
+
orderBy: SNAPSHOT_TIME_DESC
|
|
11605
|
+
first: 1
|
|
11606
|
+
) {
|
|
11607
|
+
nodes {
|
|
11608
|
+
commitment
|
|
11609
|
+
tokenA
|
|
11610
|
+
tokenB
|
|
11611
|
+
snapshotTime
|
|
11612
|
+
}
|
|
11613
|
+
}
|
|
11614
|
+
}`;
|
|
11615
|
+
var LIQUIDITY_PROVIDER_BALANCES = `
|
|
11616
|
+
query LiquidityProviderBalanceAggregates($commitment: String!, $tokenAddress: String!) {
|
|
11617
|
+
liquidityProviderBalances(
|
|
11618
|
+
filter: {
|
|
11619
|
+
and: [
|
|
11620
|
+
{ commitment: { equalTo: $commitment } }
|
|
11621
|
+
{ tokenAddress: { equalTo: $tokenAddress } }
|
|
11622
|
+
]
|
|
11623
|
+
}
|
|
11624
|
+
) {
|
|
11625
|
+
aggregates {
|
|
11626
|
+
sum {
|
|
11627
|
+
balance
|
|
11628
|
+
}
|
|
11629
|
+
distinctCount {
|
|
11630
|
+
providerId
|
|
11631
|
+
}
|
|
11632
|
+
}
|
|
11633
|
+
groupedAggregates(groupBy: [CHAIN, TOKEN_ADDRESS]) {
|
|
11634
|
+
keys
|
|
11635
|
+
sum {
|
|
11636
|
+
balance
|
|
11637
|
+
}
|
|
11638
|
+
distinctCount {
|
|
11639
|
+
providerId
|
|
11640
|
+
}
|
|
11641
|
+
}
|
|
11642
|
+
}
|
|
11643
|
+
}`;
|
|
11464
11644
|
var TOKEN_GATEWAY_ASSET_TELEPORTED_STATUS = `
|
|
11465
11645
|
query TokenGatewayAssetTeleportedStatus($commitment: String!) {
|
|
11466
11646
|
tokenGatewayAssetTeleportedV2s(
|
|
@@ -11522,6 +11702,29 @@ async function queryAssetTeleported(params) {
|
|
|
11522
11702
|
function queryGetRequest(params) {
|
|
11523
11703
|
return _queryGetRequestInternal(params);
|
|
11524
11704
|
}
|
|
11705
|
+
async function _queryLatestPhantomOrderPriceSnapshot(params) {
|
|
11706
|
+
const response = await params.queryClient.request(
|
|
11707
|
+
LATEST_PHANTOM_ORDER_PRICE_SNAPSHOT,
|
|
11708
|
+
{
|
|
11709
|
+
tokenA: params.tokenA.toLowerCase(),
|
|
11710
|
+
tokenB: params.tokenB.toLowerCase()
|
|
11711
|
+
}
|
|
11712
|
+
);
|
|
11713
|
+
const snapshot = response.phantomOrderPriceSnapshots.nodes[0];
|
|
11714
|
+
if (!snapshot?.medianPrice) return;
|
|
11715
|
+
return {
|
|
11716
|
+
commitment: snapshot.commitment,
|
|
11717
|
+
tokenA: snapshot.tokenA,
|
|
11718
|
+
tokenB: snapshot.tokenB,
|
|
11719
|
+
standardAmount: BigInt(snapshot.standardAmount),
|
|
11720
|
+
blockNumber: BigInt(snapshot.blockNumber),
|
|
11721
|
+
medianPrice: BigInt(snapshot.medianPrice),
|
|
11722
|
+
lowestPrice: snapshot.lowestPrice === null ? void 0 : BigInt(snapshot.lowestPrice),
|
|
11723
|
+
highestPrice: snapshot.highestPrice === null ? void 0 : BigInt(snapshot.highestPrice),
|
|
11724
|
+
bidCount: snapshot.bidCount,
|
|
11725
|
+
snapshotTime: new Date(snapshot.snapshotTime)
|
|
11726
|
+
};
|
|
11727
|
+
}
|
|
11525
11728
|
async function _queryTokenGatewayAssetTeleportedInternal(params) {
|
|
11526
11729
|
const { commitmentHash, queryClient: client, logger = DEFAULT_LOGGER } = params;
|
|
11527
11730
|
const response = await retryPromise(
|
|
@@ -12022,6 +12225,7 @@ function createCancellationStorage(options = {}) {
|
|
|
12022
12225
|
const decoded = decodeIProof(value);
|
|
12023
12226
|
return decoded;
|
|
12024
12227
|
}
|
|
12228
|
+
if (key2.includes("postCommitment")) return value;
|
|
12025
12229
|
throw new Error(`Unknown storage key type: ${key2}`);
|
|
12026
12230
|
};
|
|
12027
12231
|
const setItem = async (key2, value) => {
|
|
@@ -12035,6 +12239,10 @@ function createCancellationStorage(options = {}) {
|
|
|
12035
12239
|
await baseStorage.setItem(key2, encoded);
|
|
12036
12240
|
return;
|
|
12037
12241
|
}
|
|
12242
|
+
if (key2.includes("postCommitment") && typeof value === "string") {
|
|
12243
|
+
await baseStorage.setItem(key2, value);
|
|
12244
|
+
return;
|
|
12245
|
+
}
|
|
12038
12246
|
throw new Error(`Unknown storage key type: ${key2}`);
|
|
12039
12247
|
};
|
|
12040
12248
|
const removeItem = async (key2) => {
|
|
@@ -12048,11 +12256,25 @@ function createCancellationStorage(options = {}) {
|
|
|
12048
12256
|
});
|
|
12049
12257
|
}
|
|
12050
12258
|
var STORAGE_KEYS = Object.freeze({
|
|
12051
|
-
destProof: (orderId) => `cancel-order:${orderId}:destProof`,
|
|
12052
|
-
getRequest: (orderId) => `cancel-order:${orderId}:getRequest`,
|
|
12053
|
-
sourceProof: (orderId) => `cancel-order:${orderId}:sourceProof`,
|
|
12054
|
-
postCommitment: (orderId) => `cancel-order:${orderId}:postCommitment`
|
|
12259
|
+
destProof: (orderId, source, destination) => `cancel-order:${cancellationScope(orderId, source, destination)}:destProof`,
|
|
12260
|
+
getRequest: (orderId, source, destination) => `cancel-order:${cancellationScope(orderId, source, destination)}:getRequest`,
|
|
12261
|
+
sourceProof: (orderId, source, destination) => `cancel-order:${cancellationScope(orderId, source, destination)}:sourceProof`,
|
|
12262
|
+
postCommitment: (orderId, source, destination) => `cancel-order:${cancellationScope(orderId, source, destination)}:postCommitment`
|
|
12055
12263
|
});
|
|
12264
|
+
var LEGACY_STORAGE_KEYS = Object.freeze({
|
|
12265
|
+
destProof: (orderId, source, destination) => `cancel-order:${legacyCancellationScope(orderId, source, destination)}:destProof`,
|
|
12266
|
+
getRequest: (orderId, source, destination) => `cancel-order:${legacyCancellationScope(orderId, source, destination)}:getRequest`,
|
|
12267
|
+
sourceProof: (orderId, source, destination) => `cancel-order:${legacyCancellationScope(orderId, source, destination)}:sourceProof`,
|
|
12268
|
+
postCommitment: (orderId, source, destination) => `cancel-order:${legacyCancellationScope(orderId, source, destination)}:postCommitment`
|
|
12269
|
+
});
|
|
12270
|
+
function cancellationScope(orderId, source, destination) {
|
|
12271
|
+
if (!source || !destination) return orderId;
|
|
12272
|
+
return `${orderId}:${encodeURIComponent(normalizeStateMachineId(source))}:${encodeURIComponent(normalizeStateMachineId(destination))}`;
|
|
12273
|
+
}
|
|
12274
|
+
function legacyCancellationScope(orderId, source, destination) {
|
|
12275
|
+
if (!source || !destination) return orderId;
|
|
12276
|
+
return `${orderId}:${encodeURIComponent(source)}:${encodeURIComponent(destination)}`;
|
|
12277
|
+
}
|
|
12056
12278
|
function createUsedUserOpsStorage(options = {}) {
|
|
12057
12279
|
options.env ?? detectEnvironment();
|
|
12058
12280
|
const driver = loadDriver({ options }) ?? inMemoryDriver__default.default();
|
|
@@ -15218,6 +15440,29 @@ async function convertFeeTokenToWei(ctx, feeTokenAmount, feeTokenIn, evmChainID)
|
|
|
15218
15440
|
}
|
|
15219
15441
|
|
|
15220
15442
|
// src/protocols/intents/OrderPlacer.ts
|
|
15443
|
+
function deriveCanonicalPlacedOrder(order, args) {
|
|
15444
|
+
const canonicalOrder = {
|
|
15445
|
+
...order,
|
|
15446
|
+
user: args.user,
|
|
15447
|
+
source: args.source,
|
|
15448
|
+
destination: args.destination,
|
|
15449
|
+
deadline: args.deadline,
|
|
15450
|
+
nonce: args.nonce,
|
|
15451
|
+
fees: args.fees,
|
|
15452
|
+
session: args.session,
|
|
15453
|
+
predispatch: {
|
|
15454
|
+
assets: args.predispatch.map((asset) => ({ ...asset })),
|
|
15455
|
+
call: order.predispatch.call
|
|
15456
|
+
},
|
|
15457
|
+
inputs: args.inputs.map((asset) => ({ ...asset })),
|
|
15458
|
+
output: {
|
|
15459
|
+
beneficiary: args.beneficiary,
|
|
15460
|
+
assets: args.outputs.map((asset) => ({ ...asset })),
|
|
15461
|
+
call: order.output.call
|
|
15462
|
+
}
|
|
15463
|
+
};
|
|
15464
|
+
return { ...canonicalOrder, id: orderCommitment(canonicalOrder) };
|
|
15465
|
+
}
|
|
15221
15466
|
var OrderPlacer = class {
|
|
15222
15467
|
/**
|
|
15223
15468
|
* @param ctx - Shared IntentsV2 context providing the source chain client,
|
|
@@ -15234,17 +15479,16 @@ var OrderPlacer = class {
|
|
|
15234
15479
|
* 1. Yields `{ to, data, sessionPrivateKey }` — the caller must sign a
|
|
15235
15480
|
* transaction sending `data` to `to` and pass the signed transaction back
|
|
15236
15481
|
* via `gen.next(signedTx)`.
|
|
15237
|
-
* 2. Returns `{ order, transactionHash }` — the finalized order
|
|
15238
|
-
*
|
|
15239
|
-
* transaction hash.
|
|
15482
|
+
* 2. Returns `{ order, transactionHash }` — the finalized order rebuilt from
|
|
15483
|
+
* the canonical `OrderPlaced` fields with its computed `id`, plus the
|
|
15484
|
+
* placement transaction hash.
|
|
15240
15485
|
*
|
|
15241
15486
|
* A fresh ephemeral session key is generated for every call. The key is
|
|
15242
15487
|
* stored immediately (without a commitment) so it can be retrieved by
|
|
15243
15488
|
* address, then updated with the commitment once the `OrderPlaced` event
|
|
15244
|
-
* confirms the
|
|
15489
|
+
* confirms the canonical order.
|
|
15245
15490
|
*
|
|
15246
|
-
* @param order - The order to place.
|
|
15247
|
-
* with the generated session key address before yielding.
|
|
15491
|
+
* @param order - The order to place. It is not mutated.
|
|
15248
15492
|
* @param graffiti - Optional bytes32 tag for orderflow attribution /
|
|
15249
15493
|
* revenue share. Defaults to {@link DEFAULT_GRAFFITI} (bytes32 zero).
|
|
15250
15494
|
* @yields `{ to, data, sessionPrivateKey }` — target contract address,
|
|
@@ -15259,7 +15503,7 @@ var OrderPlacer = class {
|
|
|
15259
15503
|
const account = accounts.privateKeyToAccount(privateKey);
|
|
15260
15504
|
const sessionKeyAddress = account.address;
|
|
15261
15505
|
const createdAt = Date.now();
|
|
15262
|
-
order
|
|
15506
|
+
const placementOrder = { ...order, session: sessionKeyAddress };
|
|
15263
15507
|
await this.ctx.sessionKeyStorage.setSessionKeyByAddress(sessionKeyAddress, {
|
|
15264
15508
|
privateKey,
|
|
15265
15509
|
address: sessionKeyAddress,
|
|
@@ -15268,7 +15512,7 @@ var OrderPlacer = class {
|
|
|
15268
15512
|
const data = viem.encodeFunctionData({
|
|
15269
15513
|
abi: ABI3,
|
|
15270
15514
|
functionName: "placeOrder",
|
|
15271
|
-
args: [transformOrderForContract(
|
|
15515
|
+
args: [transformOrderForContract(placementOrder), graffiti]
|
|
15272
15516
|
});
|
|
15273
15517
|
const intentGatewayAddress = this.ctx.source.configService.getIntentGatewayAddress(
|
|
15274
15518
|
normalizeStateMachineId(order.source)
|
|
@@ -15288,20 +15532,15 @@ var OrderPlacer = class {
|
|
|
15288
15532
|
if (!orderPlacedEvent) {
|
|
15289
15533
|
throw new Error("OrderPlaced event not found in transaction receipt");
|
|
15290
15534
|
}
|
|
15291
|
-
|
|
15292
|
-
order.inputs = orderPlacedEvent.args.inputs.map((input) => ({
|
|
15293
|
-
token: input.token,
|
|
15294
|
-
amount: input.amount
|
|
15295
|
-
}));
|
|
15296
|
-
order.id = orderCommitment(order);
|
|
15535
|
+
const finalizedOrder = deriveCanonicalPlacedOrder(placementOrder, orderPlacedEvent.args);
|
|
15297
15536
|
const sessionKeyData = {
|
|
15298
15537
|
privateKey,
|
|
15299
15538
|
address: sessionKeyAddress,
|
|
15300
|
-
commitment:
|
|
15539
|
+
commitment: finalizedOrder.id,
|
|
15301
15540
|
createdAt
|
|
15302
15541
|
};
|
|
15303
15542
|
await this.ctx.sessionKeyStorage.setSessionKeyByAddress(sessionKeyAddress, sessionKeyData);
|
|
15304
|
-
return { order, receipt };
|
|
15543
|
+
return { order: finalizedOrder, receipt };
|
|
15305
15544
|
}
|
|
15306
15545
|
};
|
|
15307
15546
|
|
|
@@ -15631,7 +15870,7 @@ var OrderExecutor = class {
|
|
|
15631
15870
|
}
|
|
15632
15871
|
}
|
|
15633
15872
|
};
|
|
15634
|
-
var OrderCanceller = class {
|
|
15873
|
+
var OrderCanceller = class _OrderCanceller {
|
|
15635
15874
|
/**
|
|
15636
15875
|
* @param ctx - Shared IntentsV2 context providing the source and destination
|
|
15637
15876
|
* chain clients, config service, and cancellation storage.
|
|
@@ -15640,6 +15879,9 @@ var OrderCanceller = class {
|
|
|
15640
15879
|
this.ctx = ctx;
|
|
15641
15880
|
}
|
|
15642
15881
|
ctx;
|
|
15882
|
+
static DEFAULT_MAX_RECOVERY_RESTARTS = 1;
|
|
15883
|
+
static PROOF_FRESHNESS_MAX_RETRIES = 3;
|
|
15884
|
+
static PROOF_FRESHNESS_BACKOFF_MS = 500;
|
|
15643
15885
|
logger = consola.createConsola({
|
|
15644
15886
|
level: consola.LogLevels.info,
|
|
15645
15887
|
formatOptions: { columns: 80, colors: true, compact: true, date: false }
|
|
@@ -15671,11 +15913,14 @@ var OrderCanceller = class {
|
|
|
15671
15913
|
* @returns The native token dispatch fee in wei.
|
|
15672
15914
|
*/
|
|
15673
15915
|
async quoteCancelFromSource(order) {
|
|
15674
|
-
if (order.source === order.destination) return { nativeValue: 0n, relayerFee: 0n };
|
|
15675
15916
|
const sourceStateMachine = normalizeStateMachineId(order.source);
|
|
15917
|
+
const destStateMachine = normalizeStateMachineId(order.destination);
|
|
15918
|
+
if (sourceStateMachine === destStateMachine) {
|
|
15919
|
+
return { nativeValue: 0n, relayerFee: 0n };
|
|
15920
|
+
}
|
|
15676
15921
|
const height = order.deadline + 1n;
|
|
15677
15922
|
const destIntentGateway = this.ctx.dest.configService.getIntentGatewayAddress(
|
|
15678
|
-
|
|
15923
|
+
destStateMachine
|
|
15679
15924
|
);
|
|
15680
15925
|
const slotHash = await this.ctx.dest.client.readContract({
|
|
15681
15926
|
abi: ABI3,
|
|
@@ -15687,8 +15932,8 @@ var OrderCanceller = class {
|
|
|
15687
15932
|
const context = encodeWithdrawalRequest(order, order.user);
|
|
15688
15933
|
const getRequest = {
|
|
15689
15934
|
source: sourceStateMachine,
|
|
15690
|
-
dest:
|
|
15691
|
-
from: this.ctx.source.configService.getIntentGatewayAddress(
|
|
15935
|
+
dest: destStateMachine,
|
|
15936
|
+
from: this.ctx.source.configService.getIntentGatewayAddress(destStateMachine),
|
|
15692
15937
|
nonce: await this.ctx.source.getHostNonce(),
|
|
15693
15938
|
height,
|
|
15694
15939
|
keys: [key],
|
|
@@ -15705,7 +15950,9 @@ var OrderCanceller = class {
|
|
|
15705
15950
|
* cancellation is complete.
|
|
15706
15951
|
*
|
|
15707
15952
|
* Delegates to `cancelOrderFromSource` or `cancelOrderFromDest` based on
|
|
15708
|
-
* the `from` parameter.
|
|
15953
|
+
* the `from` parameter. If Hyperbridge has pruned consensus data needed for
|
|
15954
|
+
* source-side GET recovery, clears its stale checkpoint and restarts the
|
|
15955
|
+
* source-side stream internally.
|
|
15709
15956
|
*
|
|
15710
15957
|
* @param order - The order to cancel.
|
|
15711
15958
|
* @param indexerClient - Indexer client used to stream ISMP request status
|
|
@@ -15715,12 +15962,32 @@ var OrderCanceller = class {
|
|
|
15715
15962
|
* cancellation lifecycle.
|
|
15716
15963
|
*/
|
|
15717
15964
|
async *cancelOrder(order, indexerClient, options = {}) {
|
|
15718
|
-
const
|
|
15965
|
+
const sourceStateMachine = normalizeStateMachineId(order.source);
|
|
15966
|
+
const destStateMachine = normalizeStateMachineId(order.destination);
|
|
15967
|
+
const isSameChain = sourceStateMachine === destStateMachine;
|
|
15719
15968
|
if (options.from === "destination" && !isSameChain) {
|
|
15720
15969
|
yield* this.cancelOrderFromDest(order, indexerClient);
|
|
15721
15970
|
return;
|
|
15722
15971
|
}
|
|
15723
|
-
|
|
15972
|
+
let recoveryRestarts = 0;
|
|
15973
|
+
while (true) {
|
|
15974
|
+
try {
|
|
15975
|
+
yield* this.cancelOrderFromSource(order, indexerClient);
|
|
15976
|
+
return;
|
|
15977
|
+
} catch (error) {
|
|
15978
|
+
if (!MissingConsensusUpdateTimeError.isError(error)) throw error;
|
|
15979
|
+
if (recoveryRestarts >= _OrderCanceller.DEFAULT_MAX_RECOVERY_RESTARTS) {
|
|
15980
|
+
throw new Error(
|
|
15981
|
+
`Cancellation recovery stopped after ${recoveryRestarts} restart(s): Hyperbridge no longer retains a required consensus update.`
|
|
15982
|
+
);
|
|
15983
|
+
}
|
|
15984
|
+
recoveryRestarts += 1;
|
|
15985
|
+
this.logger.warn(
|
|
15986
|
+
`Restarting cancellation recovery (${recoveryRestarts}/${_OrderCanceller.DEFAULT_MAX_RECOVERY_RESTARTS}) after a required consensus update was pruned`
|
|
15987
|
+
);
|
|
15988
|
+
await this.clearGetRecoveryCache(order);
|
|
15989
|
+
}
|
|
15990
|
+
}
|
|
15724
15991
|
}
|
|
15725
15992
|
/**
|
|
15726
15993
|
* Async generator that cancels an order by initiating the cancel from the
|
|
@@ -15746,11 +16013,10 @@ var OrderCanceller = class {
|
|
|
15746
16013
|
* @throws If the cancel transaction does not contain the expected on-chain event.
|
|
15747
16014
|
*/
|
|
15748
16015
|
async *cancelOrderFromSource(order, indexerClient) {
|
|
15749
|
-
const
|
|
15750
|
-
const
|
|
15751
|
-
const
|
|
15752
|
-
|
|
15753
|
-
);
|
|
16016
|
+
const sourceStateMachine = normalizeStateMachineId(order.source);
|
|
16017
|
+
const destStateMachine = normalizeStateMachineId(order.destination);
|
|
16018
|
+
const isSameChain = sourceStateMachine === destStateMachine;
|
|
16019
|
+
const intentGatewayAddress = this.ctx.source.configService.getIntentGatewayAddress(sourceStateMachine);
|
|
15754
16020
|
if (isSameChain) {
|
|
15755
16021
|
const data = viem.encodeFunctionData({
|
|
15756
16022
|
abi: ABI3,
|
|
@@ -15779,18 +16045,37 @@ var OrderCanceller = class {
|
|
|
15779
16045
|
};
|
|
15780
16046
|
return;
|
|
15781
16047
|
}
|
|
16048
|
+
const storageKeys = this.recoveryStorageKeys(order);
|
|
16049
|
+
const legacyStorageKeys = this.legacyRecoveryStorageKeys(order);
|
|
15782
16050
|
const hyperbridge = indexerClient.hyperbridge;
|
|
15783
|
-
const sourceStateMachine = normalizeStateMachineId(order.source);
|
|
15784
16051
|
const sourceConsensusStateId = this.ctx.source.configService.getConsensusStateId(sourceStateMachine);
|
|
15785
|
-
let destIProof = await this.
|
|
16052
|
+
let destIProof = await this.getRecoveryItem(
|
|
16053
|
+
storageKeys.destProof,
|
|
16054
|
+
legacyStorageKeys.map((keys) => keys.destProof)
|
|
16055
|
+
);
|
|
15786
16056
|
if (!destIProof) {
|
|
15787
16057
|
destIProof = yield* this.fetchDestinationProof(order, indexerClient);
|
|
15788
|
-
await this.ctx.cancellationStorage.setItem(
|
|
16058
|
+
await this.ctx.cancellationStorage.setItem(storageKeys.destProof, destIProof);
|
|
15789
16059
|
} else {
|
|
15790
|
-
|
|
16060
|
+
let refreshed = false;
|
|
16061
|
+
try {
|
|
16062
|
+
await this.assertProofFresh(hyperbridge, destIProof);
|
|
16063
|
+
} catch (error) {
|
|
16064
|
+
if (!MissingConsensusUpdateTimeError.isError(error)) throw error;
|
|
16065
|
+
await this.removeRecoveryItems(
|
|
16066
|
+
storageKeys.destProof,
|
|
16067
|
+
...legacyStorageKeys.map((keys) => keys.destProof)
|
|
16068
|
+
);
|
|
16069
|
+
destIProof = yield* this.fetchDestinationProof(order, indexerClient);
|
|
16070
|
+
await this.ctx.cancellationStorage.setItem(storageKeys.destProof, destIProof);
|
|
16071
|
+
refreshed = true;
|
|
16072
|
+
}
|
|
16073
|
+
if (!refreshed) yield { status: "DESTINATION_FINALIZED", proof: destIProof };
|
|
15791
16074
|
}
|
|
15792
|
-
|
|
15793
|
-
|
|
16075
|
+
await this.assertProofFresh(hyperbridge, destIProof);
|
|
16076
|
+
let getRequest = await this.getRecoveryItem(
|
|
16077
|
+
storageKeys.getRequest,
|
|
16078
|
+
legacyStorageKeys.map((keys) => keys.getRequest)
|
|
15794
16079
|
);
|
|
15795
16080
|
if (!getRequest) {
|
|
15796
16081
|
const quote = await this.quoteCancelFromSource(order);
|
|
@@ -15810,7 +16095,7 @@ var OrderCanceller = class {
|
|
|
15810
16095
|
const request = events.find((e) => e.eventName === "GetRequestEvent");
|
|
15811
16096
|
if (!request) throw new Error("GetRequest missing");
|
|
15812
16097
|
getRequest = request.args;
|
|
15813
|
-
await this.ctx.cancellationStorage.setItem(
|
|
16098
|
+
await this.ctx.cancellationStorage.setItem(storageKeys.getRequest, getRequest);
|
|
15814
16099
|
yield {
|
|
15815
16100
|
status: "CANCEL_STARTED",
|
|
15816
16101
|
receipt
|
|
@@ -15829,8 +16114,9 @@ var OrderCanceller = class {
|
|
|
15829
16114
|
metadata: statusUpdate.metadata
|
|
15830
16115
|
};
|
|
15831
16116
|
const sourceHeight = BigInt(statusUpdate.metadata.blockNumber);
|
|
15832
|
-
let sourceIProof = await this.
|
|
15833
|
-
|
|
16117
|
+
let sourceIProof = await this.getRecoveryItem(
|
|
16118
|
+
storageKeys.sourceProof,
|
|
16119
|
+
legacyStorageKeys.map((keys) => keys.sourceProof)
|
|
15834
16120
|
);
|
|
15835
16121
|
if (!sourceIProof) {
|
|
15836
16122
|
sourceIProof = await fetchSourceProof(
|
|
@@ -15840,8 +16126,9 @@ var OrderCanceller = class {
|
|
|
15840
16126
|
sourceConsensusStateId,
|
|
15841
16127
|
sourceHeight
|
|
15842
16128
|
);
|
|
15843
|
-
await this.ctx.cancellationStorage.setItem(
|
|
16129
|
+
await this.ctx.cancellationStorage.setItem(storageKeys.sourceProof, sourceIProof);
|
|
15844
16130
|
}
|
|
16131
|
+
await this.assertProofFresh(hyperbridge, sourceIProof);
|
|
15845
16132
|
await waitForChallengePeriod(hyperbridge, {
|
|
15846
16133
|
height: sourceIProof.height,
|
|
15847
16134
|
id: {
|
|
@@ -15849,6 +16136,10 @@ var OrderCanceller = class {
|
|
|
15849
16136
|
consensusStateId: sourceConsensusStateId
|
|
15850
16137
|
}
|
|
15851
16138
|
});
|
|
16139
|
+
await Promise.all([
|
|
16140
|
+
this.assertProofFresh(hyperbridge, sourceIProof),
|
|
16141
|
+
this.assertProofFresh(hyperbridge, destIProof)
|
|
16142
|
+
]);
|
|
15852
16143
|
const getRequestMessage = {
|
|
15853
16144
|
kind: "GetRequest",
|
|
15854
16145
|
requests: [getRequest],
|
|
@@ -15870,9 +16161,12 @@ var OrderCanceller = class {
|
|
|
15870
16161
|
status: "HYPERBRIDGE_FINALIZED",
|
|
15871
16162
|
metadata: statusUpdate.metadata
|
|
15872
16163
|
};
|
|
15873
|
-
await this.
|
|
15874
|
-
|
|
15875
|
-
|
|
16164
|
+
await this.removeRecoveryItems(
|
|
16165
|
+
storageKeys.destProof,
|
|
16166
|
+
storageKeys.getRequest,
|
|
16167
|
+
storageKeys.sourceProof,
|
|
16168
|
+
...legacyStorageKeys.flatMap((keys) => [keys.destProof, keys.getRequest, keys.sourceProof])
|
|
16169
|
+
);
|
|
15876
16170
|
return;
|
|
15877
16171
|
}
|
|
15878
16172
|
}
|
|
@@ -15889,9 +16183,11 @@ var OrderCanceller = class {
|
|
|
15889
16183
|
* @returns The native token dispatch fee in wei.
|
|
15890
16184
|
*/
|
|
15891
16185
|
async quoteCancelFromDest(order) {
|
|
15892
|
-
if (order.source === order.destination) return { nativeValue: 0n, relayerFee: 0n };
|
|
15893
|
-
const destStateMachine = normalizeStateMachineId(order.destination);
|
|
15894
16186
|
const sourceStateMachine = normalizeStateMachineId(order.source);
|
|
16187
|
+
const destStateMachine = normalizeStateMachineId(order.destination);
|
|
16188
|
+
if (sourceStateMachine === destStateMachine) {
|
|
16189
|
+
return { nativeValue: 0n, relayerFee: 0n };
|
|
16190
|
+
}
|
|
15895
16191
|
const destIntentGateway = this.ctx.dest.configService.getIntentGatewayAddress(destStateMachine);
|
|
15896
16192
|
const sourceIntentGateway = this.ctx.source.configService.getIntentGatewayAddress(sourceStateMachine);
|
|
15897
16193
|
const relayerFee = await this.estimateRelayerFee(sourceStateMachine, destStateMachine);
|
|
@@ -15929,11 +16225,13 @@ var OrderCanceller = class {
|
|
|
15929
16225
|
* @throws If the cancel transaction does not contain a `PostRequestEvent`.
|
|
15930
16226
|
*/
|
|
15931
16227
|
async *cancelOrderFromDest(order, indexerClient) {
|
|
15932
|
-
const
|
|
16228
|
+
const storageKeys = this.recoveryStorageKeys(order);
|
|
15933
16229
|
const destStateMachine = normalizeStateMachineId(order.destination);
|
|
15934
16230
|
const intentGatewayAddress = this.ctx.dest.configService.getIntentGatewayAddress(destStateMachine);
|
|
15935
|
-
|
|
15936
|
-
|
|
16231
|
+
const legacyStorageKeys = this.legacyRecoveryStorageKeys(order);
|
|
16232
|
+
let commitment = await this.getRecoveryItem(
|
|
16233
|
+
storageKeys.postCommitment,
|
|
16234
|
+
legacyStorageKeys.map((keys) => keys.postCommitment)
|
|
15937
16235
|
);
|
|
15938
16236
|
if (!commitment) {
|
|
15939
16237
|
const quote = await this.quoteCancelFromDest(order);
|
|
@@ -15958,7 +16256,7 @@ var OrderCanceller = class {
|
|
|
15958
16256
|
if (!postEvent) throw new Error("PostRequestEvent not found in cancel transaction receipt");
|
|
15959
16257
|
const postArgs = postEvent.args;
|
|
15960
16258
|
commitment = postRequestCommitment(postArgs).commitment;
|
|
15961
|
-
await this.ctx.cancellationStorage.setItem(
|
|
16259
|
+
await this.ctx.cancellationStorage.setItem(storageKeys.postCommitment, commitment);
|
|
15962
16260
|
}
|
|
15963
16261
|
const statusStream = indexerClient.postRequestStatusStream(commitment);
|
|
15964
16262
|
for await (const statusUpdate of statusStream) {
|
|
@@ -15992,7 +16290,10 @@ var OrderCanceller = class {
|
|
|
15992
16290
|
if (refundEvents.length === 0) {
|
|
15993
16291
|
throw new Error("EscrowRefunded event not found in source-chain delivery receipt");
|
|
15994
16292
|
}
|
|
15995
|
-
await this.
|
|
16293
|
+
await this.removeRecoveryItems(
|
|
16294
|
+
storageKeys.postCommitment,
|
|
16295
|
+
...legacyStorageKeys.map((keys) => keys.postCommitment)
|
|
16296
|
+
);
|
|
15996
16297
|
yield {
|
|
15997
16298
|
status: "CANCELLATION_COMPLETE",
|
|
15998
16299
|
blockNumber: statusUpdate.metadata.blockNumber,
|
|
@@ -16035,7 +16336,7 @@ var OrderCanceller = class {
|
|
|
16035
16336
|
const intentGatewayV2Address = this.ctx.dest.configService.getIntentGatewayAddress(
|
|
16036
16337
|
this.ctx.dest.config.stateMachineId
|
|
16037
16338
|
);
|
|
16038
|
-
const orderId = order
|
|
16339
|
+
const orderId = this.orderId(order);
|
|
16039
16340
|
const slotHash = await this.ctx.dest.client.readContract({
|
|
16040
16341
|
abi: ABI3,
|
|
16041
16342
|
address: intentGatewayV2Address,
|
|
@@ -16052,6 +16353,7 @@ var OrderCanceller = class {
|
|
|
16052
16353
|
yield { status: "DESTINATION_FINALIZED", proof };
|
|
16053
16354
|
return proof;
|
|
16054
16355
|
} catch (e) {
|
|
16356
|
+
if (MissingConsensusUpdateTimeError.isError(e)) throw e;
|
|
16055
16357
|
lastFailedHeight = latestHeight;
|
|
16056
16358
|
await sleep(1e4);
|
|
16057
16359
|
}
|
|
@@ -16082,6 +16384,7 @@ var OrderCanceller = class {
|
|
|
16082
16384
|
this.logger.info(`Unsigned GET ${commitment} submitted; waiting for Hyperbridge response receipt`);
|
|
16083
16385
|
await sleep(3e4);
|
|
16084
16386
|
} catch (error) {
|
|
16387
|
+
if (MissingConsensusUpdateTimeError.isError(error)) throw error;
|
|
16085
16388
|
this.logger.warn(
|
|
16086
16389
|
`Unsigned GET submit failed for ${commitment}; polling response receipt before failing: ${String(error)}`
|
|
16087
16390
|
);
|
|
@@ -16090,14 +16393,128 @@ var OrderCanceller = class {
|
|
|
16090
16393
|
await this.pollDeliveredReceipt(hyperbridge, commitment);
|
|
16091
16394
|
this.logger.info(`Confirmed Hyperbridge GET delivery for ${commitment}`);
|
|
16092
16395
|
} catch (error) {
|
|
16396
|
+
if (MissingConsensusUpdateTimeError.isError(error)) throw error;
|
|
16093
16397
|
const message2 = `Failed to deliver GET request to Hyperbridge; no response receipt found for ${commitment}: ${String(error)}`;
|
|
16094
16398
|
this.logger.error(message2);
|
|
16095
16399
|
throw new Error(message2);
|
|
16096
16400
|
}
|
|
16097
16401
|
}
|
|
16402
|
+
/** Verify that Hyperbridge still retains the consensus update for a proof. */
|
|
16403
|
+
async assertProofFresh(hyperbridge, proof) {
|
|
16404
|
+
await retryPromise(
|
|
16405
|
+
() => hyperbridge.stateMachineUpdateTime({
|
|
16406
|
+
height: proof.height,
|
|
16407
|
+
id: {
|
|
16408
|
+
stateId: parseStateMachineId(proof.stateMachine).stateId,
|
|
16409
|
+
consensusStateId: proof.consensusStateId
|
|
16410
|
+
}
|
|
16411
|
+
}),
|
|
16412
|
+
{
|
|
16413
|
+
maxRetries: _OrderCanceller.PROOF_FRESHNESS_MAX_RETRIES,
|
|
16414
|
+
backoffMs: _OrderCanceller.PROOF_FRESHNESS_BACKOFF_MS,
|
|
16415
|
+
logger: this.logger,
|
|
16416
|
+
logMessage: `Checking consensus update time for proof at height ${proof.height}`,
|
|
16417
|
+
shouldRetry: (error) => !MissingConsensusUpdateTimeError.isError(error)
|
|
16418
|
+
}
|
|
16419
|
+
);
|
|
16420
|
+
}
|
|
16421
|
+
/**
|
|
16422
|
+
* Drops the source-initiated GET recovery checkpoint after Hyperbridge prunes
|
|
16423
|
+
* a consensus update required by that recovery attempt.
|
|
16424
|
+
*/
|
|
16425
|
+
async clearGetRecoveryCache(order) {
|
|
16426
|
+
const keys = this.recoveryStorageKeys(order);
|
|
16427
|
+
const legacyStorageKeys = this.legacyRecoveryStorageKeys(order);
|
|
16428
|
+
await this.removeRecoveryItems(
|
|
16429
|
+
keys.destProof,
|
|
16430
|
+
keys.sourceProof,
|
|
16431
|
+
keys.getRequest,
|
|
16432
|
+
...legacyStorageKeys.flatMap((legacyKeys) => [
|
|
16433
|
+
legacyKeys.destProof,
|
|
16434
|
+
legacyKeys.sourceProof,
|
|
16435
|
+
legacyKeys.getRequest
|
|
16436
|
+
])
|
|
16437
|
+
);
|
|
16438
|
+
}
|
|
16439
|
+
/**
|
|
16440
|
+
* Returns the pair-scoped storage keys used to resume cancellation recovery
|
|
16441
|
+
* for an order.
|
|
16442
|
+
*
|
|
16443
|
+
* @param order - The order whose source/destination recovery state is stored.
|
|
16444
|
+
*/
|
|
16445
|
+
recoveryStorageKeys(order) {
|
|
16446
|
+
const orderId = this.orderId(order);
|
|
16447
|
+
return {
|
|
16448
|
+
destProof: STORAGE_KEYS.destProof(orderId, order.source, order.destination),
|
|
16449
|
+
getRequest: STORAGE_KEYS.getRequest(orderId, order.source, order.destination),
|
|
16450
|
+
sourceProof: STORAGE_KEYS.sourceProof(orderId, order.source, order.destination),
|
|
16451
|
+
postCommitment: STORAGE_KEYS.postCommitment(orderId, order.source, order.destination)
|
|
16452
|
+
};
|
|
16453
|
+
}
|
|
16454
|
+
/** Older SDK key shapes, checked once and migrated to the normalized pair-scoped key. */
|
|
16455
|
+
legacyRecoveryStorageKeys(order) {
|
|
16456
|
+
const orderId = this.orderId(order);
|
|
16457
|
+
return [
|
|
16458
|
+
{
|
|
16459
|
+
destProof: LEGACY_STORAGE_KEYS.destProof(orderId, order.source, order.destination),
|
|
16460
|
+
getRequest: LEGACY_STORAGE_KEYS.getRequest(orderId, order.source, order.destination),
|
|
16461
|
+
sourceProof: LEGACY_STORAGE_KEYS.sourceProof(orderId, order.source, order.destination),
|
|
16462
|
+
postCommitment: LEGACY_STORAGE_KEYS.postCommitment(orderId, order.source, order.destination)
|
|
16463
|
+
},
|
|
16464
|
+
{
|
|
16465
|
+
destProof: LEGACY_STORAGE_KEYS.destProof(orderId),
|
|
16466
|
+
getRequest: LEGACY_STORAGE_KEYS.getRequest(orderId),
|
|
16467
|
+
sourceProof: LEGACY_STORAGE_KEYS.sourceProof(orderId),
|
|
16468
|
+
postCommitment: LEGACY_STORAGE_KEYS.postCommitment(orderId)
|
|
16469
|
+
}
|
|
16470
|
+
];
|
|
16471
|
+
}
|
|
16472
|
+
async getRecoveryItem(currentKey, legacyKeys) {
|
|
16473
|
+
const current = await this.ctx.cancellationStorage.getItem(currentKey);
|
|
16474
|
+
if (current) return current;
|
|
16475
|
+
for (const legacyKey of new Set(legacyKeys)) {
|
|
16476
|
+
if (legacyKey === currentKey) continue;
|
|
16477
|
+
const legacy = await this.ctx.cancellationStorage.getItem(legacyKey);
|
|
16478
|
+
if (!legacy) continue;
|
|
16479
|
+
await this.ctx.cancellationStorage.setItem(currentKey, legacy);
|
|
16480
|
+
await this.ctx.cancellationStorage.removeItem(legacyKey);
|
|
16481
|
+
return legacy;
|
|
16482
|
+
}
|
|
16483
|
+
return null;
|
|
16484
|
+
}
|
|
16485
|
+
async removeRecoveryItems(...keys) {
|
|
16486
|
+
await Promise.all(
|
|
16487
|
+
[...new Set(keys)].map((key) => this.ctx.cancellationStorage.removeItem(key))
|
|
16488
|
+
);
|
|
16489
|
+
}
|
|
16490
|
+
/**
|
|
16491
|
+
* Returns the order identifier required to persist or clear recovery state.
|
|
16492
|
+
*
|
|
16493
|
+
* @param order - The order being cancelled.
|
|
16494
|
+
* @throws If the order has no identifier.
|
|
16495
|
+
*/
|
|
16496
|
+
orderId(order) {
|
|
16497
|
+
if (!order.id) throw new Error("An order id is required to recover cancellation");
|
|
16498
|
+
return order.id;
|
|
16499
|
+
}
|
|
16500
|
+
/**
|
|
16501
|
+
* Reads the Hyperbridge response receipt for a GET request commitment.
|
|
16502
|
+
*
|
|
16503
|
+
* @param hyperbridge - Hyperbridge chain client used to query the receipt.
|
|
16504
|
+
* @param commitment - Commitment of the GET request.
|
|
16505
|
+
* @returns The receipt commitment when delivered, otherwise `undefined`.
|
|
16506
|
+
*/
|
|
16098
16507
|
async queryDeliveredReceipt(hyperbridge, commitment) {
|
|
16099
16508
|
return hyperbridge.queryResponseReceipt(commitment);
|
|
16100
16509
|
}
|
|
16510
|
+
/**
|
|
16511
|
+
* Polls Hyperbridge until it records a response receipt for the GET request.
|
|
16512
|
+
*
|
|
16513
|
+
* @param hyperbridge - Hyperbridge chain client used to query the receipt.
|
|
16514
|
+
* @param commitment - Commitment of the GET request.
|
|
16515
|
+
* @returns The delivered response receipt commitment.
|
|
16516
|
+
* @throws If no receipt is observed within the configured retry limit.
|
|
16517
|
+
*/
|
|
16101
16518
|
async pollDeliveredReceipt(hyperbridge, commitment) {
|
|
16102
16519
|
this.logger.info(`Polling Hyperbridge GET response receipt for ${commitment}`);
|
|
16103
16520
|
return retryPromise(
|
|
@@ -17310,6 +17727,178 @@ var OrderStatusChecker = class {
|
|
|
17310
17727
|
return true;
|
|
17311
17728
|
}
|
|
17312
17729
|
};
|
|
17730
|
+
var COMMITMENT_PATTERN = /^0x[0-9a-f]{64}$/i;
|
|
17731
|
+
var LiquidityEngine = class {
|
|
17732
|
+
/**
|
|
17733
|
+
* @param queryClient - Nexus GraphQL client attached to the gateway.
|
|
17734
|
+
* @param chainConfigService - Resolves token decimals for formatted results.
|
|
17735
|
+
*/
|
|
17736
|
+
constructor(queryClient, chainConfigService) {
|
|
17737
|
+
this.queryClient = queryClient;
|
|
17738
|
+
this.chainConfigService = chainConfigService;
|
|
17739
|
+
}
|
|
17740
|
+
queryClient;
|
|
17741
|
+
chainConfigService;
|
|
17742
|
+
/**
|
|
17743
|
+
* Retrieves the newest directional Phantom snapshot for a pair and its
|
|
17744
|
+
* indexed output-token liquidity.
|
|
17745
|
+
*
|
|
17746
|
+
* Nexus filters balances to the canonical output token, then aggregates them
|
|
17747
|
+
* overall and by chain. The returned amounts are decimal strings: the total
|
|
17748
|
+
* uses the canonical Base output-token decimals, while each chain group uses
|
|
17749
|
+
* that chain's token decimals. They describe `snapshotTime`, not live
|
|
17750
|
+
* reservations or fill guarantees.
|
|
17751
|
+
*
|
|
17752
|
+
* @param params - Canonical Phantom-market input and output token addresses.
|
|
17753
|
+
* @returns The latest snapshot, or `undefined` if Nexus has no snapshot for
|
|
17754
|
+
* the directional pair.
|
|
17755
|
+
* @throws {InvalidAvailableLiquiditySnapshotError} If Nexus returns malformed
|
|
17756
|
+
* or internally inconsistent snapshot data.
|
|
17757
|
+
*/
|
|
17758
|
+
async getAvailableLiquiditySnapshot(params) {
|
|
17759
|
+
const tokenIn = normalizeEvmAddress(params.tokenIn, "tokenIn");
|
|
17760
|
+
const tokenOut = normalizeEvmAddress(params.tokenOut, "tokenOut");
|
|
17761
|
+
const response = await this.queryClient.request(
|
|
17762
|
+
LATEST_PHANTOM_ORDER_LIQUIDITY_SNAPSHOT,
|
|
17763
|
+
{ tokenA: tokenIn, tokenB: tokenOut }
|
|
17764
|
+
);
|
|
17765
|
+
const node = response?.phantomOrderPriceSnapshots?.nodes?.[0];
|
|
17766
|
+
if (!node) return;
|
|
17767
|
+
const commitment = node.commitment.toLowerCase();
|
|
17768
|
+
if (!COMMITMENT_PATTERN.test(commitment)) {
|
|
17769
|
+
throw new InvalidAvailableLiquiditySnapshotError(commitment || "<missing>", "commitment is not bytes32 hex");
|
|
17770
|
+
}
|
|
17771
|
+
if (node.tokenA.toLowerCase() !== tokenIn || node.tokenB.toLowerCase() !== tokenOut) {
|
|
17772
|
+
throw new InvalidAvailableLiquiditySnapshotError(commitment, "snapshot token pair does not match the query");
|
|
17773
|
+
}
|
|
17774
|
+
const snapshotTime = new Date(dateStringtoTimestamp(node.snapshotTime));
|
|
17775
|
+
if (Number.isNaN(snapshotTime.getTime())) {
|
|
17776
|
+
throw new InvalidAvailableLiquiditySnapshotError(commitment, "snapshotTime is invalid");
|
|
17777
|
+
}
|
|
17778
|
+
const { totalLiquidity, providerCount, liquidityByChain } = await this.querySnapshotLiquidityAggregates({
|
|
17779
|
+
commitment,
|
|
17780
|
+
tokenAddress: tokenOut
|
|
17781
|
+
});
|
|
17782
|
+
return {
|
|
17783
|
+
totalLiquidity: this.formatLiquidity(totalLiquidity, "EVM-8453" /* BASE_MAINNET */, tokenOut, commitment),
|
|
17784
|
+
providerCount,
|
|
17785
|
+
tokenAddress: tokenOut,
|
|
17786
|
+
snapshotTime,
|
|
17787
|
+
liquidityByChain: liquidityByChain.map((group) => ({
|
|
17788
|
+
...group,
|
|
17789
|
+
totalLiquidity: this.formatLiquidity(group.totalLiquidity, group.chain, group.tokenAddress, commitment)
|
|
17790
|
+
}))
|
|
17791
|
+
};
|
|
17792
|
+
}
|
|
17793
|
+
/**
|
|
17794
|
+
* Requests server-side sums and distinct provider counts for one immutable
|
|
17795
|
+
* snapshot/output-token pair, including chain-level aggregate groups.
|
|
17796
|
+
*
|
|
17797
|
+
* `commitment` uniquely identifies the selected snapshot
|
|
17798
|
+
*/
|
|
17799
|
+
async querySnapshotLiquidityAggregates(params) {
|
|
17800
|
+
const response = await this.queryClient.request(
|
|
17801
|
+
LIQUIDITY_PROVIDER_BALANCES,
|
|
17802
|
+
{ commitment: params.commitment, tokenAddress: params.tokenAddress }
|
|
17803
|
+
);
|
|
17804
|
+
const connection = response?.liquidityProviderBalances;
|
|
17805
|
+
const aggregates = connection?.aggregates;
|
|
17806
|
+
if (!connection || !aggregates) {
|
|
17807
|
+
throw new InvalidAvailableLiquiditySnapshotError(
|
|
17808
|
+
params.commitment,
|
|
17809
|
+
"liquidityProviderBalances aggregates are missing"
|
|
17810
|
+
);
|
|
17811
|
+
}
|
|
17812
|
+
const totalLiquidity = parseSnapshotBigInt(aggregates.sum.balance ?? "0", params.commitment, "total balance");
|
|
17813
|
+
const providerCount = parseProviderCount(aggregates.distinctCount.providerId, params.commitment, "total");
|
|
17814
|
+
const liquidityByChain = connection.groupedAggregates.map((group, index) => {
|
|
17815
|
+
const [chain, tokenAddress] = group.keys;
|
|
17816
|
+
if (!chain?.trim() || !tokenAddress) {
|
|
17817
|
+
throw new InvalidAvailableLiquiditySnapshotError(
|
|
17818
|
+
params.commitment,
|
|
17819
|
+
`liquidity group ${index} has invalid keys`
|
|
17820
|
+
);
|
|
17821
|
+
}
|
|
17822
|
+
const normalizedTokenAddress = normalizeIndexedLiquidityAddress(
|
|
17823
|
+
tokenAddress,
|
|
17824
|
+
params.commitment,
|
|
17825
|
+
`liquidity group ${index} tokenAddress`
|
|
17826
|
+
);
|
|
17827
|
+
if (normalizedTokenAddress !== params.tokenAddress) {
|
|
17828
|
+
throw new InvalidAvailableLiquiditySnapshotError(
|
|
17829
|
+
params.commitment,
|
|
17830
|
+
`liquidity group ${index} tokenAddress does not match the snapshot output token`
|
|
17831
|
+
);
|
|
17832
|
+
}
|
|
17833
|
+
return {
|
|
17834
|
+
chain: chain.trim(),
|
|
17835
|
+
tokenAddress: normalizedTokenAddress,
|
|
17836
|
+
totalLiquidity: parseSnapshotBigInt(
|
|
17837
|
+
group.sum.balance ?? "0",
|
|
17838
|
+
params.commitment,
|
|
17839
|
+
`liquidity group ${index} balance`
|
|
17840
|
+
),
|
|
17841
|
+
providerCount: parseProviderCount(
|
|
17842
|
+
group.distinctCount.providerId,
|
|
17843
|
+
params.commitment,
|
|
17844
|
+
`liquidity group ${index}`
|
|
17845
|
+
)
|
|
17846
|
+
};
|
|
17847
|
+
});
|
|
17848
|
+
const groupedTotal = liquidityByChain.reduce((sum, group) => sum + group.totalLiquidity, 0n);
|
|
17849
|
+
if (groupedTotal !== totalLiquidity) {
|
|
17850
|
+
throw new InvalidAvailableLiquiditySnapshotError(
|
|
17851
|
+
params.commitment,
|
|
17852
|
+
"grouped liquidity does not match the total liquidity"
|
|
17853
|
+
);
|
|
17854
|
+
}
|
|
17855
|
+
return { totalLiquidity, providerCount, liquidityByChain };
|
|
17856
|
+
}
|
|
17857
|
+
/** Formats a raw amount using the configured decimals for its chain/token. */
|
|
17858
|
+
formatLiquidity(amount, chain, tokenAddress, commitment) {
|
|
17859
|
+
const decimals = this.chainConfigService.getAssetMetadataByAddress(chain, tokenAddress)?.decimals;
|
|
17860
|
+
if (decimals === void 0) {
|
|
17861
|
+
throw new InvalidAvailableLiquiditySnapshotError(
|
|
17862
|
+
commitment,
|
|
17863
|
+
`token decimals are not configured for ${tokenAddress} on ${chain}`
|
|
17864
|
+
);
|
|
17865
|
+
}
|
|
17866
|
+
return viem.formatUnits(amount, decimals);
|
|
17867
|
+
}
|
|
17868
|
+
};
|
|
17869
|
+
var InvalidAvailableLiquiditySnapshotError = class extends Error {
|
|
17870
|
+
/** Creates an error that identifies the invalid snapshot and field/reason. */
|
|
17871
|
+
constructor(commitment, reason) {
|
|
17872
|
+
super(`Invalid available-liquidity snapshot ${commitment}: ${reason}`);
|
|
17873
|
+
this.name = "InvalidAvailableLiquiditySnapshotError";
|
|
17874
|
+
}
|
|
17875
|
+
};
|
|
17876
|
+
function parseSnapshotBigInt(value, commitment, field) {
|
|
17877
|
+
try {
|
|
17878
|
+
const amount = BigInt(value);
|
|
17879
|
+
if (amount < 0n) {
|
|
17880
|
+
throw new InvalidAvailableLiquiditySnapshotError(commitment, `${field} cannot be negative`);
|
|
17881
|
+
}
|
|
17882
|
+
return amount;
|
|
17883
|
+
} catch (error) {
|
|
17884
|
+
if (error instanceof InvalidAvailableLiquiditySnapshotError) throw error;
|
|
17885
|
+
throw new InvalidAvailableLiquiditySnapshotError(commitment, `${field} is not an integer`);
|
|
17886
|
+
}
|
|
17887
|
+
}
|
|
17888
|
+
function parseProviderCount(value, commitment, field) {
|
|
17889
|
+
const count = Number(value);
|
|
17890
|
+
if (!Number.isSafeInteger(count) || count < 0) {
|
|
17891
|
+
throw new InvalidAvailableLiquiditySnapshotError(commitment, `${field} provider count is invalid`);
|
|
17892
|
+
}
|
|
17893
|
+
return count;
|
|
17894
|
+
}
|
|
17895
|
+
function normalizeIndexedLiquidityAddress(address, commitment, field) {
|
|
17896
|
+
try {
|
|
17897
|
+
return normalizeEvmAddress(address, field);
|
|
17898
|
+
} catch {
|
|
17899
|
+
throw new InvalidAvailableLiquiditySnapshotError(commitment, `${field} is not a valid EVM address`);
|
|
17900
|
+
}
|
|
17901
|
+
}
|
|
17313
17902
|
|
|
17314
17903
|
// src/protocols/intents/quote/types.ts
|
|
17315
17904
|
var UnsupportedIntentQuoteStrategyError = class extends Error {
|
|
@@ -17321,15 +17910,67 @@ var UnsupportedIntentQuoteStrategyError = class extends Error {
|
|
|
17321
17910
|
var UnsupportedIntentQuotePairError = class extends Error {
|
|
17322
17911
|
constructor(params) {
|
|
17323
17912
|
super(
|
|
17324
|
-
`No Uniswap v4 pool config found for ${params.tokenIn
|
|
17913
|
+
`No ${params.quoteSource ?? "Uniswap v4 pool config"} found for ${params.tokenIn} -> ${params.tokenOut} on ${params.source} -> ${params.destination}`
|
|
17325
17914
|
);
|
|
17326
17915
|
this.name = "UnsupportedIntentQuotePairError";
|
|
17327
17916
|
}
|
|
17328
17917
|
};
|
|
17918
|
+
var PhantomSnapshotUnavailableError = class extends Error {
|
|
17919
|
+
constructor(tokenA, tokenB) {
|
|
17920
|
+
super(`No Phantom order price snapshot found for ${tokenA} -> ${tokenB}`);
|
|
17921
|
+
this.name = "PhantomSnapshotUnavailableError";
|
|
17922
|
+
}
|
|
17923
|
+
};
|
|
17924
|
+
var InvalidPhantomSnapshotError = class extends Error {
|
|
17925
|
+
constructor(commitment, reason) {
|
|
17926
|
+
super(`Invalid Phantom order price snapshot ${commitment}: ${reason}`);
|
|
17927
|
+
this.name = "InvalidPhantomSnapshotError";
|
|
17928
|
+
}
|
|
17929
|
+
};
|
|
17930
|
+
var BPS_DENOMINATOR = 10000n;
|
|
17931
|
+
function validateQuoteParams(params) {
|
|
17932
|
+
const hasAmountIn = params.amountIn !== void 0;
|
|
17933
|
+
const hasAmountOut = params.amountOut !== void 0;
|
|
17934
|
+
if (hasAmountIn === hasAmountOut) throw new Error("Provide exactly one of amountIn or amountOut");
|
|
17935
|
+
if (params.amountIn !== void 0 && params.amountIn <= 0n) throw new Error("amountIn must be greater than zero");
|
|
17936
|
+
if (params.amountOut !== void 0 && params.amountOut <= 0n) throw new Error("amountOut must be greater than zero");
|
|
17937
|
+
if (params.tokenIn.toLowerCase() === params.tokenOut.toLowerCase()) {
|
|
17938
|
+
throw new Error("tokenIn and tokenOut cannot be the same");
|
|
17939
|
+
}
|
|
17940
|
+
}
|
|
17941
|
+
async function readProtocolFeeBps(chainConfigService, source) {
|
|
17942
|
+
const gatewayAddress = chainConfigService.getIntentGatewayAddress(source.stateMachineId);
|
|
17943
|
+
if (!gatewayAddress || gatewayAddress === "0x" || gatewayAddress === viem.zeroAddress) {
|
|
17944
|
+
throw new Error(`IntentGatewayV2 is not configured for chain ${source.stateMachineId}`);
|
|
17945
|
+
}
|
|
17946
|
+
const gatewayParams = await source.client.readContract({
|
|
17947
|
+
address: gatewayAddress,
|
|
17948
|
+
abi: IntentGatewayV2_default.ABI,
|
|
17949
|
+
functionName: "params"
|
|
17950
|
+
});
|
|
17951
|
+
const protocolFeeBps = Array.isArray(gatewayParams) ? BigInt(gatewayParams[4]) : BigInt(gatewayParams.protocolFeeBps ?? 0);
|
|
17952
|
+
if (protocolFeeBps < 0n || protocolFeeBps >= BPS_DENOMINATOR) {
|
|
17953
|
+
throw new Error(`Invalid IntentGateway protocol fee: ${protocolFeeBps} bps`);
|
|
17954
|
+
}
|
|
17955
|
+
return protocolFeeBps;
|
|
17956
|
+
}
|
|
17957
|
+
function deductProtocolFee(amount, protocolFeeBps) {
|
|
17958
|
+
if (protocolFeeBps <= 0n) return amount;
|
|
17959
|
+
const fee = amount * protocolFeeBps / BPS_DENOMINATOR;
|
|
17960
|
+
return amount - fee;
|
|
17961
|
+
}
|
|
17962
|
+
function grossUpForProtocolFee(netAmount, protocolFeeBps) {
|
|
17963
|
+
if (protocolFeeBps <= 0n) return netAmount;
|
|
17964
|
+
if (protocolFeeBps >= BPS_DENOMINATOR) throw new Error("protocolFeeBps must be less than 10,000");
|
|
17965
|
+
return divCeil(netAmount * BPS_DENOMINATOR, BPS_DENOMINATOR - protocolFeeBps);
|
|
17966
|
+
}
|
|
17967
|
+
function divCeil(numerator, denominator) {
|
|
17968
|
+
if (denominator <= 0n) throw new Error("denominator must be greater than zero");
|
|
17969
|
+
return (numerator + denominator - 1n) / denominator;
|
|
17970
|
+
}
|
|
17329
17971
|
|
|
17330
17972
|
// src/protocols/intents/quote/uniswapV4.ts
|
|
17331
17973
|
var UNISWAP_INTENT_QUOTE_CHAIN = "EVM-8453" /* BASE_MAINNET */;
|
|
17332
|
-
var BPS_DENOMINATOR = 10000n;
|
|
17333
17974
|
var UniswapV4IntentQuoteStrategy = class {
|
|
17334
17975
|
constructor(chainConfigService) {
|
|
17335
17976
|
this.chainConfigService = chainConfigService;
|
|
@@ -17337,10 +17978,10 @@ var UniswapV4IntentQuoteStrategy = class {
|
|
|
17337
17978
|
chainConfigService;
|
|
17338
17979
|
baseQuoteClient;
|
|
17339
17980
|
async quote(params, source, destination) {
|
|
17340
|
-
|
|
17341
|
-
const protocolFeeBps = await
|
|
17981
|
+
validateQuoteParams(params);
|
|
17982
|
+
const protocolFeeBps = await readProtocolFeeBps(this.chainConfigService, source);
|
|
17342
17983
|
const quoteClient = this.resolveQuoteClient(source, destination);
|
|
17343
|
-
const poolConfig = this.resolvePoolConfig(params, source.stateMachineId,
|
|
17984
|
+
const poolConfig = this.resolvePoolConfig(params, source.stateMachineId, destination.stateMachineId);
|
|
17344
17985
|
return params.amountIn !== void 0 ? this.quoteExactInput({ params, client: quoteClient, protocolFeeBps, poolConfig }) : this.quoteExactOutput({ params, client: quoteClient, protocolFeeBps, poolConfig });
|
|
17345
17986
|
}
|
|
17346
17987
|
resolveQuoteClient(source, destination) {
|
|
@@ -17356,34 +17997,11 @@ var UniswapV4IntentQuoteStrategy = class {
|
|
|
17356
17997
|
this.baseQuoteClient = baseQuoteClient;
|
|
17357
17998
|
return baseQuoteClient;
|
|
17358
17999
|
}
|
|
17359
|
-
validateQuoteParams(params) {
|
|
17360
|
-
const hasAmountIn = params.amountIn !== void 0;
|
|
17361
|
-
const hasAmountOut = params.amountOut !== void 0;
|
|
17362
|
-
if (hasAmountIn === hasAmountOut) throw new Error("Provide exactly one of amountIn or amountOut");
|
|
17363
|
-
if (hasAmountIn && params.amountIn <= 0n) throw new Error("amountIn must be greater than zero");
|
|
17364
|
-
if (hasAmountOut && params.amountOut <= 0n) throw new Error("amountOut must be greater than zero");
|
|
17365
|
-
if (params.tokenIn.address.toLowerCase() === params.tokenOut.address.toLowerCase()) {
|
|
17366
|
-
throw new Error("tokenIn and tokenOut cannot be the same");
|
|
17367
|
-
}
|
|
17368
|
-
}
|
|
17369
|
-
async readProtocolFeeBps(client, chain) {
|
|
17370
|
-
const gatewayAddress = this.chainConfigService.getIntentGatewayAddress(chain);
|
|
17371
|
-
if (!gatewayAddress || gatewayAddress === "0x" || gatewayAddress === viem.zeroAddress) {
|
|
17372
|
-
throw new Error(`IntentGatewayV2 is not configured for chain ${chain}`);
|
|
17373
|
-
}
|
|
17374
|
-
const gatewayParams = await client.readContract({
|
|
17375
|
-
address: gatewayAddress,
|
|
17376
|
-
abi: IntentGatewayV2_default.ABI,
|
|
17377
|
-
functionName: "params"
|
|
17378
|
-
});
|
|
17379
|
-
if (isGatewayParamsTuple(gatewayParams)) return BigInt(gatewayParams[4]);
|
|
17380
|
-
return BigInt(gatewayParams.protocolFeeBps ?? 0);
|
|
17381
|
-
}
|
|
17382
18000
|
resolvePoolConfig(params, source, destination) {
|
|
17383
18001
|
const override = params.uniswapV4?.poolKey;
|
|
17384
18002
|
if (override) {
|
|
17385
18003
|
const poolKey = normalizePoolKey(override);
|
|
17386
|
-
const tokenInForQuote = viem.getAddress(override.currencyIn ?? params.tokenIn
|
|
18004
|
+
const tokenInForQuote = viem.getAddress(override.currencyIn ?? params.tokenIn);
|
|
17387
18005
|
if (tokenInForQuote !== poolKey.currency0 && tokenInForQuote !== poolKey.currency1) {
|
|
17388
18006
|
throw new Error(
|
|
17389
18007
|
`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.`
|
|
@@ -17391,11 +18009,11 @@ var UniswapV4IntentQuoteStrategy = class {
|
|
|
17391
18009
|
}
|
|
17392
18010
|
return {
|
|
17393
18011
|
poolKey,
|
|
17394
|
-
quoterAddress: this.resolveQuoterAddress(
|
|
18012
|
+
quoterAddress: this.resolveQuoterAddress(UNISWAP_INTENT_QUOTE_CHAIN, override.quoterAddress),
|
|
17395
18013
|
tokenInForQuote
|
|
17396
18014
|
};
|
|
17397
18015
|
}
|
|
17398
|
-
const poolConfig = this.resolveConfiguredPool(params, destination);
|
|
18016
|
+
const poolConfig = this.resolveConfiguredPool(params, source, destination, UNISWAP_INTENT_QUOTE_CHAIN);
|
|
17399
18017
|
if (poolConfig) return poolConfig;
|
|
17400
18018
|
throw new UnsupportedIntentQuotePairError({
|
|
17401
18019
|
source,
|
|
@@ -17404,12 +18022,12 @@ var UniswapV4IntentQuoteStrategy = class {
|
|
|
17404
18022
|
tokenOut: params.tokenOut
|
|
17405
18023
|
});
|
|
17406
18024
|
}
|
|
17407
|
-
resolveConfiguredPool(params,
|
|
17408
|
-
for (const pool of this.chainConfigService.getUniswapV4PoolConfigs(
|
|
17409
|
-
const resolvedPool = this.resolveConfiguredPoolTokens(
|
|
18025
|
+
resolveConfiguredPool(params, sourceChain, destinationChain, quoteChain) {
|
|
18026
|
+
for (const pool of this.chainConfigService.getUniswapV4PoolConfigs(quoteChain)) {
|
|
18027
|
+
const resolvedPool = this.resolveConfiguredPoolTokens(quoteChain, pool);
|
|
17410
18028
|
if (!resolvedPool) continue;
|
|
17411
|
-
const tokenInForQuote = matchPoolToken(params.tokenIn, resolvedPool);
|
|
17412
|
-
const tokenOutForQuote = matchPoolToken(params.tokenOut, resolvedPool);
|
|
18029
|
+
const tokenInForQuote = this.matchPoolToken(params.tokenIn, sourceChain, resolvedPool);
|
|
18030
|
+
const tokenOutForQuote = this.matchPoolToken(params.tokenOut, destinationChain, resolvedPool);
|
|
17413
18031
|
if (!tokenInForQuote || !tokenOutForQuote || tokenInForQuote.symbol === tokenOutForQuote.symbol) continue;
|
|
17414
18032
|
const { currency0, currency1 } = sortCurrencies(resolvedPool[0].address, resolvedPool[1].address);
|
|
17415
18033
|
return {
|
|
@@ -17420,7 +18038,7 @@ var UniswapV4IntentQuoteStrategy = class {
|
|
|
17420
18038
|
tickSpacing: pool.tickSpacing,
|
|
17421
18039
|
hooks: viem.getAddress(pool.hooks ?? viem.zeroAddress)
|
|
17422
18040
|
},
|
|
17423
|
-
quoterAddress: this.resolveQuoterAddress(
|
|
18041
|
+
quoterAddress: this.resolveQuoterAddress(quoteChain),
|
|
17424
18042
|
tokenInForQuote: tokenInForQuote.address
|
|
17425
18043
|
};
|
|
17426
18044
|
}
|
|
@@ -17443,8 +18061,18 @@ var UniswapV4IntentQuoteStrategy = class {
|
|
|
17443
18061
|
if (!address || address === "0x") return null;
|
|
17444
18062
|
return { symbol, address: viem.getAddress(address) };
|
|
17445
18063
|
}
|
|
18064
|
+
matchPoolToken(tokenAddress, orderChain, poolTokens) {
|
|
18065
|
+
const addressMatch = poolTokens.find(
|
|
18066
|
+
(poolToken) => poolToken.address.toLowerCase() === tokenAddress.toLowerCase()
|
|
18067
|
+
);
|
|
18068
|
+
if (addressMatch) return addressMatch;
|
|
18069
|
+
const metadata = this.chainConfigService.getAssetMetadataByAddress(orderChain, tokenAddress);
|
|
18070
|
+
if (!metadata) return null;
|
|
18071
|
+
return poolTokens.find((poolToken) => poolToken.symbol === metadata.symbol) ?? null;
|
|
18072
|
+
}
|
|
17446
18073
|
async quoteExactInput(args) {
|
|
17447
18074
|
const amountIn = args.params.amountIn;
|
|
18075
|
+
if (amountIn === void 0) throw new Error("amountIn is required for an exact-input quote");
|
|
17448
18076
|
const swapAmountIn = deductProtocolFee(amountIn, args.protocolFeeBps);
|
|
17449
18077
|
const amountOut = await this.readV4QuoteExactInput(args.client, args.poolConfig, swapAmountIn);
|
|
17450
18078
|
return {
|
|
@@ -17462,6 +18090,7 @@ var UniswapV4IntentQuoteStrategy = class {
|
|
|
17462
18090
|
}
|
|
17463
18091
|
async quoteExactOutput(args) {
|
|
17464
18092
|
const amountOut = args.params.amountOut;
|
|
18093
|
+
if (amountOut === void 0) throw new Error("amountOut is required for an exact-output quote");
|
|
17465
18094
|
const swapAmountIn = await this.readV4QuoteExactOutput(args.client, args.poolConfig, amountOut);
|
|
17466
18095
|
const amountIn = grossUpForProtocolFee(swapAmountIn, args.protocolFeeBps);
|
|
17467
18096
|
return {
|
|
@@ -17540,34 +18169,133 @@ function sortCurrencies(tokenIn, tokenOut) {
|
|
|
17540
18169
|
const output = viem.getAddress(tokenOut);
|
|
17541
18170
|
return BigInt(input) < BigInt(output) ? { currency0: input, currency1: output } : { currency0: output, currency1: input };
|
|
17542
18171
|
}
|
|
17543
|
-
function matchPoolToken(token, poolTokens) {
|
|
17544
|
-
const tokenAddress = token.address.toLowerCase();
|
|
17545
|
-
const addressMatch = poolTokens.find((poolToken) => poolToken.address.toLowerCase() === tokenAddress);
|
|
17546
|
-
if (addressMatch) return addressMatch;
|
|
17547
|
-
const tokenSymbol = token.symbol?.toUpperCase();
|
|
17548
|
-
if (!tokenSymbol) return null;
|
|
17549
|
-
return poolTokens.find((poolToken) => poolToken.symbol.toUpperCase() === tokenSymbol) ?? null;
|
|
17550
|
-
}
|
|
17551
18172
|
function getZeroForOne(tokenIn, poolKey) {
|
|
17552
18173
|
return viem.getAddress(tokenIn).toLowerCase() === viem.getAddress(poolKey.currency0).toLowerCase();
|
|
17553
18174
|
}
|
|
17554
|
-
|
|
17555
|
-
|
|
17556
|
-
|
|
17557
|
-
|
|
17558
|
-
|
|
17559
|
-
|
|
17560
|
-
|
|
17561
|
-
}
|
|
17562
|
-
|
|
17563
|
-
|
|
17564
|
-
|
|
18175
|
+
|
|
18176
|
+
// src/protocols/intents/quote/phantomSnapshot.ts
|
|
18177
|
+
var PHANTOM_INTENT_QUOTE_CHAIN = "EVM-8453" /* BASE_MAINNET */;
|
|
18178
|
+
var BASE_SNAPSHOT_ASSET_BY_ORDER_ASSET = {
|
|
18179
|
+
USDC: "USDC",
|
|
18180
|
+
USDT: "USDC",
|
|
18181
|
+
cNGN: "cNGN"
|
|
18182
|
+
};
|
|
18183
|
+
var SUPPORTED_BASE_SNAPSHOT_PAIRS = /* @__PURE__ */ new Set(["USDC:cNGN", "cNGN:USDC"]);
|
|
18184
|
+
var PhantomSnapshotIntentQuoteStrategy = class {
|
|
18185
|
+
constructor(chainConfigService, getQueryClient) {
|
|
18186
|
+
this.chainConfigService = chainConfigService;
|
|
18187
|
+
this.getQueryClient = getQueryClient;
|
|
18188
|
+
this.pairResolver = new PhantomSnapshotPairResolver(chainConfigService);
|
|
18189
|
+
}
|
|
18190
|
+
chainConfigService;
|
|
18191
|
+
getQueryClient;
|
|
18192
|
+
pairResolver;
|
|
18193
|
+
async quote(params, source, destination) {
|
|
18194
|
+
validateQuoteParams(params);
|
|
18195
|
+
const pair = this.pairResolver.resolve(params, source.stateMachineId, destination.stateMachineId);
|
|
18196
|
+
if (!pair) {
|
|
18197
|
+
throw new UnsupportedIntentQuotePairError({
|
|
18198
|
+
source: source.stateMachineId,
|
|
18199
|
+
destination: destination.stateMachineId,
|
|
18200
|
+
tokenIn: params.tokenIn,
|
|
18201
|
+
tokenOut: params.tokenOut,
|
|
18202
|
+
quoteSource: "Phantom snapshot pair"
|
|
18203
|
+
});
|
|
18204
|
+
}
|
|
18205
|
+
const queryClient = this.getQueryClient();
|
|
18206
|
+
const [protocolFeeBps, snapshot] = await Promise.all([
|
|
18207
|
+
readProtocolFeeBps(this.chainConfigService, source),
|
|
18208
|
+
_queryLatestPhantomOrderPriceSnapshot({
|
|
18209
|
+
tokenA: pair.tokenA,
|
|
18210
|
+
tokenB: pair.tokenB,
|
|
18211
|
+
queryClient
|
|
18212
|
+
})
|
|
18213
|
+
]);
|
|
18214
|
+
if (!snapshot) throw new PhantomSnapshotUnavailableError(pair.tokenA, pair.tokenB);
|
|
18215
|
+
this.validateSnapshot(snapshot);
|
|
18216
|
+
return this.quoteSnapshot(params, protocolFeeBps, snapshot);
|
|
18217
|
+
}
|
|
18218
|
+
quoteSnapshot(params, protocolFeeBps, snapshot) {
|
|
18219
|
+
if (params.amountIn !== void 0) {
|
|
18220
|
+
const netAmountIn2 = deductProtocolFee(params.amountIn, protocolFeeBps);
|
|
18221
|
+
const amountOut = netAmountIn2 * snapshot.medianPrice / snapshot.standardAmount;
|
|
18222
|
+
if (amountOut <= 0n) {
|
|
18223
|
+
throw new InvalidPhantomSnapshotError(snapshot.commitment, "quote rounds down to zero output");
|
|
18224
|
+
}
|
|
18225
|
+
return this.buildResult("EXACT_INPUT", params.amountIn, amountOut, protocolFeeBps, snapshot);
|
|
18226
|
+
}
|
|
18227
|
+
if (params.amountOut === void 0) throw new Error("Quote amount is missing after validation");
|
|
18228
|
+
const netAmountIn = divCeil(params.amountOut * snapshot.standardAmount, snapshot.medianPrice);
|
|
18229
|
+
const amountIn = grossUpForProtocolFee(netAmountIn, protocolFeeBps);
|
|
18230
|
+
return this.buildResult("EXACT_OUTPUT", amountIn, params.amountOut, protocolFeeBps, snapshot);
|
|
18231
|
+
}
|
|
18232
|
+
buildResult(tradeType, amountIn, amountOut, protocolFeeBps, snapshot) {
|
|
18233
|
+
return {
|
|
18234
|
+
strategy: "phantom_snapshot",
|
|
18235
|
+
tradeType,
|
|
18236
|
+
amountIn,
|
|
18237
|
+
amountOut,
|
|
18238
|
+
quoteMetadata: {
|
|
18239
|
+
quoteChain: PHANTOM_INTENT_QUOTE_CHAIN,
|
|
18240
|
+
commitment: snapshot.commitment,
|
|
18241
|
+
tokenA: snapshot.tokenA,
|
|
18242
|
+
tokenB: snapshot.tokenB,
|
|
18243
|
+
standardAmount: snapshot.standardAmount,
|
|
18244
|
+
medianPrice: snapshot.medianPrice,
|
|
18245
|
+
lowestPrice: snapshot.lowestPrice,
|
|
18246
|
+
highestPrice: snapshot.highestPrice,
|
|
18247
|
+
blockNumber: snapshot.blockNumber,
|
|
18248
|
+
snapshotTime: snapshot.snapshotTime,
|
|
18249
|
+
bidCount: snapshot.bidCount,
|
|
18250
|
+
protocolFeeBps
|
|
18251
|
+
}
|
|
18252
|
+
};
|
|
18253
|
+
}
|
|
18254
|
+
validateSnapshot(snapshot) {
|
|
18255
|
+
if (snapshot.standardAmount <= 0n) {
|
|
18256
|
+
throw new InvalidPhantomSnapshotError(snapshot.commitment, "standardAmount must be greater than zero");
|
|
18257
|
+
}
|
|
18258
|
+
if (snapshot.medianPrice <= 0n) {
|
|
18259
|
+
throw new InvalidPhantomSnapshotError(snapshot.commitment, "medianPrice must be greater than zero");
|
|
18260
|
+
}
|
|
18261
|
+
if (snapshot.bidCount <= 0) {
|
|
18262
|
+
throw new InvalidPhantomSnapshotError(snapshot.commitment, "bidCount must be greater than zero");
|
|
18263
|
+
}
|
|
18264
|
+
if (Number.isNaN(snapshot.snapshotTime.getTime())) {
|
|
18265
|
+
throw new InvalidPhantomSnapshotError(snapshot.commitment, "snapshotTime is invalid");
|
|
18266
|
+
}
|
|
18267
|
+
}
|
|
18268
|
+
};
|
|
18269
|
+
var PhantomSnapshotPairResolver = class {
|
|
18270
|
+
constructor(chainConfigService) {
|
|
18271
|
+
this.chainConfigService = chainConfigService;
|
|
18272
|
+
}
|
|
18273
|
+
chainConfigService;
|
|
18274
|
+
resolve(params, sourceStateMachineId, destinationStateMachineId) {
|
|
18275
|
+
const tokenIn = this.resolveBaseSnapshotToken(sourceStateMachineId, params.tokenIn);
|
|
18276
|
+
const tokenOut = this.resolveBaseSnapshotToken(destinationStateMachineId, params.tokenOut);
|
|
18277
|
+
if (!tokenIn || !tokenOut || !isSupportedSnapshotPair(tokenIn.symbol, tokenOut.symbol)) return;
|
|
18278
|
+
return { tokenA: tokenIn.address, tokenB: tokenOut.address };
|
|
18279
|
+
}
|
|
18280
|
+
resolveBaseSnapshotToken(chain, tokenAddress) {
|
|
18281
|
+
const orderAsset = this.chainConfigService.getAssetMetadataByAddress(chain, tokenAddress)?.symbol;
|
|
18282
|
+
if (!orderAsset) return;
|
|
18283
|
+
const snapshotAsset = BASE_SNAPSHOT_ASSET_BY_ORDER_ASSET[orderAsset];
|
|
18284
|
+
if (!snapshotAsset) return;
|
|
18285
|
+
const address = this.chainConfigService.getAssetAddress(PHANTOM_INTENT_QUOTE_CHAIN, snapshotAsset);
|
|
18286
|
+
if (!isConfiguredAddress(address)) return;
|
|
18287
|
+
return { symbol: snapshotAsset, address };
|
|
18288
|
+
}
|
|
18289
|
+
};
|
|
18290
|
+
function isSupportedSnapshotPair(tokenA, tokenB) {
|
|
18291
|
+
return SUPPORTED_BASE_SNAPSHOT_PAIRS.has(`${tokenA}:${tokenB}`);
|
|
17565
18292
|
}
|
|
17566
|
-
function
|
|
17567
|
-
return (
|
|
18293
|
+
function isConfiguredAddress(address) {
|
|
18294
|
+
return Boolean(address && address !== "0x" && !/^0x0{40}$/i.test(address));
|
|
17568
18295
|
}
|
|
17569
18296
|
|
|
17570
18297
|
// src/protocols/intents/IntentGateway.ts
|
|
18298
|
+
var CROSS_CHAIN_ORDER_FEE_GAS_BUMP = 600000n;
|
|
17571
18299
|
var IntentGateway = class _IntentGateway {
|
|
17572
18300
|
/** EVM chain on which orders are placed and escrowed. */
|
|
17573
18301
|
source;
|
|
@@ -17595,6 +18323,8 @@ var IntentGateway = class _IntentGateway {
|
|
|
17595
18323
|
gasEstimator;
|
|
17596
18324
|
/** Quote strategies for pricing orders before placement, keyed by strategy name. */
|
|
17597
18325
|
quoteStrategies;
|
|
18326
|
+
/** Resolves order tokens to canonical Phantom snapshot market pairs. */
|
|
18327
|
+
phantomSnapshotPairResolver;
|
|
17598
18328
|
/**
|
|
17599
18329
|
* Private constructor — use {@link IntentGateway.create} instead.
|
|
17600
18330
|
*
|
|
@@ -17638,7 +18368,12 @@ var IntentGateway = class _IntentGateway {
|
|
|
17638
18368
|
this.bidManager = bidManager;
|
|
17639
18369
|
this.gasEstimator = gasEstimator;
|
|
17640
18370
|
this._crypto = crypto;
|
|
18371
|
+
this.phantomSnapshotPairResolver = new PhantomSnapshotPairResolver(dest.configService);
|
|
17641
18372
|
this.quoteStrategies = {
|
|
18373
|
+
phantom_snapshot: new PhantomSnapshotIntentQuoteStrategy(
|
|
18374
|
+
dest.configService,
|
|
18375
|
+
() => this.requireIndexer().queryClient
|
|
18376
|
+
),
|
|
17642
18377
|
uniswap_v4: new UniswapV4IntentQuoteStrategy(dest.configService)
|
|
17643
18378
|
};
|
|
17644
18379
|
}
|
|
@@ -17688,37 +18423,69 @@ var IntentGateway = class _IntentGateway {
|
|
|
17688
18423
|
/**
|
|
17689
18424
|
* Quotes an intent between this gateway's source and destination chains.
|
|
17690
18425
|
*
|
|
17691
|
-
*
|
|
17692
|
-
*
|
|
18426
|
+
* Uses the latest directional Phantom order price snapshot from the attached
|
|
18427
|
+
* indexer by default. Pass `strategy: "uniswap_v4"` only when explicitly
|
|
18428
|
+
* requesting a Uniswap quote. Provide exactly one of `amountIn` or `amountOut`.
|
|
17693
18429
|
*
|
|
17694
|
-
*
|
|
17695
|
-
*
|
|
18430
|
+
* Both built-in strategies resolve their canonical market on Base,
|
|
18431
|
+
* regardless of this gateway's destination chain. Returned
|
|
17696
18432
|
* `amountIn`/`amountOut` already account for the gateway's protocol fee
|
|
17697
18433
|
* (`quoteMetadata.protocolFeeBps`), which the gateway deducts from order
|
|
17698
|
-
* inputs;
|
|
18434
|
+
* inputs; use the returned amounts directly when placing the order.
|
|
17699
18435
|
*
|
|
17700
18436
|
* @param params - Token pair, amount, and optional strategy/pool overrides.
|
|
17701
18437
|
* @returns The quoted amounts plus strategy-specific metadata.
|
|
17702
18438
|
* @throws {UnsupportedIntentQuoteStrategyError} For unknown strategies.
|
|
17703
|
-
* @throws {UnsupportedIntentQuotePairError} When
|
|
18439
|
+
* @throws {UnsupportedIntentQuotePairError} When the selected strategy does not support the pair.
|
|
18440
|
+
* @throws {PhantomSnapshotUnavailableError} When an eligible cNGN pair has no snapshot.
|
|
17704
18441
|
*/
|
|
17705
18442
|
async quoteIntent(params) {
|
|
17706
|
-
const
|
|
18443
|
+
const source = { stateMachineId: this.source.config.stateMachineId, client: this.source.client };
|
|
18444
|
+
const destination = { stateMachineId: this.dest.config.stateMachineId, client: this.dest.client };
|
|
18445
|
+
const strategy = params.strategy ?? "phantom_snapshot";
|
|
17707
18446
|
const handler = this.quoteStrategies[strategy];
|
|
17708
18447
|
if (!handler) throw new UnsupportedIntentQuoteStrategyError(strategy);
|
|
17709
|
-
return handler.quote(
|
|
17710
|
-
|
|
17711
|
-
|
|
17712
|
-
|
|
17713
|
-
|
|
18448
|
+
return handler.quote({ ...params, strategy }, source, destination);
|
|
18449
|
+
}
|
|
18450
|
+
/**
|
|
18451
|
+
* Returns the output-token liquidity measured in the latest directional
|
|
18452
|
+
* Phantom snapshot for this gateway's source and destination.
|
|
18453
|
+
*
|
|
18454
|
+
* Pair resolution uses the same canonical Base market as {@link quoteIntent}.
|
|
18455
|
+
* The snapshot itself determines the output token and chain to aggregate. The
|
|
18456
|
+
* amount is in the token's smallest unit and reflects the indexer's
|
|
18457
|
+
* `snapshotTime`; it is not a live reservation or fill guarantee.
|
|
18458
|
+
*
|
|
18459
|
+
* Requires a prior call to {@link withQueryClient}.
|
|
18460
|
+
*/
|
|
18461
|
+
async queryAvailableLiquidity(params) {
|
|
18462
|
+
const { queryClient } = this.requireIndexer();
|
|
18463
|
+
const sourceStateMachineId = this.source.config.stateMachineId;
|
|
18464
|
+
const destinationStateMachineId = this.dest.config.stateMachineId;
|
|
18465
|
+
const pair = this.phantomSnapshotPairResolver.resolve(params, sourceStateMachineId, destinationStateMachineId);
|
|
18466
|
+
if (!pair) {
|
|
18467
|
+
throw new UnsupportedIntentQuotePairError({
|
|
18468
|
+
source: sourceStateMachineId,
|
|
18469
|
+
destination: destinationStateMachineId,
|
|
18470
|
+
tokenIn: params.tokenIn,
|
|
18471
|
+
tokenOut: params.tokenOut,
|
|
18472
|
+
quoteSource: "Phantom snapshot pair"
|
|
18473
|
+
});
|
|
18474
|
+
}
|
|
18475
|
+
return new LiquidityEngine(queryClient, this.dest.configService).getAvailableLiquiditySnapshot({
|
|
18476
|
+
tokenIn: pair.tokenA,
|
|
18477
|
+
tokenOut: pair.tokenB
|
|
18478
|
+
});
|
|
17714
18479
|
}
|
|
17715
18480
|
/**
|
|
17716
18481
|
* Bidirectional async generator that orchestrates the full order lifecycle:
|
|
17717
18482
|
* placement, fee estimation, bid collection, and execution.
|
|
17718
18483
|
*
|
|
17719
18484
|
* **Yield/receive protocol:**
|
|
17720
|
-
* 1. If `order.fees` is unset or zero, estimates gas and sets
|
|
17721
|
-
*
|
|
18485
|
+
* 1. If `order.fees` is unset or zero, estimates gas on an internal copy and sets
|
|
18486
|
+
* same-chain fees to twice the estimate. Cross-chain orders retain a 1% buffer
|
|
18487
|
+
* and include an additional 600k-gas fee uplift, while the wei cost used for
|
|
18488
|
+
* the `value` field receives a 2% buffer.
|
|
17722
18489
|
* 2. Yields `AWAITING_PLACE_ORDER` with `{ to, data, value, sessionPrivateKey }`.
|
|
17723
18490
|
* The caller must sign the transaction and pass it back via `gen.next(signedTx)`.
|
|
17724
18491
|
* 3. Yields `ORDER_PLACED` with the finalised order and transaction hash once
|
|
@@ -17726,8 +18493,8 @@ var IntentGateway = class _IntentGateway {
|
|
|
17726
18493
|
* 4. Delegates to {@link OrderExecutor.executeOrder} and forwards all
|
|
17727
18494
|
* subsequent status updates until the order is filled, exhausted, or fails.
|
|
17728
18495
|
*
|
|
17729
|
-
* @param order - The order to place and execute. `order.fees`
|
|
17730
|
-
*
|
|
18496
|
+
* @param order - The order to place and execute. It is not mutated. `order.fees`
|
|
18497
|
+
* may be 0; fees are estimated automatically if so.
|
|
17731
18498
|
* @param graffiti - Optional bytes32 tag for orderflow attribution /
|
|
17732
18499
|
* revenue share. Defaults to {@link DEFAULT_GRAFFITI}.
|
|
17733
18500
|
* @param options - Optional tuning parameters:
|
|
@@ -17740,20 +18507,28 @@ var IntentGateway = class _IntentGateway {
|
|
|
17740
18507
|
* estimation returns zero.
|
|
17741
18508
|
*/
|
|
17742
18509
|
async *execute(order, graffiti = DEFAULT_GRAFFITI, options) {
|
|
18510
|
+
const executionOrder = { ...order };
|
|
17743
18511
|
let value;
|
|
17744
|
-
if (!
|
|
18512
|
+
if (!executionOrder.fees || executionOrder.fees === 0n) {
|
|
17745
18513
|
const estimate = await this.gasEstimator.estimateFillOrder({
|
|
17746
|
-
order,
|
|
18514
|
+
order: executionOrder,
|
|
17747
18515
|
maxPriorityFeePerGasBumpPercent: options?.maxPriorityFeePerGasBumpPercent,
|
|
17748
18516
|
maxFeePerGasBumpPercent: options?.maxFeePerGasBumpPercent
|
|
17749
18517
|
});
|
|
17750
18518
|
if (estimate.totalGasCostWei === 0n || estimate.totalGasInFeeToken === 0n) {
|
|
17751
18519
|
throw new Error("Gas estimation failed");
|
|
17752
18520
|
}
|
|
18521
|
+
const isSameChain = this.source.config.stateMachineId === this.dest.config.stateMachineId;
|
|
17753
18522
|
value = estimate.totalGasCostWei + estimate.totalGasCostWei * 2n / 100n;
|
|
17754
|
-
|
|
18523
|
+
const crossChainFeeBump = isSameChain ? 0n : await convertGasToFeeToken(
|
|
18524
|
+
this.ctx,
|
|
18525
|
+
CROSS_CHAIN_ORDER_FEE_GAS_BUMP,
|
|
18526
|
+
"source",
|
|
18527
|
+
this.source.config.stateMachineId
|
|
18528
|
+
);
|
|
18529
|
+
executionOrder.fees = isSameChain ? estimate.totalGasInFeeToken * 2n : estimate.totalGasInFeeToken + (crossChainFeeBump + estimate.totalGasInFeeToken * 1n / 100n);
|
|
17755
18530
|
}
|
|
17756
|
-
const placeOrderGen = this.orderPlacer.placeOrder(
|
|
18531
|
+
const placeOrderGen = this.orderPlacer.placeOrder(executionOrder, graffiti);
|
|
17757
18532
|
const placeOrderFirst = await placeOrderGen.next();
|
|
17758
18533
|
if (placeOrderFirst.done) {
|
|
17759
18534
|
throw new Error("placeOrder generator completed without yielding");
|
|
@@ -17864,13 +18639,20 @@ var IntentGateway = class _IntentGateway {
|
|
|
17864
18639
|
const gen = this.execute(order, graffiti, options);
|
|
17865
18640
|
try {
|
|
17866
18641
|
let input;
|
|
18642
|
+
let finalizedOrder;
|
|
17867
18643
|
while (true) {
|
|
17868
18644
|
const { value, done } = await gen.next(input);
|
|
17869
18645
|
input = void 0;
|
|
17870
18646
|
if (done) break;
|
|
17871
|
-
if (value.status === "
|
|
18647
|
+
if (value.status === "ORDER_PLACED") {
|
|
18648
|
+
finalizedOrder = value.order;
|
|
17872
18649
|
yield value;
|
|
17873
|
-
|
|
18650
|
+
} else if (value.status === "BIDS_RECEIVED") {
|
|
18651
|
+
if (!finalizedOrder) {
|
|
18652
|
+
throw new Error("Received bids before the order was finalized");
|
|
18653
|
+
}
|
|
18654
|
+
yield value;
|
|
18655
|
+
input = await this.autoSelect(finalizedOrder, value.bids);
|
|
17874
18656
|
} else if (value.status === "AWAITING_PLACE_ORDER") {
|
|
17875
18657
|
input = yield value;
|
|
17876
18658
|
} else {
|
|
@@ -18132,7 +18914,9 @@ var IntentGateway = class _IntentGateway {
|
|
|
18132
18914
|
}
|
|
18133
18915
|
requireIndexer() {
|
|
18134
18916
|
if (!this.indexer) {
|
|
18135
|
-
throw new Error(
|
|
18917
|
+
throw new Error(
|
|
18918
|
+
"IntentGateway: call withQueryClient(queryClient) before using indexer-backed methods or Phantom quotes"
|
|
18919
|
+
);
|
|
18136
18920
|
}
|
|
18137
18921
|
return this.indexer;
|
|
18138
18922
|
}
|
|
@@ -22667,6 +23451,7 @@ exports.IntentGateway = IntentGateway;
|
|
|
22667
23451
|
exports.IntentGatewayABI = ABI3;
|
|
22668
23452
|
exports.IntentOrderStatus = IntentOrderStatus;
|
|
22669
23453
|
exports.IntentsCoprocessor = IntentsCoprocessor;
|
|
23454
|
+
exports.InvalidPhantomSnapshotError = InvalidPhantomSnapshotError;
|
|
22670
23455
|
exports.IsmpClient = IsmpClient;
|
|
22671
23456
|
exports.MOCK_ADDRESS = MOCK_ADDRESS;
|
|
22672
23457
|
exports.ORDER_V2_PARAM_TYPE = ORDER_V2_PARAM_TYPE;
|
|
@@ -22674,6 +23459,7 @@ exports.OrderStatus = OrderStatus;
|
|
|
22674
23459
|
exports.OrderStatusChecker = OrderStatusChecker;
|
|
22675
23460
|
exports.PACKED_USEROP_TYPEHASH = PACKED_USEROP_TYPEHASH;
|
|
22676
23461
|
exports.PLACE_ORDER_SELECTOR = PLACE_ORDER_SELECTOR;
|
|
23462
|
+
exports.PhantomSnapshotUnavailableError = PhantomSnapshotUnavailableError;
|
|
22677
23463
|
exports.PharosChain = PharosChain;
|
|
22678
23464
|
exports.PolkadotHubChain = PolkadotHubChain;
|
|
22679
23465
|
exports.REQUEST_COMMITMENTS_SLOT = REQUEST_COMMITMENTS_SLOT;
|
|
@@ -22743,6 +23529,7 @@ exports.hyperbridgeAddress = hyperbridgeAddress;
|
|
|
22743
23529
|
exports.maxBigInt = maxBigInt;
|
|
22744
23530
|
exports.normalizeAddressForEvmBytes32 = normalizeAddressForEvmBytes32;
|
|
22745
23531
|
exports.normalizeAddressForStateMachine = normalizeAddressForStateMachine;
|
|
23532
|
+
exports.normalizeEvmAddress = normalizeEvmAddress;
|
|
22746
23533
|
exports.normalizeEvmChainId = normalizeEvmChainId;
|
|
22747
23534
|
exports.normalizeStateMachineId = normalizeStateMachineId;
|
|
22748
23535
|
exports.orderCommitment = orderCommitment;
|