@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/browser/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createConsola, LogLevels } from 'consola';
|
|
2
|
-
import { defineChain, keccak256, toHex, createPublicClient, http, hexToBytes, toFunctionSelector, bytesToHex, encodeFunctionData, erc20Abi, bytesToBigInt, pad, toBytes, numberToBytes, decodeAbiParameters, getAddress, encodeAbiParameters, isHex, maxUint256, parseAbiParameters, encodePacked, parseAbiItem, concat, decodeFunctionData, hexToString as hexToString$1, decodeEventLog, parseEventLogs, parseUnits, concatHex, zeroAddress, decodeFunctionResult, formatUnits } from 'viem';
|
|
2
|
+
import { defineChain, keccak256, toHex, createPublicClient, http, hexToBytes, toFunctionSelector, bytesToHex, encodeFunctionData, erc20Abi, bytesToBigInt, pad, toBytes, numberToBytes, decodeAbiParameters, getAddress, encodeAbiParameters, isHex, isAddress, maxUint256, parseAbiParameters, encodePacked, parseAbiItem, concat, decodeFunctionData, hexToString as hexToString$1, decodeEventLog, parseEventLogs, parseUnits, concatHex, zeroAddress, decodeFunctionResult, formatUnits } from 'viem';
|
|
3
3
|
import { baseSepolia, optimismSepolia, arbitrumSepolia, soneium, gnosis, optimism, polygonAmoy, polygon, base, arbitrum, bsc, mainnet, sepolia, gnosisChiado, bscTestnet, tron, unichain } from 'viem/chains';
|
|
4
4
|
import { TronWeb } from 'tronweb';
|
|
5
5
|
import { flatten, zip, capitalize, maxBy, isNil } from 'lodash-es';
|
|
@@ -2529,30 +2529,30 @@ var handlerV2_default = { ABI: ABI2 };
|
|
|
2529
2529
|
function tronAddress(base58) {
|
|
2530
2530
|
return `0x${TronWeb.address.toHex(base58).slice(2)}`;
|
|
2531
2531
|
}
|
|
2532
|
-
var Chains = /* @__PURE__ */ ((
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
return
|
|
2532
|
+
var Chains = /* @__PURE__ */ ((Chains2) => {
|
|
2533
|
+
Chains2["BSC_CHAPEL"] = "EVM-97";
|
|
2534
|
+
Chains2["GNOSIS_CHIADO"] = "EVM-10200";
|
|
2535
|
+
Chains2["HYPERBRIDGE_GARGANTUA"] = "KUSAMA-4009";
|
|
2536
|
+
Chains2["SEPOLIA"] = "EVM-11155111";
|
|
2537
|
+
Chains2["MAINNET"] = "EVM-1";
|
|
2538
|
+
Chains2["BSC_MAINNET"] = "EVM-56";
|
|
2539
|
+
Chains2["ARBITRUM_MAINNET"] = "EVM-42161";
|
|
2540
|
+
Chains2["ARBITRUM_SEPOLIA"] = "EVM-421614";
|
|
2541
|
+
Chains2["BASE_MAINNET"] = "EVM-8453";
|
|
2542
|
+
Chains2["BASE_SEPOLIA"] = "EVM-84532";
|
|
2543
|
+
Chains2["OPTIMISM_MAINNET"] = "EVM-10";
|
|
2544
|
+
Chains2["OPTIMISM_SEPOLIA"] = "EVM-11155420";
|
|
2545
|
+
Chains2["GNOSIS_MAINNET"] = "EVM-100";
|
|
2546
|
+
Chains2["SONEIUM_MAINNET"] = "EVM-1868";
|
|
2547
|
+
Chains2["POLYGON_MAINNET"] = "EVM-137";
|
|
2548
|
+
Chains2["POLKADOT_HUB_MAINNET"] = "EVM-420420419";
|
|
2549
|
+
Chains2["POLYGON_AMOY"] = "EVM-80002";
|
|
2550
|
+
Chains2["POLKADOT_ASSET_HUB_PASEO"] = "EVM-420420417";
|
|
2551
|
+
Chains2["TRON_MAINNET"] = "EVM-728126428";
|
|
2552
|
+
Chains2["TRON_NILE"] = "EVM-3448148188";
|
|
2553
|
+
Chains2["PHAROS_MAINNET"] = "EVM-688600";
|
|
2554
|
+
Chains2["PHAROS_ATLANTIC"] = "EVM-688689";
|
|
2555
|
+
return Chains2;
|
|
2556
2556
|
})(Chains || {});
|
|
2557
2557
|
var polkadotAssetHubPaseo = defineChain({
|
|
2558
2558
|
id: 420420417,
|
|
@@ -2743,7 +2743,7 @@ var chainConfigs = {
|
|
|
2743
2743
|
},
|
|
2744
2744
|
addresses: {
|
|
2745
2745
|
IntentGateway: "0xAe041F7B0CB581876832830baeB6a2Aa2a3C9716",
|
|
2746
|
-
SolverAccount: "
|
|
2746
|
+
SolverAccount: "0xfCd233b937D7622AAc63ced3C9A1A12F4a6B64E3",
|
|
2747
2747
|
TokenGateway: "0xFd413e3AFe560182C4471F4d143A96d3e259B6dE",
|
|
2748
2748
|
Host: "0x620128E2B19193d6Bd244a3AC8D3bBa0541B19c3",
|
|
2749
2749
|
UniswapRouter02: "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D",
|
|
@@ -2759,6 +2759,7 @@ var chainConfigs = {
|
|
|
2759
2759
|
Permit2: "0x000000000022D473030F116dDEE9F6B43aC78BA3",
|
|
2760
2760
|
EntryPointV08: "0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108",
|
|
2761
2761
|
CirclePaymaster: "0x0578cFB241215b77442a541325d6A4E6dFE700Ec",
|
|
2762
|
+
SimplexPaymaster: "0xD4340d7466e040626383cb9cda9307ba8E081149",
|
|
2762
2763
|
Usdt0Oft: "0x6C96dE32CEa08842dcc4058c14d3aaAD7Fa41dee"
|
|
2763
2764
|
},
|
|
2764
2765
|
rpcEnvKey: "ETH_MAINNET",
|
|
@@ -2798,7 +2799,7 @@ var chainConfigs = {
|
|
|
2798
2799
|
},
|
|
2799
2800
|
addresses: {
|
|
2800
2801
|
IntentGateway: "0xAe041F7B0CB581876832830baeB6a2Aa2a3C9716",
|
|
2801
|
-
SolverAccount: "
|
|
2802
|
+
SolverAccount: "0xfCd233b937D7622AAc63ced3C9A1A12F4a6B64E3",
|
|
2802
2803
|
TokenGateway: "0xFd413e3AFe560182C4471F4d143A96d3e259B6dE",
|
|
2803
2804
|
Host: "0x620128E2B19193d6Bd244a3AC8D3bBa0541B19c3",
|
|
2804
2805
|
UniswapRouter02: "0x10ED43C718714eb63d5aA57B78B54704E256024E",
|
|
@@ -2812,7 +2813,8 @@ var chainConfigs = {
|
|
|
2812
2813
|
UniswapV4StateView: "0xd13dd3d6e93f276fafc9db9e6bb47c1180aee0c4",
|
|
2813
2814
|
Calldispatcher: "0xc71251c8b3e7b02697a84363eef6dce8dfbdf333",
|
|
2814
2815
|
Permit2: "0x000000000022D473030F116dDEE9F6B43aC78BA3",
|
|
2815
|
-
EntryPointV08: "0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108"
|
|
2816
|
+
EntryPointV08: "0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108",
|
|
2817
|
+
SimplexPaymaster: "0xeD02f9f0df8F562B89cC5b25867Ad3C2d61252A9"
|
|
2816
2818
|
// "Usdt0Oft": Not available on BSC
|
|
2817
2819
|
},
|
|
2818
2820
|
rpcEnvKey: "BSC_MAINNET",
|
|
@@ -2854,7 +2856,7 @@ var chainConfigs = {
|
|
|
2854
2856
|
},
|
|
2855
2857
|
addresses: {
|
|
2856
2858
|
IntentGateway: "0xAe041F7B0CB581876832830baeB6a2Aa2a3C9716",
|
|
2857
|
-
SolverAccount: "
|
|
2859
|
+
SolverAccount: "0xfCd233b937D7622AAc63ced3C9A1A12F4a6B64E3",
|
|
2858
2860
|
TokenGateway: "0xFd413e3AFe560182C4471F4d143A96d3e259B6dE",
|
|
2859
2861
|
Host: "0x620128E2B19193d6Bd244a3AC8D3bBa0541B19c3",
|
|
2860
2862
|
UniswapRouter02: "0x4752ba5DBc23f44D87826276BF6Fd6b1C372aD24",
|
|
@@ -2870,6 +2872,7 @@ var chainConfigs = {
|
|
|
2870
2872
|
Permit2: "0x000000000022D473030F116dDEE9F6B43aC78BA3",
|
|
2871
2873
|
EntryPointV08: "0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108",
|
|
2872
2874
|
CirclePaymaster: "0x0578cFB241215b77442a541325d6A4E6dFE700Ec",
|
|
2875
|
+
SimplexPaymaster: "0x7281Bccb4f0BCE44F3B8542d1fC5e51c2F5fC08C",
|
|
2873
2876
|
Usdt0Oft: "0x14E4A1B13bf7F943c8ff7C51fb60FA964A298D92"
|
|
2874
2877
|
},
|
|
2875
2878
|
rpcEnvKey: "ARBITRUM_MAINNET",
|
|
@@ -2911,7 +2914,7 @@ var chainConfigs = {
|
|
|
2911
2914
|
},
|
|
2912
2915
|
addresses: {
|
|
2913
2916
|
IntentGateway: "0xAe041F7B0CB581876832830baeB6a2Aa2a3C9716",
|
|
2914
|
-
SolverAccount: "
|
|
2917
|
+
SolverAccount: "0xfCd233b937D7622AAc63ced3C9A1A12F4a6B64E3",
|
|
2915
2918
|
TokenGateway: "0xFd413e3AFe560182C4471F4d143A96d3e259B6dE",
|
|
2916
2919
|
Host: "0x620128E2B19193d6Bd244a3AC8D3bBa0541B19c3",
|
|
2917
2920
|
UniswapRouter02: "0x4752ba5DBc23f44D87826276BF6Fd6b1C372aD24",
|
|
@@ -2924,6 +2927,7 @@ var chainConfigs = {
|
|
|
2924
2927
|
Permit2: "0x000000000022D473030F116dDEE9F6B43aC78BA3",
|
|
2925
2928
|
EntryPointV08: "0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108",
|
|
2926
2929
|
CirclePaymaster: "0x0578cFB241215b77442a541325d6A4E6dFE700Ec",
|
|
2930
|
+
SimplexPaymaster: "0x15b3B03C870c7ef252029c35A12d3b339F5c8d7f",
|
|
2927
2931
|
AerodromeRouter: "0xcF77a3Ba9A5CA399B7c97c74d54e5b1Beb874E43",
|
|
2928
2932
|
UniswapV4PositionManager: "0x7c5f5a4bbd8fd63184577525326123b519429bdc",
|
|
2929
2933
|
UniswapV4PoolManager: "0x498581ff718922c3f8e6a244956af099b2652b2b",
|
|
@@ -2970,7 +2974,7 @@ var chainConfigs = {
|
|
|
2970
2974
|
},
|
|
2971
2975
|
addresses: {
|
|
2972
2976
|
IntentGateway: "0xAe041F7B0CB581876832830baeB6a2Aa2a3C9716",
|
|
2973
|
-
SolverAccount: "
|
|
2977
|
+
SolverAccount: "0xfCd233b937D7622AAc63ced3C9A1A12F4a6B64E3",
|
|
2974
2978
|
TokenGateway: "0x8b536105b6Fae2aE9199f5146D3C57Dfe53b614E",
|
|
2975
2979
|
Host: "0x620128E2B19193d6Bd244a3AC8D3bBa0541B19c3",
|
|
2976
2980
|
UniswapRouter02: "0xd2f9496824951D5237cC71245D659E48d0d5f9E8",
|
|
@@ -2986,6 +2990,7 @@ var chainConfigs = {
|
|
|
2986
2990
|
Permit2: "0x000000000022D473030F116dDEE9F6B43aC78BA3",
|
|
2987
2991
|
EntryPointV08: "0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108",
|
|
2988
2992
|
CirclePaymaster: "0x0578cFB241215b77442a541325d6A4E6dFE700Ec",
|
|
2993
|
+
SimplexPaymaster: "0xe99acFe0f5fC4C8ea54A187D8D3b05f136150095",
|
|
2989
2994
|
Usdt0Oft: "0x6BA10300f0DC58B7a1e4c0e41f5daBb7D7829e13"
|
|
2990
2995
|
},
|
|
2991
2996
|
rpcEnvKey: "POLYGON_MAINNET",
|
|
@@ -3081,7 +3086,7 @@ var chainConfigs = {
|
|
|
3081
3086
|
},
|
|
3082
3087
|
addresses: {
|
|
3083
3088
|
IntentGateway: "0xAe041F7B0CB581876832830baeB6a2Aa2a3C9716",
|
|
3084
|
-
SolverAccount: "
|
|
3089
|
+
SolverAccount: "0xfCd233b937D7622AAc63ced3C9A1A12F4a6B64E3",
|
|
3085
3090
|
TokenGateway: "0xFd413e3AFe560182C4471F4d143A96d3e259B6dE",
|
|
3086
3091
|
Host: "0x620128E2B19193d6Bd244a3AC8D3bBa0541B19c3",
|
|
3087
3092
|
UniswapRouter02: "0x4A7b5Da61326A6379179b40d00F57E5bbDC962c2",
|
|
@@ -3116,7 +3121,7 @@ var chainConfigs = {
|
|
|
3116
3121
|
},
|
|
3117
3122
|
addresses: {
|
|
3118
3123
|
IntentGateway: "0xAe041F7B0CB581876832830baeB6a2Aa2a3C9716",
|
|
3119
|
-
SolverAccount: "
|
|
3124
|
+
SolverAccount: "0xfCd233b937D7622AAc63ced3C9A1A12F4a6B64E3",
|
|
3120
3125
|
TokenGateway: "0xFd413e3AFe560182C4471F4d143A96d3e259B6dE",
|
|
3121
3126
|
Host: "0x620128E2B19193d6Bd244a3AC8D3bBa0541B19c3",
|
|
3122
3127
|
UniswapRouter02: "0xB2e26652e4BAd1e56055A051f922E06760cA0BFE",
|
|
@@ -3271,7 +3276,7 @@ var chainConfigs = {
|
|
|
3271
3276
|
},
|
|
3272
3277
|
addresses: {
|
|
3273
3278
|
IntentGateway: "0xAe041F7B0CB581876832830baeB6a2Aa2a3C9716",
|
|
3274
|
-
SolverAccount: "
|
|
3279
|
+
SolverAccount: "0xfCd233b937D7622AAc63ced3C9A1A12F4a6B64E3",
|
|
3275
3280
|
Host: "0x620128E2B19193d6Bd244a3AC8D3bBa0541B19c3",
|
|
3276
3281
|
Calldispatcher: "0xE2C7e576E26E0bE7aC97c6fE925bcDAbD87c4bEd"
|
|
3277
3282
|
},
|
|
@@ -5157,6 +5162,24 @@ var ChainConfigService = class {
|
|
|
5157
5162
|
getAssetAddress(chain, symbol) {
|
|
5158
5163
|
return this.getConfig(chain)?.assets?.[symbol];
|
|
5159
5164
|
}
|
|
5165
|
+
/**
|
|
5166
|
+
* Resolves configured token metadata from an address on a specific chain.
|
|
5167
|
+
* This is used by SDK helpers that accept token addresses rather than caller-
|
|
5168
|
+
* supplied symbols or decimals.
|
|
5169
|
+
*/
|
|
5170
|
+
getAssetMetadataByAddress(chain, address) {
|
|
5171
|
+
const config = this.getConfig(chain);
|
|
5172
|
+
if (!config?.assets) return;
|
|
5173
|
+
const normalizedAddress = address.toLowerCase();
|
|
5174
|
+
for (const [symbol, configuredAddress] of Object.entries(config.assets)) {
|
|
5175
|
+
if (configuredAddress.toLowerCase() !== normalizedAddress) continue;
|
|
5176
|
+
return {
|
|
5177
|
+
symbol,
|
|
5178
|
+
address: configuredAddress,
|
|
5179
|
+
decimals: config.tokenDecimals?.[symbol]
|
|
5180
|
+
};
|
|
5181
|
+
}
|
|
5182
|
+
}
|
|
5160
5183
|
getUsdtAsset(chain) {
|
|
5161
5184
|
return this.getConfig(chain)?.assets?.USDT ?? "0x";
|
|
5162
5185
|
}
|
|
@@ -5263,6 +5286,9 @@ var ChainConfigService = class {
|
|
|
5263
5286
|
getCirclePaymasterAddress(chain) {
|
|
5264
5287
|
return this.getConfig(chain)?.addresses.CirclePaymaster;
|
|
5265
5288
|
}
|
|
5289
|
+
getSimplexPaymasterAddress(chain) {
|
|
5290
|
+
return this.getConfig(chain)?.addresses.SimplexPaymaster;
|
|
5291
|
+
}
|
|
5266
5292
|
getHyperbridgeAddress() {
|
|
5267
5293
|
return hyperbridgeAddress;
|
|
5268
5294
|
}
|
|
@@ -7083,6 +7109,16 @@ var ExpectedError = class _ExpectedError extends Error {
|
|
|
7083
7109
|
return error instanceof _ExpectedError;
|
|
7084
7110
|
}
|
|
7085
7111
|
};
|
|
7112
|
+
var MISSING_CONSENSUS_UPDATE_TIME_MESSAGE = "Consensus update time not found";
|
|
7113
|
+
var MissingConsensusUpdateTimeError = class _MissingConsensusUpdateTimeError extends Error {
|
|
7114
|
+
constructor(message = MISSING_CONSENSUS_UPDATE_TIME_MESSAGE, options) {
|
|
7115
|
+
super(message, options);
|
|
7116
|
+
this.name = "Hyperbridge/SDK/MissingConsensusUpdateTimeError";
|
|
7117
|
+
}
|
|
7118
|
+
static isError(error) {
|
|
7119
|
+
return error instanceof _MissingConsensusUpdateTimeError || error instanceof Error && error.message.toLowerCase().includes(MISSING_CONSENSUS_UPDATE_TIME_MESSAGE.toLowerCase());
|
|
7120
|
+
}
|
|
7121
|
+
};
|
|
7086
7122
|
|
|
7087
7123
|
// src/configs/constants.ts
|
|
7088
7124
|
var ISMP_PREFIX = ":child_storage:default:ISMPv2";
|
|
@@ -7396,8 +7432,15 @@ var SubstrateChain = class _SubstrateChain {
|
|
|
7396
7432
|
id: stateMachineId,
|
|
7397
7433
|
height: Number(stateMachineHeight.height)
|
|
7398
7434
|
};
|
|
7399
|
-
|
|
7400
|
-
|
|
7435
|
+
try {
|
|
7436
|
+
const updateTime = await this.rpcClient.call("ismp_queryStateMachineUpdateTime", [payload]);
|
|
7437
|
+
return BigInt(updateTime);
|
|
7438
|
+
} catch (error) {
|
|
7439
|
+
if (MissingConsensusUpdateTimeError.isError(error)) {
|
|
7440
|
+
throw new MissingConsensusUpdateTimeError(MISSING_CONSENSUS_UPDATE_TIME_MESSAGE, { cause: error });
|
|
7441
|
+
}
|
|
7442
|
+
throw error;
|
|
7443
|
+
}
|
|
7401
7444
|
}
|
|
7402
7445
|
/**
|
|
7403
7446
|
* Get the challenge period for a given state machine id.
|
|
@@ -7830,7 +7873,7 @@ var IntentsCoprocessor = class _IntentsCoprocessor {
|
|
|
7830
7873
|
*/
|
|
7831
7874
|
async sendExtrinsicWithRetries(extrinsic, maxRetries, timeoutMs) {
|
|
7832
7875
|
const keyPair = this.getKeyPair();
|
|
7833
|
-
|
|
7876
|
+
const baseTip = 1000000000n;
|
|
7834
7877
|
let attempt = 0;
|
|
7835
7878
|
while (attempt < maxRetries) {
|
|
7836
7879
|
const currentTip = baseTip * BigInt(2 ** attempt);
|
|
@@ -8143,26 +8186,76 @@ var IntentsCoprocessor = class _IntentsCoprocessor {
|
|
|
8143
8186
|
};
|
|
8144
8187
|
}
|
|
8145
8188
|
/**
|
|
8146
|
-
*
|
|
8147
|
-
|
|
8148
|
-
|
|
8149
|
-
|
|
8150
|
-
|
|
8151
|
-
const
|
|
8152
|
-
|
|
8153
|
-
|
|
8154
|
-
|
|
8155
|
-
|
|
8156
|
-
|
|
8157
|
-
|
|
8158
|
-
|
|
8159
|
-
|
|
8160
|
-
|
|
8161
|
-
|
|
8162
|
-
|
|
8189
|
+
* Reads the PhantomOrderRegistered events emitted in a single block.
|
|
8190
|
+
*/
|
|
8191
|
+
async getPhantomOrdersInBlock(blockNumber) {
|
|
8192
|
+
const blockHash = await this.api.rpc.chain.getBlockHash(blockNumber);
|
|
8193
|
+
const apiAt = await this.api.at(blockHash);
|
|
8194
|
+
const records = await apiAt.query.system.events();
|
|
8195
|
+
const orders = [];
|
|
8196
|
+
for (const { event } of records) {
|
|
8197
|
+
if (event.section !== "intentsCoprocessor" || event.method !== "PhantomOrderRegistered") continue;
|
|
8198
|
+
const [commitment, chain, createdAt, tokenA, tokenB, standardAmount] = event.data;
|
|
8199
|
+
orders.push({
|
|
8200
|
+
commitment: commitment.toHex(),
|
|
8201
|
+
chain: new TextDecoder().decode(hexToU8a(chain.toHex())),
|
|
8202
|
+
createdAt: createdAt.toNumber(),
|
|
8203
|
+
tokenA: tokenA.toHex(),
|
|
8204
|
+
tokenB: tokenB.toHex(),
|
|
8205
|
+
standardAmount: BigInt(standardAmount.toString())
|
|
8206
|
+
});
|
|
8207
|
+
}
|
|
8208
|
+
return orders;
|
|
8209
|
+
}
|
|
8210
|
+
/**
|
|
8211
|
+
* Polls for newly registered phantom orders, invoking the callback once per order.
|
|
8212
|
+
*
|
|
8213
|
+
* Each tick reads the current head and scans every block between the last one processed and that
|
|
8214
|
+
* head, so the block cursor — not the connection — determines what has been seen. This replaced a
|
|
8215
|
+
* system.events subscription, which was only as reliable as its socket: polkadot-js reconnects
|
|
8216
|
+
* the transport but does not reliably re-establish storage subscriptions, and anything emitted
|
|
8217
|
+
* while disconnected was lost silently. With a bid window measured in a handful of blocks, that
|
|
8218
|
+
* meant silently missed bids.
|
|
8219
|
+
*
|
|
8220
|
+
* Scanning a block range is gap-free rather than merely self-healing: an outage delays orders but
|
|
8221
|
+
* cannot drop them, because the cursor only advances past a block whose events were actually
|
|
8222
|
+
* read. Recovery replays the backlog.
|
|
8223
|
+
*
|
|
8224
|
+
* Returns a function that stops polling.
|
|
8225
|
+
*/
|
|
8226
|
+
pollPhantomOrders(callback, options = {}) {
|
|
8227
|
+
const { intervalMs = 6e3, maxBlocksPerPoll = 500, lookbackBlocks = 0, onError } = options;
|
|
8228
|
+
let cursor = null;
|
|
8229
|
+
let inFlight = false;
|
|
8230
|
+
let stopped = false;
|
|
8231
|
+
const tick = async () => {
|
|
8232
|
+
if (inFlight || stopped) return;
|
|
8233
|
+
inFlight = true;
|
|
8234
|
+
try {
|
|
8235
|
+
const head = (await this.api.rpc.chain.getHeader()).number.toNumber();
|
|
8236
|
+
if (cursor === null) {
|
|
8237
|
+
cursor = Math.max(head - 1 - lookbackBlocks, -1);
|
|
8238
|
+
}
|
|
8239
|
+
if (head <= cursor) return;
|
|
8240
|
+
const to = Math.min(head, cursor + maxBlocksPerPoll);
|
|
8241
|
+
for (let blockNumber = cursor + 1; blockNumber <= to; blockNumber++) {
|
|
8242
|
+
if (stopped) return;
|
|
8243
|
+
const orders = await this.getPhantomOrdersInBlock(blockNumber);
|
|
8244
|
+
for (const order of orders) callback(order);
|
|
8245
|
+
cursor = blockNumber;
|
|
8246
|
+
}
|
|
8247
|
+
} catch (err) {
|
|
8248
|
+
onError?.(err);
|
|
8249
|
+
} finally {
|
|
8250
|
+
inFlight = false;
|
|
8163
8251
|
}
|
|
8164
|
-
}
|
|
8165
|
-
|
|
8252
|
+
};
|
|
8253
|
+
void tick();
|
|
8254
|
+
const timer = setInterval(() => void tick(), intervalMs);
|
|
8255
|
+
return () => {
|
|
8256
|
+
stopped = true;
|
|
8257
|
+
clearInterval(timer);
|
|
8258
|
+
};
|
|
8166
8259
|
}
|
|
8167
8260
|
};
|
|
8168
8261
|
var TronChain = class _TronChain {
|
|
@@ -9295,7 +9388,12 @@ function sleep(ms) {
|
|
|
9295
9388
|
async function waitForChallengePeriod(chain, stateMachineHeight) {
|
|
9296
9389
|
const challengePeriod = await chain.challengePeriod(stateMachineHeight.id);
|
|
9297
9390
|
if (challengePeriod === BigInt(0)) return;
|
|
9298
|
-
const updateTime = await chain.stateMachineUpdateTime(stateMachineHeight)
|
|
9391
|
+
const updateTime = await retryPromise(() => chain.stateMachineUpdateTime(stateMachineHeight), {
|
|
9392
|
+
maxRetries: 3,
|
|
9393
|
+
backoffMs: 500,
|
|
9394
|
+
logMessage: "Fetching consensus update time while waiting for the challenge period",
|
|
9395
|
+
shouldRetry: (error) => !MissingConsensusUpdateTimeError.isError(error)
|
|
9396
|
+
});
|
|
9299
9397
|
let currentTimestamp = await chain.timestamp();
|
|
9300
9398
|
let timeElapsed = currentTimestamp - updateTime;
|
|
9301
9399
|
if (timeElapsed > challengePeriod) return;
|
|
@@ -9442,6 +9540,10 @@ function normalizeAddressForEvmBytes32(address) {
|
|
|
9442
9540
|
if (address.length === 66) return address;
|
|
9443
9541
|
return bytes20ToBytes32(address);
|
|
9444
9542
|
}
|
|
9543
|
+
function normalizeEvmAddress(address, field = "address") {
|
|
9544
|
+
if (!isAddress(address)) throw new TypeError(`${field} must be a valid EVM address`);
|
|
9545
|
+
return address.toLowerCase();
|
|
9546
|
+
}
|
|
9445
9547
|
function normalizeAddressForStateMachine(address, stateMachineId) {
|
|
9446
9548
|
return isEvmChain(normalizeStateMachineId(stateMachineId)) ? normalizeAddressForEvmBytes32(address) : address;
|
|
9447
9549
|
}
|
|
@@ -9449,14 +9551,16 @@ var DEFAULT_LOGGER = createConsola({
|
|
|
9449
9551
|
level: LogLevels.silent
|
|
9450
9552
|
});
|
|
9451
9553
|
async function retryPromise(operation, retryConfig) {
|
|
9452
|
-
const { logger = DEFAULT_LOGGER, logMessage = "Retry operation failed" } = retryConfig;
|
|
9554
|
+
const { logger = DEFAULT_LOGGER, logMessage = "Retry operation failed", shouldRetry } = retryConfig;
|
|
9453
9555
|
let lastError;
|
|
9454
9556
|
for (let i = 0; i < retryConfig.maxRetries; i++) {
|
|
9455
9557
|
try {
|
|
9456
9558
|
return await operation();
|
|
9457
9559
|
} catch (error) {
|
|
9560
|
+
if (shouldRetry && !shouldRetry(error)) throw error;
|
|
9458
9561
|
logger.trace(`Retrying(${i}) > ${logMessage}`);
|
|
9459
9562
|
lastError = error;
|
|
9563
|
+
if (i === retryConfig.maxRetries - 1) break;
|
|
9460
9564
|
await new Promise((resolve) => setTimeout(resolve, retryConfig.backoffMs * 2 ** i));
|
|
9461
9565
|
}
|
|
9462
9566
|
}
|
|
@@ -11500,6 +11604,82 @@ query OrderStatus($commitment: String!) {
|
|
|
11500
11604
|
}
|
|
11501
11605
|
}
|
|
11502
11606
|
}`;
|
|
11607
|
+
var LATEST_PHANTOM_ORDER_PRICE_SNAPSHOT = `
|
|
11608
|
+
query LatestPhantomOrderPriceSnapshot($tokenA: String!, $tokenB: String!) {
|
|
11609
|
+
phantomOrderPriceSnapshots(
|
|
11610
|
+
filter: {
|
|
11611
|
+
and: [
|
|
11612
|
+
{ tokenA: { equalTo: $tokenA } }
|
|
11613
|
+
{ tokenB: { equalTo: $tokenB } }
|
|
11614
|
+
{ medianPrice: { isNull: false } }
|
|
11615
|
+
]
|
|
11616
|
+
}
|
|
11617
|
+
orderBy: BLOCK_NUMBER_DESC
|
|
11618
|
+
first: 1
|
|
11619
|
+
) {
|
|
11620
|
+
nodes {
|
|
11621
|
+
commitment
|
|
11622
|
+
tokenA
|
|
11623
|
+
tokenB
|
|
11624
|
+
standardAmount
|
|
11625
|
+
blockNumber
|
|
11626
|
+
medianPrice
|
|
11627
|
+
lowestPrice
|
|
11628
|
+
highestPrice
|
|
11629
|
+
bidCount
|
|
11630
|
+
snapshotTime
|
|
11631
|
+
}
|
|
11632
|
+
}
|
|
11633
|
+
}`;
|
|
11634
|
+
var LATEST_PHANTOM_ORDER_LIQUIDITY_SNAPSHOT = `
|
|
11635
|
+
query LatestPhantomOrderLiquiditySnapshot($tokenA: String!, $tokenB: String!) {
|
|
11636
|
+
phantomOrderPriceSnapshots(
|
|
11637
|
+
filter: {
|
|
11638
|
+
and: [
|
|
11639
|
+
{ tokenA: { equalTo: $tokenA } }
|
|
11640
|
+
{ tokenB: { equalTo: $tokenB } }
|
|
11641
|
+
]
|
|
11642
|
+
}
|
|
11643
|
+
orderBy: SNAPSHOT_TIME_DESC
|
|
11644
|
+
first: 1
|
|
11645
|
+
) {
|
|
11646
|
+
nodes {
|
|
11647
|
+
commitment
|
|
11648
|
+
tokenA
|
|
11649
|
+
tokenB
|
|
11650
|
+
snapshotTime
|
|
11651
|
+
}
|
|
11652
|
+
}
|
|
11653
|
+
}`;
|
|
11654
|
+
var LIQUIDITY_PROVIDER_BALANCES = `
|
|
11655
|
+
query LiquidityProviderBalanceAggregates($commitment: String!, $tokenAddress: String!) {
|
|
11656
|
+
liquidityProviderBalances(
|
|
11657
|
+
filter: {
|
|
11658
|
+
and: [
|
|
11659
|
+
{ commitment: { equalTo: $commitment } }
|
|
11660
|
+
{ tokenAddress: { equalTo: $tokenAddress } }
|
|
11661
|
+
]
|
|
11662
|
+
}
|
|
11663
|
+
) {
|
|
11664
|
+
aggregates {
|
|
11665
|
+
sum {
|
|
11666
|
+
balance
|
|
11667
|
+
}
|
|
11668
|
+
distinctCount {
|
|
11669
|
+
providerId
|
|
11670
|
+
}
|
|
11671
|
+
}
|
|
11672
|
+
groupedAggregates(groupBy: [CHAIN, TOKEN_ADDRESS]) {
|
|
11673
|
+
keys
|
|
11674
|
+
sum {
|
|
11675
|
+
balance
|
|
11676
|
+
}
|
|
11677
|
+
distinctCount {
|
|
11678
|
+
providerId
|
|
11679
|
+
}
|
|
11680
|
+
}
|
|
11681
|
+
}
|
|
11682
|
+
}`;
|
|
11503
11683
|
var TOKEN_GATEWAY_ASSET_TELEPORTED_STATUS = `
|
|
11504
11684
|
query TokenGatewayAssetTeleportedStatus($commitment: String!) {
|
|
11505
11685
|
tokenGatewayAssetTeleportedV2s(
|
|
@@ -11561,6 +11741,29 @@ async function queryAssetTeleported(params) {
|
|
|
11561
11741
|
function queryGetRequest(params) {
|
|
11562
11742
|
return _queryGetRequestInternal(params);
|
|
11563
11743
|
}
|
|
11744
|
+
async function _queryLatestPhantomOrderPriceSnapshot(params) {
|
|
11745
|
+
const response = await params.queryClient.request(
|
|
11746
|
+
LATEST_PHANTOM_ORDER_PRICE_SNAPSHOT,
|
|
11747
|
+
{
|
|
11748
|
+
tokenA: params.tokenA.toLowerCase(),
|
|
11749
|
+
tokenB: params.tokenB.toLowerCase()
|
|
11750
|
+
}
|
|
11751
|
+
);
|
|
11752
|
+
const snapshot = response.phantomOrderPriceSnapshots.nodes[0];
|
|
11753
|
+
if (!snapshot?.medianPrice) return;
|
|
11754
|
+
return {
|
|
11755
|
+
commitment: snapshot.commitment,
|
|
11756
|
+
tokenA: snapshot.tokenA,
|
|
11757
|
+
tokenB: snapshot.tokenB,
|
|
11758
|
+
standardAmount: BigInt(snapshot.standardAmount),
|
|
11759
|
+
blockNumber: BigInt(snapshot.blockNumber),
|
|
11760
|
+
medianPrice: BigInt(snapshot.medianPrice),
|
|
11761
|
+
lowestPrice: snapshot.lowestPrice === null ? void 0 : BigInt(snapshot.lowestPrice),
|
|
11762
|
+
highestPrice: snapshot.highestPrice === null ? void 0 : BigInt(snapshot.highestPrice),
|
|
11763
|
+
bidCount: snapshot.bidCount,
|
|
11764
|
+
snapshotTime: new Date(snapshot.snapshotTime)
|
|
11765
|
+
};
|
|
11766
|
+
}
|
|
11564
11767
|
async function _queryTokenGatewayAssetTeleportedInternal(params) {
|
|
11565
11768
|
const { commitmentHash, queryClient: client, logger = DEFAULT_LOGGER } = params;
|
|
11566
11769
|
const response = await retryPromise(
|
|
@@ -12071,6 +12274,7 @@ function createCancellationStorage(options = {}) {
|
|
|
12071
12274
|
const decoded = decodeIProof(value);
|
|
12072
12275
|
return decoded;
|
|
12073
12276
|
}
|
|
12277
|
+
if (key2.includes("postCommitment")) return value;
|
|
12074
12278
|
throw new Error(`Unknown storage key type: ${key2}`);
|
|
12075
12279
|
};
|
|
12076
12280
|
const setItem = async (key2, value) => {
|
|
@@ -12084,6 +12288,10 @@ function createCancellationStorage(options = {}) {
|
|
|
12084
12288
|
await baseStorage.setItem(key2, encoded);
|
|
12085
12289
|
return;
|
|
12086
12290
|
}
|
|
12291
|
+
if (key2.includes("postCommitment") && typeof value === "string") {
|
|
12292
|
+
await baseStorage.setItem(key2, value);
|
|
12293
|
+
return;
|
|
12294
|
+
}
|
|
12087
12295
|
throw new Error(`Unknown storage key type: ${key2}`);
|
|
12088
12296
|
};
|
|
12089
12297
|
const removeItem = async (key2) => {
|
|
@@ -12097,11 +12305,25 @@ function createCancellationStorage(options = {}) {
|
|
|
12097
12305
|
});
|
|
12098
12306
|
}
|
|
12099
12307
|
var STORAGE_KEYS = Object.freeze({
|
|
12100
|
-
destProof: (orderId) => `cancel-order:${orderId}:destProof`,
|
|
12101
|
-
getRequest: (orderId) => `cancel-order:${orderId}:getRequest`,
|
|
12102
|
-
sourceProof: (orderId) => `cancel-order:${orderId}:sourceProof`,
|
|
12103
|
-
postCommitment: (orderId) => `cancel-order:${orderId}:postCommitment`
|
|
12308
|
+
destProof: (orderId, source, destination) => `cancel-order:${cancellationScope(orderId, source, destination)}:destProof`,
|
|
12309
|
+
getRequest: (orderId, source, destination) => `cancel-order:${cancellationScope(orderId, source, destination)}:getRequest`,
|
|
12310
|
+
sourceProof: (orderId, source, destination) => `cancel-order:${cancellationScope(orderId, source, destination)}:sourceProof`,
|
|
12311
|
+
postCommitment: (orderId, source, destination) => `cancel-order:${cancellationScope(orderId, source, destination)}:postCommitment`
|
|
12104
12312
|
});
|
|
12313
|
+
var LEGACY_STORAGE_KEYS = Object.freeze({
|
|
12314
|
+
destProof: (orderId, source, destination) => `cancel-order:${legacyCancellationScope(orderId, source, destination)}:destProof`,
|
|
12315
|
+
getRequest: (orderId, source, destination) => `cancel-order:${legacyCancellationScope(orderId, source, destination)}:getRequest`,
|
|
12316
|
+
sourceProof: (orderId, source, destination) => `cancel-order:${legacyCancellationScope(orderId, source, destination)}:sourceProof`,
|
|
12317
|
+
postCommitment: (orderId, source, destination) => `cancel-order:${legacyCancellationScope(orderId, source, destination)}:postCommitment`
|
|
12318
|
+
});
|
|
12319
|
+
function cancellationScope(orderId, source, destination) {
|
|
12320
|
+
if (!source || !destination) return orderId;
|
|
12321
|
+
return `${orderId}:${encodeURIComponent(normalizeStateMachineId(source))}:${encodeURIComponent(normalizeStateMachineId(destination))}`;
|
|
12322
|
+
}
|
|
12323
|
+
function legacyCancellationScope(orderId, source, destination) {
|
|
12324
|
+
if (!source || !destination) return orderId;
|
|
12325
|
+
return `${orderId}:${encodeURIComponent(source)}:${encodeURIComponent(destination)}`;
|
|
12326
|
+
}
|
|
12105
12327
|
function createUsedUserOpsStorage(options = {}) {
|
|
12106
12328
|
const key = options.env ?? detectEnvironment();
|
|
12107
12329
|
const driver = loadDriver({ key}) ?? inMemoryDriver();
|
|
@@ -15267,6 +15489,29 @@ async function convertFeeTokenToWei(ctx, feeTokenAmount, feeTokenIn, evmChainID)
|
|
|
15267
15489
|
}
|
|
15268
15490
|
|
|
15269
15491
|
// src/protocols/intents/OrderPlacer.ts
|
|
15492
|
+
function deriveCanonicalPlacedOrder(order, args) {
|
|
15493
|
+
const canonicalOrder = {
|
|
15494
|
+
...order,
|
|
15495
|
+
user: args.user,
|
|
15496
|
+
source: args.source,
|
|
15497
|
+
destination: args.destination,
|
|
15498
|
+
deadline: args.deadline,
|
|
15499
|
+
nonce: args.nonce,
|
|
15500
|
+
fees: args.fees,
|
|
15501
|
+
session: args.session,
|
|
15502
|
+
predispatch: {
|
|
15503
|
+
assets: args.predispatch.map((asset) => ({ ...asset })),
|
|
15504
|
+
call: order.predispatch.call
|
|
15505
|
+
},
|
|
15506
|
+
inputs: args.inputs.map((asset) => ({ ...asset })),
|
|
15507
|
+
output: {
|
|
15508
|
+
beneficiary: args.beneficiary,
|
|
15509
|
+
assets: args.outputs.map((asset) => ({ ...asset })),
|
|
15510
|
+
call: order.output.call
|
|
15511
|
+
}
|
|
15512
|
+
};
|
|
15513
|
+
return { ...canonicalOrder, id: orderCommitment(canonicalOrder) };
|
|
15514
|
+
}
|
|
15270
15515
|
var OrderPlacer = class {
|
|
15271
15516
|
/**
|
|
15272
15517
|
* @param ctx - Shared IntentsV2 context providing the source chain client,
|
|
@@ -15283,17 +15528,16 @@ var OrderPlacer = class {
|
|
|
15283
15528
|
* 1. Yields `{ to, data, sessionPrivateKey }` — the caller must sign a
|
|
15284
15529
|
* transaction sending `data` to `to` and pass the signed transaction back
|
|
15285
15530
|
* via `gen.next(signedTx)`.
|
|
15286
|
-
* 2. Returns `{ order, transactionHash }` — the finalized order
|
|
15287
|
-
*
|
|
15288
|
-
* transaction hash.
|
|
15531
|
+
* 2. Returns `{ order, transactionHash }` — the finalized order rebuilt from
|
|
15532
|
+
* the canonical `OrderPlaced` fields with its computed `id`, plus the
|
|
15533
|
+
* placement transaction hash.
|
|
15289
15534
|
*
|
|
15290
15535
|
* A fresh ephemeral session key is generated for every call. The key is
|
|
15291
15536
|
* stored immediately (without a commitment) so it can be retrieved by
|
|
15292
15537
|
* address, then updated with the commitment once the `OrderPlaced` event
|
|
15293
|
-
* confirms the
|
|
15538
|
+
* confirms the canonical order.
|
|
15294
15539
|
*
|
|
15295
|
-
* @param order - The order to place.
|
|
15296
|
-
* with the generated session key address before yielding.
|
|
15540
|
+
* @param order - The order to place. It is not mutated.
|
|
15297
15541
|
* @param graffiti - Optional bytes32 tag for orderflow attribution /
|
|
15298
15542
|
* revenue share. Defaults to {@link DEFAULT_GRAFFITI} (bytes32 zero).
|
|
15299
15543
|
* @yields `{ to, data, sessionPrivateKey }` — target contract address,
|
|
@@ -15308,7 +15552,7 @@ var OrderPlacer = class {
|
|
|
15308
15552
|
const account = privateKeyToAccount(privateKey);
|
|
15309
15553
|
const sessionKeyAddress = account.address;
|
|
15310
15554
|
const createdAt = Date.now();
|
|
15311
|
-
order
|
|
15555
|
+
const placementOrder = { ...order, session: sessionKeyAddress };
|
|
15312
15556
|
await this.ctx.sessionKeyStorage.setSessionKeyByAddress(sessionKeyAddress, {
|
|
15313
15557
|
privateKey,
|
|
15314
15558
|
address: sessionKeyAddress,
|
|
@@ -15317,7 +15561,7 @@ var OrderPlacer = class {
|
|
|
15317
15561
|
const data = encodeFunctionData({
|
|
15318
15562
|
abi: ABI3,
|
|
15319
15563
|
functionName: "placeOrder",
|
|
15320
|
-
args: [transformOrderForContract(
|
|
15564
|
+
args: [transformOrderForContract(placementOrder), graffiti]
|
|
15321
15565
|
});
|
|
15322
15566
|
const intentGatewayAddress = this.ctx.source.configService.getIntentGatewayAddress(
|
|
15323
15567
|
normalizeStateMachineId(order.source)
|
|
@@ -15337,20 +15581,15 @@ var OrderPlacer = class {
|
|
|
15337
15581
|
if (!orderPlacedEvent) {
|
|
15338
15582
|
throw new Error("OrderPlaced event not found in transaction receipt");
|
|
15339
15583
|
}
|
|
15340
|
-
|
|
15341
|
-
order.inputs = orderPlacedEvent.args.inputs.map((input) => ({
|
|
15342
|
-
token: input.token,
|
|
15343
|
-
amount: input.amount
|
|
15344
|
-
}));
|
|
15345
|
-
order.id = orderCommitment(order);
|
|
15584
|
+
const finalizedOrder = deriveCanonicalPlacedOrder(placementOrder, orderPlacedEvent.args);
|
|
15346
15585
|
const sessionKeyData = {
|
|
15347
15586
|
privateKey,
|
|
15348
15587
|
address: sessionKeyAddress,
|
|
15349
|
-
commitment:
|
|
15588
|
+
commitment: finalizedOrder.id,
|
|
15350
15589
|
createdAt
|
|
15351
15590
|
};
|
|
15352
15591
|
await this.ctx.sessionKeyStorage.setSessionKeyByAddress(sessionKeyAddress, sessionKeyData);
|
|
15353
|
-
return { order, receipt };
|
|
15592
|
+
return { order: finalizedOrder, receipt };
|
|
15354
15593
|
}
|
|
15355
15594
|
};
|
|
15356
15595
|
|
|
@@ -15680,7 +15919,7 @@ var OrderExecutor = class {
|
|
|
15680
15919
|
}
|
|
15681
15920
|
}
|
|
15682
15921
|
};
|
|
15683
|
-
var OrderCanceller = class {
|
|
15922
|
+
var OrderCanceller = class _OrderCanceller {
|
|
15684
15923
|
/**
|
|
15685
15924
|
* @param ctx - Shared IntentsV2 context providing the source and destination
|
|
15686
15925
|
* chain clients, config service, and cancellation storage.
|
|
@@ -15689,6 +15928,9 @@ var OrderCanceller = class {
|
|
|
15689
15928
|
this.ctx = ctx;
|
|
15690
15929
|
}
|
|
15691
15930
|
ctx;
|
|
15931
|
+
static DEFAULT_MAX_RECOVERY_RESTARTS = 1;
|
|
15932
|
+
static PROOF_FRESHNESS_MAX_RETRIES = 3;
|
|
15933
|
+
static PROOF_FRESHNESS_BACKOFF_MS = 500;
|
|
15692
15934
|
logger = createConsola({
|
|
15693
15935
|
level: LogLevels.info,
|
|
15694
15936
|
formatOptions: { columns: 80, colors: true, compact: true, date: false }
|
|
@@ -15720,11 +15962,14 @@ var OrderCanceller = class {
|
|
|
15720
15962
|
* @returns The native token dispatch fee in wei.
|
|
15721
15963
|
*/
|
|
15722
15964
|
async quoteCancelFromSource(order) {
|
|
15723
|
-
if (order.source === order.destination) return { nativeValue: 0n, relayerFee: 0n };
|
|
15724
15965
|
const sourceStateMachine = normalizeStateMachineId(order.source);
|
|
15966
|
+
const destStateMachine = normalizeStateMachineId(order.destination);
|
|
15967
|
+
if (sourceStateMachine === destStateMachine) {
|
|
15968
|
+
return { nativeValue: 0n, relayerFee: 0n };
|
|
15969
|
+
}
|
|
15725
15970
|
const height = order.deadline + 1n;
|
|
15726
15971
|
const destIntentGateway = this.ctx.dest.configService.getIntentGatewayAddress(
|
|
15727
|
-
|
|
15972
|
+
destStateMachine
|
|
15728
15973
|
);
|
|
15729
15974
|
const slotHash = await this.ctx.dest.client.readContract({
|
|
15730
15975
|
abi: ABI3,
|
|
@@ -15736,8 +15981,8 @@ var OrderCanceller = class {
|
|
|
15736
15981
|
const context = encodeWithdrawalRequest(order, order.user);
|
|
15737
15982
|
const getRequest = {
|
|
15738
15983
|
source: sourceStateMachine,
|
|
15739
|
-
dest:
|
|
15740
|
-
from: this.ctx.source.configService.getIntentGatewayAddress(
|
|
15984
|
+
dest: destStateMachine,
|
|
15985
|
+
from: this.ctx.source.configService.getIntentGatewayAddress(destStateMachine),
|
|
15741
15986
|
nonce: await this.ctx.source.getHostNonce(),
|
|
15742
15987
|
height,
|
|
15743
15988
|
keys: [key],
|
|
@@ -15754,7 +15999,9 @@ var OrderCanceller = class {
|
|
|
15754
15999
|
* cancellation is complete.
|
|
15755
16000
|
*
|
|
15756
16001
|
* Delegates to `cancelOrderFromSource` or `cancelOrderFromDest` based on
|
|
15757
|
-
* the `from` parameter.
|
|
16002
|
+
* the `from` parameter. If Hyperbridge has pruned consensus data needed for
|
|
16003
|
+
* source-side GET recovery, clears its stale checkpoint and restarts the
|
|
16004
|
+
* source-side stream internally.
|
|
15758
16005
|
*
|
|
15759
16006
|
* @param order - The order to cancel.
|
|
15760
16007
|
* @param indexerClient - Indexer client used to stream ISMP request status
|
|
@@ -15764,12 +16011,32 @@ var OrderCanceller = class {
|
|
|
15764
16011
|
* cancellation lifecycle.
|
|
15765
16012
|
*/
|
|
15766
16013
|
async *cancelOrder(order, indexerClient, options = {}) {
|
|
15767
|
-
const
|
|
16014
|
+
const sourceStateMachine = normalizeStateMachineId(order.source);
|
|
16015
|
+
const destStateMachine = normalizeStateMachineId(order.destination);
|
|
16016
|
+
const isSameChain = sourceStateMachine === destStateMachine;
|
|
15768
16017
|
if (options.from === "destination" && !isSameChain) {
|
|
15769
16018
|
yield* this.cancelOrderFromDest(order, indexerClient);
|
|
15770
16019
|
return;
|
|
15771
16020
|
}
|
|
15772
|
-
|
|
16021
|
+
let recoveryRestarts = 0;
|
|
16022
|
+
while (true) {
|
|
16023
|
+
try {
|
|
16024
|
+
yield* this.cancelOrderFromSource(order, indexerClient);
|
|
16025
|
+
return;
|
|
16026
|
+
} catch (error) {
|
|
16027
|
+
if (!MissingConsensusUpdateTimeError.isError(error)) throw error;
|
|
16028
|
+
if (recoveryRestarts >= _OrderCanceller.DEFAULT_MAX_RECOVERY_RESTARTS) {
|
|
16029
|
+
throw new Error(
|
|
16030
|
+
`Cancellation recovery stopped after ${recoveryRestarts} restart(s): Hyperbridge no longer retains a required consensus update.`
|
|
16031
|
+
);
|
|
16032
|
+
}
|
|
16033
|
+
recoveryRestarts += 1;
|
|
16034
|
+
this.logger.warn(
|
|
16035
|
+
`Restarting cancellation recovery (${recoveryRestarts}/${_OrderCanceller.DEFAULT_MAX_RECOVERY_RESTARTS}) after a required consensus update was pruned`
|
|
16036
|
+
);
|
|
16037
|
+
await this.clearGetRecoveryCache(order);
|
|
16038
|
+
}
|
|
16039
|
+
}
|
|
15773
16040
|
}
|
|
15774
16041
|
/**
|
|
15775
16042
|
* Async generator that cancels an order by initiating the cancel from the
|
|
@@ -15795,11 +16062,10 @@ var OrderCanceller = class {
|
|
|
15795
16062
|
* @throws If the cancel transaction does not contain the expected on-chain event.
|
|
15796
16063
|
*/
|
|
15797
16064
|
async *cancelOrderFromSource(order, indexerClient) {
|
|
15798
|
-
const
|
|
15799
|
-
const
|
|
15800
|
-
const
|
|
15801
|
-
|
|
15802
|
-
);
|
|
16065
|
+
const sourceStateMachine = normalizeStateMachineId(order.source);
|
|
16066
|
+
const destStateMachine = normalizeStateMachineId(order.destination);
|
|
16067
|
+
const isSameChain = sourceStateMachine === destStateMachine;
|
|
16068
|
+
const intentGatewayAddress = this.ctx.source.configService.getIntentGatewayAddress(sourceStateMachine);
|
|
15803
16069
|
if (isSameChain) {
|
|
15804
16070
|
const data = encodeFunctionData({
|
|
15805
16071
|
abi: ABI3,
|
|
@@ -15828,18 +16094,37 @@ var OrderCanceller = class {
|
|
|
15828
16094
|
};
|
|
15829
16095
|
return;
|
|
15830
16096
|
}
|
|
16097
|
+
const storageKeys = this.recoveryStorageKeys(order);
|
|
16098
|
+
const legacyStorageKeys = this.legacyRecoveryStorageKeys(order);
|
|
15831
16099
|
const hyperbridge = indexerClient.hyperbridge;
|
|
15832
|
-
const sourceStateMachine = normalizeStateMachineId(order.source);
|
|
15833
16100
|
const sourceConsensusStateId = this.ctx.source.configService.getConsensusStateId(sourceStateMachine);
|
|
15834
|
-
let destIProof = await this.
|
|
16101
|
+
let destIProof = await this.getRecoveryItem(
|
|
16102
|
+
storageKeys.destProof,
|
|
16103
|
+
legacyStorageKeys.map((keys) => keys.destProof)
|
|
16104
|
+
);
|
|
15835
16105
|
if (!destIProof) {
|
|
15836
16106
|
destIProof = yield* this.fetchDestinationProof(order, indexerClient);
|
|
15837
|
-
await this.ctx.cancellationStorage.setItem(
|
|
16107
|
+
await this.ctx.cancellationStorage.setItem(storageKeys.destProof, destIProof);
|
|
15838
16108
|
} else {
|
|
15839
|
-
|
|
16109
|
+
let refreshed = false;
|
|
16110
|
+
try {
|
|
16111
|
+
await this.assertProofFresh(hyperbridge, destIProof);
|
|
16112
|
+
} catch (error) {
|
|
16113
|
+
if (!MissingConsensusUpdateTimeError.isError(error)) throw error;
|
|
16114
|
+
await this.removeRecoveryItems(
|
|
16115
|
+
storageKeys.destProof,
|
|
16116
|
+
...legacyStorageKeys.map((keys) => keys.destProof)
|
|
16117
|
+
);
|
|
16118
|
+
destIProof = yield* this.fetchDestinationProof(order, indexerClient);
|
|
16119
|
+
await this.ctx.cancellationStorage.setItem(storageKeys.destProof, destIProof);
|
|
16120
|
+
refreshed = true;
|
|
16121
|
+
}
|
|
16122
|
+
if (!refreshed) yield { status: "DESTINATION_FINALIZED", proof: destIProof };
|
|
15840
16123
|
}
|
|
15841
|
-
|
|
15842
|
-
|
|
16124
|
+
await this.assertProofFresh(hyperbridge, destIProof);
|
|
16125
|
+
let getRequest = await this.getRecoveryItem(
|
|
16126
|
+
storageKeys.getRequest,
|
|
16127
|
+
legacyStorageKeys.map((keys) => keys.getRequest)
|
|
15843
16128
|
);
|
|
15844
16129
|
if (!getRequest) {
|
|
15845
16130
|
const quote = await this.quoteCancelFromSource(order);
|
|
@@ -15859,7 +16144,7 @@ var OrderCanceller = class {
|
|
|
15859
16144
|
const request = events.find((e) => e.eventName === "GetRequestEvent");
|
|
15860
16145
|
if (!request) throw new Error("GetRequest missing");
|
|
15861
16146
|
getRequest = request.args;
|
|
15862
|
-
await this.ctx.cancellationStorage.setItem(
|
|
16147
|
+
await this.ctx.cancellationStorage.setItem(storageKeys.getRequest, getRequest);
|
|
15863
16148
|
yield {
|
|
15864
16149
|
status: "CANCEL_STARTED",
|
|
15865
16150
|
receipt
|
|
@@ -15878,8 +16163,9 @@ var OrderCanceller = class {
|
|
|
15878
16163
|
metadata: statusUpdate.metadata
|
|
15879
16164
|
};
|
|
15880
16165
|
const sourceHeight = BigInt(statusUpdate.metadata.blockNumber);
|
|
15881
|
-
let sourceIProof = await this.
|
|
15882
|
-
|
|
16166
|
+
let sourceIProof = await this.getRecoveryItem(
|
|
16167
|
+
storageKeys.sourceProof,
|
|
16168
|
+
legacyStorageKeys.map((keys) => keys.sourceProof)
|
|
15883
16169
|
);
|
|
15884
16170
|
if (!sourceIProof) {
|
|
15885
16171
|
sourceIProof = await fetchSourceProof(
|
|
@@ -15889,8 +16175,9 @@ var OrderCanceller = class {
|
|
|
15889
16175
|
sourceConsensusStateId,
|
|
15890
16176
|
sourceHeight
|
|
15891
16177
|
);
|
|
15892
|
-
await this.ctx.cancellationStorage.setItem(
|
|
16178
|
+
await this.ctx.cancellationStorage.setItem(storageKeys.sourceProof, sourceIProof);
|
|
15893
16179
|
}
|
|
16180
|
+
await this.assertProofFresh(hyperbridge, sourceIProof);
|
|
15894
16181
|
await waitForChallengePeriod(hyperbridge, {
|
|
15895
16182
|
height: sourceIProof.height,
|
|
15896
16183
|
id: {
|
|
@@ -15898,6 +16185,10 @@ var OrderCanceller = class {
|
|
|
15898
16185
|
consensusStateId: sourceConsensusStateId
|
|
15899
16186
|
}
|
|
15900
16187
|
});
|
|
16188
|
+
await Promise.all([
|
|
16189
|
+
this.assertProofFresh(hyperbridge, sourceIProof),
|
|
16190
|
+
this.assertProofFresh(hyperbridge, destIProof)
|
|
16191
|
+
]);
|
|
15901
16192
|
const getRequestMessage = {
|
|
15902
16193
|
kind: "GetRequest",
|
|
15903
16194
|
requests: [getRequest],
|
|
@@ -15919,9 +16210,12 @@ var OrderCanceller = class {
|
|
|
15919
16210
|
status: "HYPERBRIDGE_FINALIZED",
|
|
15920
16211
|
metadata: statusUpdate.metadata
|
|
15921
16212
|
};
|
|
15922
|
-
await this.
|
|
15923
|
-
|
|
15924
|
-
|
|
16213
|
+
await this.removeRecoveryItems(
|
|
16214
|
+
storageKeys.destProof,
|
|
16215
|
+
storageKeys.getRequest,
|
|
16216
|
+
storageKeys.sourceProof,
|
|
16217
|
+
...legacyStorageKeys.flatMap((keys) => [keys.destProof, keys.getRequest, keys.sourceProof])
|
|
16218
|
+
);
|
|
15925
16219
|
return;
|
|
15926
16220
|
}
|
|
15927
16221
|
}
|
|
@@ -15938,9 +16232,11 @@ var OrderCanceller = class {
|
|
|
15938
16232
|
* @returns The native token dispatch fee in wei.
|
|
15939
16233
|
*/
|
|
15940
16234
|
async quoteCancelFromDest(order) {
|
|
15941
|
-
if (order.source === order.destination) return { nativeValue: 0n, relayerFee: 0n };
|
|
15942
|
-
const destStateMachine = normalizeStateMachineId(order.destination);
|
|
15943
16235
|
const sourceStateMachine = normalizeStateMachineId(order.source);
|
|
16236
|
+
const destStateMachine = normalizeStateMachineId(order.destination);
|
|
16237
|
+
if (sourceStateMachine === destStateMachine) {
|
|
16238
|
+
return { nativeValue: 0n, relayerFee: 0n };
|
|
16239
|
+
}
|
|
15944
16240
|
const destIntentGateway = this.ctx.dest.configService.getIntentGatewayAddress(destStateMachine);
|
|
15945
16241
|
const sourceIntentGateway = this.ctx.source.configService.getIntentGatewayAddress(sourceStateMachine);
|
|
15946
16242
|
const relayerFee = await this.estimateRelayerFee(sourceStateMachine, destStateMachine);
|
|
@@ -15978,11 +16274,13 @@ var OrderCanceller = class {
|
|
|
15978
16274
|
* @throws If the cancel transaction does not contain a `PostRequestEvent`.
|
|
15979
16275
|
*/
|
|
15980
16276
|
async *cancelOrderFromDest(order, indexerClient) {
|
|
15981
|
-
const
|
|
16277
|
+
const storageKeys = this.recoveryStorageKeys(order);
|
|
15982
16278
|
const destStateMachine = normalizeStateMachineId(order.destination);
|
|
15983
16279
|
const intentGatewayAddress = this.ctx.dest.configService.getIntentGatewayAddress(destStateMachine);
|
|
15984
|
-
|
|
15985
|
-
|
|
16280
|
+
const legacyStorageKeys = this.legacyRecoveryStorageKeys(order);
|
|
16281
|
+
let commitment = await this.getRecoveryItem(
|
|
16282
|
+
storageKeys.postCommitment,
|
|
16283
|
+
legacyStorageKeys.map((keys) => keys.postCommitment)
|
|
15986
16284
|
);
|
|
15987
16285
|
if (!commitment) {
|
|
15988
16286
|
const quote = await this.quoteCancelFromDest(order);
|
|
@@ -16007,7 +16305,7 @@ var OrderCanceller = class {
|
|
|
16007
16305
|
if (!postEvent) throw new Error("PostRequestEvent not found in cancel transaction receipt");
|
|
16008
16306
|
const postArgs = postEvent.args;
|
|
16009
16307
|
commitment = postRequestCommitment(postArgs).commitment;
|
|
16010
|
-
await this.ctx.cancellationStorage.setItem(
|
|
16308
|
+
await this.ctx.cancellationStorage.setItem(storageKeys.postCommitment, commitment);
|
|
16011
16309
|
}
|
|
16012
16310
|
const statusStream = indexerClient.postRequestStatusStream(commitment);
|
|
16013
16311
|
for await (const statusUpdate of statusStream) {
|
|
@@ -16041,7 +16339,10 @@ var OrderCanceller = class {
|
|
|
16041
16339
|
if (refundEvents.length === 0) {
|
|
16042
16340
|
throw new Error("EscrowRefunded event not found in source-chain delivery receipt");
|
|
16043
16341
|
}
|
|
16044
|
-
await this.
|
|
16342
|
+
await this.removeRecoveryItems(
|
|
16343
|
+
storageKeys.postCommitment,
|
|
16344
|
+
...legacyStorageKeys.map((keys) => keys.postCommitment)
|
|
16345
|
+
);
|
|
16045
16346
|
yield {
|
|
16046
16347
|
status: "CANCELLATION_COMPLETE",
|
|
16047
16348
|
blockNumber: statusUpdate.metadata.blockNumber,
|
|
@@ -16084,7 +16385,7 @@ var OrderCanceller = class {
|
|
|
16084
16385
|
const intentGatewayV2Address = this.ctx.dest.configService.getIntentGatewayAddress(
|
|
16085
16386
|
this.ctx.dest.config.stateMachineId
|
|
16086
16387
|
);
|
|
16087
|
-
const orderId = order
|
|
16388
|
+
const orderId = this.orderId(order);
|
|
16088
16389
|
const slotHash = await this.ctx.dest.client.readContract({
|
|
16089
16390
|
abi: ABI3,
|
|
16090
16391
|
address: intentGatewayV2Address,
|
|
@@ -16101,6 +16402,7 @@ var OrderCanceller = class {
|
|
|
16101
16402
|
yield { status: "DESTINATION_FINALIZED", proof };
|
|
16102
16403
|
return proof;
|
|
16103
16404
|
} catch (e) {
|
|
16405
|
+
if (MissingConsensusUpdateTimeError.isError(e)) throw e;
|
|
16104
16406
|
lastFailedHeight = latestHeight;
|
|
16105
16407
|
await sleep(1e4);
|
|
16106
16408
|
}
|
|
@@ -16131,6 +16433,7 @@ var OrderCanceller = class {
|
|
|
16131
16433
|
this.logger.info(`Unsigned GET ${commitment} submitted; waiting for Hyperbridge response receipt`);
|
|
16132
16434
|
await sleep(3e4);
|
|
16133
16435
|
} catch (error) {
|
|
16436
|
+
if (MissingConsensusUpdateTimeError.isError(error)) throw error;
|
|
16134
16437
|
this.logger.warn(
|
|
16135
16438
|
`Unsigned GET submit failed for ${commitment}; polling response receipt before failing: ${String(error)}`
|
|
16136
16439
|
);
|
|
@@ -16139,14 +16442,128 @@ var OrderCanceller = class {
|
|
|
16139
16442
|
await this.pollDeliveredReceipt(hyperbridge, commitment);
|
|
16140
16443
|
this.logger.info(`Confirmed Hyperbridge GET delivery for ${commitment}`);
|
|
16141
16444
|
} catch (error) {
|
|
16445
|
+
if (MissingConsensusUpdateTimeError.isError(error)) throw error;
|
|
16142
16446
|
const message2 = `Failed to deliver GET request to Hyperbridge; no response receipt found for ${commitment}: ${String(error)}`;
|
|
16143
16447
|
this.logger.error(message2);
|
|
16144
16448
|
throw new Error(message2);
|
|
16145
16449
|
}
|
|
16146
16450
|
}
|
|
16451
|
+
/** Verify that Hyperbridge still retains the consensus update for a proof. */
|
|
16452
|
+
async assertProofFresh(hyperbridge, proof) {
|
|
16453
|
+
await retryPromise(
|
|
16454
|
+
() => hyperbridge.stateMachineUpdateTime({
|
|
16455
|
+
height: proof.height,
|
|
16456
|
+
id: {
|
|
16457
|
+
stateId: parseStateMachineId(proof.stateMachine).stateId,
|
|
16458
|
+
consensusStateId: proof.consensusStateId
|
|
16459
|
+
}
|
|
16460
|
+
}),
|
|
16461
|
+
{
|
|
16462
|
+
maxRetries: _OrderCanceller.PROOF_FRESHNESS_MAX_RETRIES,
|
|
16463
|
+
backoffMs: _OrderCanceller.PROOF_FRESHNESS_BACKOFF_MS,
|
|
16464
|
+
logger: this.logger,
|
|
16465
|
+
logMessage: `Checking consensus update time for proof at height ${proof.height}`,
|
|
16466
|
+
shouldRetry: (error) => !MissingConsensusUpdateTimeError.isError(error)
|
|
16467
|
+
}
|
|
16468
|
+
);
|
|
16469
|
+
}
|
|
16470
|
+
/**
|
|
16471
|
+
* Drops the source-initiated GET recovery checkpoint after Hyperbridge prunes
|
|
16472
|
+
* a consensus update required by that recovery attempt.
|
|
16473
|
+
*/
|
|
16474
|
+
async clearGetRecoveryCache(order) {
|
|
16475
|
+
const keys = this.recoveryStorageKeys(order);
|
|
16476
|
+
const legacyStorageKeys = this.legacyRecoveryStorageKeys(order);
|
|
16477
|
+
await this.removeRecoveryItems(
|
|
16478
|
+
keys.destProof,
|
|
16479
|
+
keys.sourceProof,
|
|
16480
|
+
keys.getRequest,
|
|
16481
|
+
...legacyStorageKeys.flatMap((legacyKeys) => [
|
|
16482
|
+
legacyKeys.destProof,
|
|
16483
|
+
legacyKeys.sourceProof,
|
|
16484
|
+
legacyKeys.getRequest
|
|
16485
|
+
])
|
|
16486
|
+
);
|
|
16487
|
+
}
|
|
16488
|
+
/**
|
|
16489
|
+
* Returns the pair-scoped storage keys used to resume cancellation recovery
|
|
16490
|
+
* for an order.
|
|
16491
|
+
*
|
|
16492
|
+
* @param order - The order whose source/destination recovery state is stored.
|
|
16493
|
+
*/
|
|
16494
|
+
recoveryStorageKeys(order) {
|
|
16495
|
+
const orderId = this.orderId(order);
|
|
16496
|
+
return {
|
|
16497
|
+
destProof: STORAGE_KEYS.destProof(orderId, order.source, order.destination),
|
|
16498
|
+
getRequest: STORAGE_KEYS.getRequest(orderId, order.source, order.destination),
|
|
16499
|
+
sourceProof: STORAGE_KEYS.sourceProof(orderId, order.source, order.destination),
|
|
16500
|
+
postCommitment: STORAGE_KEYS.postCommitment(orderId, order.source, order.destination)
|
|
16501
|
+
};
|
|
16502
|
+
}
|
|
16503
|
+
/** Older SDK key shapes, checked once and migrated to the normalized pair-scoped key. */
|
|
16504
|
+
legacyRecoveryStorageKeys(order) {
|
|
16505
|
+
const orderId = this.orderId(order);
|
|
16506
|
+
return [
|
|
16507
|
+
{
|
|
16508
|
+
destProof: LEGACY_STORAGE_KEYS.destProof(orderId, order.source, order.destination),
|
|
16509
|
+
getRequest: LEGACY_STORAGE_KEYS.getRequest(orderId, order.source, order.destination),
|
|
16510
|
+
sourceProof: LEGACY_STORAGE_KEYS.sourceProof(orderId, order.source, order.destination),
|
|
16511
|
+
postCommitment: LEGACY_STORAGE_KEYS.postCommitment(orderId, order.source, order.destination)
|
|
16512
|
+
},
|
|
16513
|
+
{
|
|
16514
|
+
destProof: LEGACY_STORAGE_KEYS.destProof(orderId),
|
|
16515
|
+
getRequest: LEGACY_STORAGE_KEYS.getRequest(orderId),
|
|
16516
|
+
sourceProof: LEGACY_STORAGE_KEYS.sourceProof(orderId),
|
|
16517
|
+
postCommitment: LEGACY_STORAGE_KEYS.postCommitment(orderId)
|
|
16518
|
+
}
|
|
16519
|
+
];
|
|
16520
|
+
}
|
|
16521
|
+
async getRecoveryItem(currentKey, legacyKeys) {
|
|
16522
|
+
const current = await this.ctx.cancellationStorage.getItem(currentKey);
|
|
16523
|
+
if (current) return current;
|
|
16524
|
+
for (const legacyKey of new Set(legacyKeys)) {
|
|
16525
|
+
if (legacyKey === currentKey) continue;
|
|
16526
|
+
const legacy = await this.ctx.cancellationStorage.getItem(legacyKey);
|
|
16527
|
+
if (!legacy) continue;
|
|
16528
|
+
await this.ctx.cancellationStorage.setItem(currentKey, legacy);
|
|
16529
|
+
await this.ctx.cancellationStorage.removeItem(legacyKey);
|
|
16530
|
+
return legacy;
|
|
16531
|
+
}
|
|
16532
|
+
return null;
|
|
16533
|
+
}
|
|
16534
|
+
async removeRecoveryItems(...keys) {
|
|
16535
|
+
await Promise.all(
|
|
16536
|
+
[...new Set(keys)].map((key) => this.ctx.cancellationStorage.removeItem(key))
|
|
16537
|
+
);
|
|
16538
|
+
}
|
|
16539
|
+
/**
|
|
16540
|
+
* Returns the order identifier required to persist or clear recovery state.
|
|
16541
|
+
*
|
|
16542
|
+
* @param order - The order being cancelled.
|
|
16543
|
+
* @throws If the order has no identifier.
|
|
16544
|
+
*/
|
|
16545
|
+
orderId(order) {
|
|
16546
|
+
if (!order.id) throw new Error("An order id is required to recover cancellation");
|
|
16547
|
+
return order.id;
|
|
16548
|
+
}
|
|
16549
|
+
/**
|
|
16550
|
+
* Reads the Hyperbridge response receipt for a GET request commitment.
|
|
16551
|
+
*
|
|
16552
|
+
* @param hyperbridge - Hyperbridge chain client used to query the receipt.
|
|
16553
|
+
* @param commitment - Commitment of the GET request.
|
|
16554
|
+
* @returns The receipt commitment when delivered, otherwise `undefined`.
|
|
16555
|
+
*/
|
|
16147
16556
|
async queryDeliveredReceipt(hyperbridge, commitment) {
|
|
16148
16557
|
return hyperbridge.queryResponseReceipt(commitment);
|
|
16149
16558
|
}
|
|
16559
|
+
/**
|
|
16560
|
+
* Polls Hyperbridge until it records a response receipt for the GET request.
|
|
16561
|
+
*
|
|
16562
|
+
* @param hyperbridge - Hyperbridge chain client used to query the receipt.
|
|
16563
|
+
* @param commitment - Commitment of the GET request.
|
|
16564
|
+
* @returns The delivered response receipt commitment.
|
|
16565
|
+
* @throws If no receipt is observed within the configured retry limit.
|
|
16566
|
+
*/
|
|
16150
16567
|
async pollDeliveredReceipt(hyperbridge, commitment) {
|
|
16151
16568
|
this.logger.info(`Polling Hyperbridge GET response receipt for ${commitment}`);
|
|
16152
16569
|
return retryPromise(
|
|
@@ -17359,6 +17776,178 @@ var OrderStatusChecker = class {
|
|
|
17359
17776
|
return true;
|
|
17360
17777
|
}
|
|
17361
17778
|
};
|
|
17779
|
+
var COMMITMENT_PATTERN = /^0x[0-9a-f]{64}$/i;
|
|
17780
|
+
var LiquidityEngine = class {
|
|
17781
|
+
/**
|
|
17782
|
+
* @param queryClient - Nexus GraphQL client attached to the gateway.
|
|
17783
|
+
* @param chainConfigService - Resolves token decimals for formatted results.
|
|
17784
|
+
*/
|
|
17785
|
+
constructor(queryClient, chainConfigService) {
|
|
17786
|
+
this.queryClient = queryClient;
|
|
17787
|
+
this.chainConfigService = chainConfigService;
|
|
17788
|
+
}
|
|
17789
|
+
queryClient;
|
|
17790
|
+
chainConfigService;
|
|
17791
|
+
/**
|
|
17792
|
+
* Retrieves the newest directional Phantom snapshot for a pair and its
|
|
17793
|
+
* indexed output-token liquidity.
|
|
17794
|
+
*
|
|
17795
|
+
* Nexus filters balances to the canonical output token, then aggregates them
|
|
17796
|
+
* overall and by chain. The returned amounts are decimal strings: the total
|
|
17797
|
+
* uses the canonical Base output-token decimals, while each chain group uses
|
|
17798
|
+
* that chain's token decimals. They describe `snapshotTime`, not live
|
|
17799
|
+
* reservations or fill guarantees.
|
|
17800
|
+
*
|
|
17801
|
+
* @param params - Canonical Phantom-market input and output token addresses.
|
|
17802
|
+
* @returns The latest snapshot, or `undefined` if Nexus has no snapshot for
|
|
17803
|
+
* the directional pair.
|
|
17804
|
+
* @throws {InvalidAvailableLiquiditySnapshotError} If Nexus returns malformed
|
|
17805
|
+
* or internally inconsistent snapshot data.
|
|
17806
|
+
*/
|
|
17807
|
+
async getAvailableLiquiditySnapshot(params) {
|
|
17808
|
+
const tokenIn = normalizeEvmAddress(params.tokenIn, "tokenIn");
|
|
17809
|
+
const tokenOut = normalizeEvmAddress(params.tokenOut, "tokenOut");
|
|
17810
|
+
const response = await this.queryClient.request(
|
|
17811
|
+
LATEST_PHANTOM_ORDER_LIQUIDITY_SNAPSHOT,
|
|
17812
|
+
{ tokenA: tokenIn, tokenB: tokenOut }
|
|
17813
|
+
);
|
|
17814
|
+
const node = response?.phantomOrderPriceSnapshots?.nodes?.[0];
|
|
17815
|
+
if (!node) return;
|
|
17816
|
+
const commitment = node.commitment.toLowerCase();
|
|
17817
|
+
if (!COMMITMENT_PATTERN.test(commitment)) {
|
|
17818
|
+
throw new InvalidAvailableLiquiditySnapshotError(commitment || "<missing>", "commitment is not bytes32 hex");
|
|
17819
|
+
}
|
|
17820
|
+
if (node.tokenA.toLowerCase() !== tokenIn || node.tokenB.toLowerCase() !== tokenOut) {
|
|
17821
|
+
throw new InvalidAvailableLiquiditySnapshotError(commitment, "snapshot token pair does not match the query");
|
|
17822
|
+
}
|
|
17823
|
+
const snapshotTime = new Date(dateStringtoTimestamp(node.snapshotTime));
|
|
17824
|
+
if (Number.isNaN(snapshotTime.getTime())) {
|
|
17825
|
+
throw new InvalidAvailableLiquiditySnapshotError(commitment, "snapshotTime is invalid");
|
|
17826
|
+
}
|
|
17827
|
+
const { totalLiquidity, providerCount, liquidityByChain } = await this.querySnapshotLiquidityAggregates({
|
|
17828
|
+
commitment,
|
|
17829
|
+
tokenAddress: tokenOut
|
|
17830
|
+
});
|
|
17831
|
+
return {
|
|
17832
|
+
totalLiquidity: this.formatLiquidity(totalLiquidity, "EVM-8453" /* BASE_MAINNET */, tokenOut, commitment),
|
|
17833
|
+
providerCount,
|
|
17834
|
+
tokenAddress: tokenOut,
|
|
17835
|
+
snapshotTime,
|
|
17836
|
+
liquidityByChain: liquidityByChain.map((group) => ({
|
|
17837
|
+
...group,
|
|
17838
|
+
totalLiquidity: this.formatLiquidity(group.totalLiquidity, group.chain, group.tokenAddress, commitment)
|
|
17839
|
+
}))
|
|
17840
|
+
};
|
|
17841
|
+
}
|
|
17842
|
+
/**
|
|
17843
|
+
* Requests server-side sums and distinct provider counts for one immutable
|
|
17844
|
+
* snapshot/output-token pair, including chain-level aggregate groups.
|
|
17845
|
+
*
|
|
17846
|
+
* `commitment` uniquely identifies the selected snapshot
|
|
17847
|
+
*/
|
|
17848
|
+
async querySnapshotLiquidityAggregates(params) {
|
|
17849
|
+
const response = await this.queryClient.request(
|
|
17850
|
+
LIQUIDITY_PROVIDER_BALANCES,
|
|
17851
|
+
{ commitment: params.commitment, tokenAddress: params.tokenAddress }
|
|
17852
|
+
);
|
|
17853
|
+
const connection = response?.liquidityProviderBalances;
|
|
17854
|
+
const aggregates = connection?.aggregates;
|
|
17855
|
+
if (!connection || !aggregates) {
|
|
17856
|
+
throw new InvalidAvailableLiquiditySnapshotError(
|
|
17857
|
+
params.commitment,
|
|
17858
|
+
"liquidityProviderBalances aggregates are missing"
|
|
17859
|
+
);
|
|
17860
|
+
}
|
|
17861
|
+
const totalLiquidity = parseSnapshotBigInt(aggregates.sum.balance ?? "0", params.commitment, "total balance");
|
|
17862
|
+
const providerCount = parseProviderCount(aggregates.distinctCount.providerId, params.commitment, "total");
|
|
17863
|
+
const liquidityByChain = connection.groupedAggregates.map((group, index) => {
|
|
17864
|
+
const [chain, tokenAddress] = group.keys;
|
|
17865
|
+
if (!chain?.trim() || !tokenAddress) {
|
|
17866
|
+
throw new InvalidAvailableLiquiditySnapshotError(
|
|
17867
|
+
params.commitment,
|
|
17868
|
+
`liquidity group ${index} has invalid keys`
|
|
17869
|
+
);
|
|
17870
|
+
}
|
|
17871
|
+
const normalizedTokenAddress = normalizeIndexedLiquidityAddress(
|
|
17872
|
+
tokenAddress,
|
|
17873
|
+
params.commitment,
|
|
17874
|
+
`liquidity group ${index} tokenAddress`
|
|
17875
|
+
);
|
|
17876
|
+
if (normalizedTokenAddress !== params.tokenAddress) {
|
|
17877
|
+
throw new InvalidAvailableLiquiditySnapshotError(
|
|
17878
|
+
params.commitment,
|
|
17879
|
+
`liquidity group ${index} tokenAddress does not match the snapshot output token`
|
|
17880
|
+
);
|
|
17881
|
+
}
|
|
17882
|
+
return {
|
|
17883
|
+
chain: chain.trim(),
|
|
17884
|
+
tokenAddress: normalizedTokenAddress,
|
|
17885
|
+
totalLiquidity: parseSnapshotBigInt(
|
|
17886
|
+
group.sum.balance ?? "0",
|
|
17887
|
+
params.commitment,
|
|
17888
|
+
`liquidity group ${index} balance`
|
|
17889
|
+
),
|
|
17890
|
+
providerCount: parseProviderCount(
|
|
17891
|
+
group.distinctCount.providerId,
|
|
17892
|
+
params.commitment,
|
|
17893
|
+
`liquidity group ${index}`
|
|
17894
|
+
)
|
|
17895
|
+
};
|
|
17896
|
+
});
|
|
17897
|
+
const groupedTotal = liquidityByChain.reduce((sum, group) => sum + group.totalLiquidity, 0n);
|
|
17898
|
+
if (groupedTotal !== totalLiquidity) {
|
|
17899
|
+
throw new InvalidAvailableLiquiditySnapshotError(
|
|
17900
|
+
params.commitment,
|
|
17901
|
+
"grouped liquidity does not match the total liquidity"
|
|
17902
|
+
);
|
|
17903
|
+
}
|
|
17904
|
+
return { totalLiquidity, providerCount, liquidityByChain };
|
|
17905
|
+
}
|
|
17906
|
+
/** Formats a raw amount using the configured decimals for its chain/token. */
|
|
17907
|
+
formatLiquidity(amount, chain, tokenAddress, commitment) {
|
|
17908
|
+
const decimals = this.chainConfigService.getAssetMetadataByAddress(chain, tokenAddress)?.decimals;
|
|
17909
|
+
if (decimals === void 0) {
|
|
17910
|
+
throw new InvalidAvailableLiquiditySnapshotError(
|
|
17911
|
+
commitment,
|
|
17912
|
+
`token decimals are not configured for ${tokenAddress} on ${chain}`
|
|
17913
|
+
);
|
|
17914
|
+
}
|
|
17915
|
+
return formatUnits(amount, decimals);
|
|
17916
|
+
}
|
|
17917
|
+
};
|
|
17918
|
+
var InvalidAvailableLiquiditySnapshotError = class extends Error {
|
|
17919
|
+
/** Creates an error that identifies the invalid snapshot and field/reason. */
|
|
17920
|
+
constructor(commitment, reason) {
|
|
17921
|
+
super(`Invalid available-liquidity snapshot ${commitment}: ${reason}`);
|
|
17922
|
+
this.name = "InvalidAvailableLiquiditySnapshotError";
|
|
17923
|
+
}
|
|
17924
|
+
};
|
|
17925
|
+
function parseSnapshotBigInt(value, commitment, field) {
|
|
17926
|
+
try {
|
|
17927
|
+
const amount = BigInt(value);
|
|
17928
|
+
if (amount < 0n) {
|
|
17929
|
+
throw new InvalidAvailableLiquiditySnapshotError(commitment, `${field} cannot be negative`);
|
|
17930
|
+
}
|
|
17931
|
+
return amount;
|
|
17932
|
+
} catch (error) {
|
|
17933
|
+
if (error instanceof InvalidAvailableLiquiditySnapshotError) throw error;
|
|
17934
|
+
throw new InvalidAvailableLiquiditySnapshotError(commitment, `${field} is not an integer`);
|
|
17935
|
+
}
|
|
17936
|
+
}
|
|
17937
|
+
function parseProviderCount(value, commitment, field) {
|
|
17938
|
+
const count = Number(value);
|
|
17939
|
+
if (!Number.isSafeInteger(count) || count < 0) {
|
|
17940
|
+
throw new InvalidAvailableLiquiditySnapshotError(commitment, `${field} provider count is invalid`);
|
|
17941
|
+
}
|
|
17942
|
+
return count;
|
|
17943
|
+
}
|
|
17944
|
+
function normalizeIndexedLiquidityAddress(address, commitment, field) {
|
|
17945
|
+
try {
|
|
17946
|
+
return normalizeEvmAddress(address, field);
|
|
17947
|
+
} catch {
|
|
17948
|
+
throw new InvalidAvailableLiquiditySnapshotError(commitment, `${field} is not a valid EVM address`);
|
|
17949
|
+
}
|
|
17950
|
+
}
|
|
17362
17951
|
|
|
17363
17952
|
// src/protocols/intents/quote/types.ts
|
|
17364
17953
|
var UnsupportedIntentQuoteStrategyError = class extends Error {
|
|
@@ -17370,15 +17959,67 @@ var UnsupportedIntentQuoteStrategyError = class extends Error {
|
|
|
17370
17959
|
var UnsupportedIntentQuotePairError = class extends Error {
|
|
17371
17960
|
constructor(params) {
|
|
17372
17961
|
super(
|
|
17373
|
-
`No Uniswap v4 pool config found for ${params.tokenIn
|
|
17962
|
+
`No ${params.quoteSource ?? "Uniswap v4 pool config"} found for ${params.tokenIn} -> ${params.tokenOut} on ${params.source} -> ${params.destination}`
|
|
17374
17963
|
);
|
|
17375
17964
|
this.name = "UnsupportedIntentQuotePairError";
|
|
17376
17965
|
}
|
|
17377
17966
|
};
|
|
17967
|
+
var PhantomSnapshotUnavailableError = class extends Error {
|
|
17968
|
+
constructor(tokenA, tokenB) {
|
|
17969
|
+
super(`No Phantom order price snapshot found for ${tokenA} -> ${tokenB}`);
|
|
17970
|
+
this.name = "PhantomSnapshotUnavailableError";
|
|
17971
|
+
}
|
|
17972
|
+
};
|
|
17973
|
+
var InvalidPhantomSnapshotError = class extends Error {
|
|
17974
|
+
constructor(commitment, reason) {
|
|
17975
|
+
super(`Invalid Phantom order price snapshot ${commitment}: ${reason}`);
|
|
17976
|
+
this.name = "InvalidPhantomSnapshotError";
|
|
17977
|
+
}
|
|
17978
|
+
};
|
|
17979
|
+
var BPS_DENOMINATOR = 10000n;
|
|
17980
|
+
function validateQuoteParams(params) {
|
|
17981
|
+
const hasAmountIn = params.amountIn !== void 0;
|
|
17982
|
+
const hasAmountOut = params.amountOut !== void 0;
|
|
17983
|
+
if (hasAmountIn === hasAmountOut) throw new Error("Provide exactly one of amountIn or amountOut");
|
|
17984
|
+
if (params.amountIn !== void 0 && params.amountIn <= 0n) throw new Error("amountIn must be greater than zero");
|
|
17985
|
+
if (params.amountOut !== void 0 && params.amountOut <= 0n) throw new Error("amountOut must be greater than zero");
|
|
17986
|
+
if (params.tokenIn.toLowerCase() === params.tokenOut.toLowerCase()) {
|
|
17987
|
+
throw new Error("tokenIn and tokenOut cannot be the same");
|
|
17988
|
+
}
|
|
17989
|
+
}
|
|
17990
|
+
async function readProtocolFeeBps(chainConfigService, source) {
|
|
17991
|
+
const gatewayAddress = chainConfigService.getIntentGatewayAddress(source.stateMachineId);
|
|
17992
|
+
if (!gatewayAddress || gatewayAddress === "0x" || gatewayAddress === zeroAddress) {
|
|
17993
|
+
throw new Error(`IntentGatewayV2 is not configured for chain ${source.stateMachineId}`);
|
|
17994
|
+
}
|
|
17995
|
+
const gatewayParams = await source.client.readContract({
|
|
17996
|
+
address: gatewayAddress,
|
|
17997
|
+
abi: IntentGatewayV2_default.ABI,
|
|
17998
|
+
functionName: "params"
|
|
17999
|
+
});
|
|
18000
|
+
const protocolFeeBps = Array.isArray(gatewayParams) ? BigInt(gatewayParams[4]) : BigInt(gatewayParams.protocolFeeBps ?? 0);
|
|
18001
|
+
if (protocolFeeBps < 0n || protocolFeeBps >= BPS_DENOMINATOR) {
|
|
18002
|
+
throw new Error(`Invalid IntentGateway protocol fee: ${protocolFeeBps} bps`);
|
|
18003
|
+
}
|
|
18004
|
+
return protocolFeeBps;
|
|
18005
|
+
}
|
|
18006
|
+
function deductProtocolFee(amount, protocolFeeBps) {
|
|
18007
|
+
if (protocolFeeBps <= 0n) return amount;
|
|
18008
|
+
const fee = amount * protocolFeeBps / BPS_DENOMINATOR;
|
|
18009
|
+
return amount - fee;
|
|
18010
|
+
}
|
|
18011
|
+
function grossUpForProtocolFee(netAmount, protocolFeeBps) {
|
|
18012
|
+
if (protocolFeeBps <= 0n) return netAmount;
|
|
18013
|
+
if (protocolFeeBps >= BPS_DENOMINATOR) throw new Error("protocolFeeBps must be less than 10,000");
|
|
18014
|
+
return divCeil(netAmount * BPS_DENOMINATOR, BPS_DENOMINATOR - protocolFeeBps);
|
|
18015
|
+
}
|
|
18016
|
+
function divCeil(numerator, denominator) {
|
|
18017
|
+
if (denominator <= 0n) throw new Error("denominator must be greater than zero");
|
|
18018
|
+
return (numerator + denominator - 1n) / denominator;
|
|
18019
|
+
}
|
|
17378
18020
|
|
|
17379
18021
|
// src/protocols/intents/quote/uniswapV4.ts
|
|
17380
18022
|
var UNISWAP_INTENT_QUOTE_CHAIN = "EVM-8453" /* BASE_MAINNET */;
|
|
17381
|
-
var BPS_DENOMINATOR = 10000n;
|
|
17382
18023
|
var UniswapV4IntentQuoteStrategy = class {
|
|
17383
18024
|
constructor(chainConfigService) {
|
|
17384
18025
|
this.chainConfigService = chainConfigService;
|
|
@@ -17386,10 +18027,10 @@ var UniswapV4IntentQuoteStrategy = class {
|
|
|
17386
18027
|
chainConfigService;
|
|
17387
18028
|
baseQuoteClient;
|
|
17388
18029
|
async quote(params, source, destination) {
|
|
17389
|
-
|
|
17390
|
-
const protocolFeeBps = await
|
|
18030
|
+
validateQuoteParams(params);
|
|
18031
|
+
const protocolFeeBps = await readProtocolFeeBps(this.chainConfigService, source);
|
|
17391
18032
|
const quoteClient = this.resolveQuoteClient(source, destination);
|
|
17392
|
-
const poolConfig = this.resolvePoolConfig(params, source.stateMachineId,
|
|
18033
|
+
const poolConfig = this.resolvePoolConfig(params, source.stateMachineId, destination.stateMachineId);
|
|
17393
18034
|
return params.amountIn !== void 0 ? this.quoteExactInput({ params, client: quoteClient, protocolFeeBps, poolConfig }) : this.quoteExactOutput({ params, client: quoteClient, protocolFeeBps, poolConfig });
|
|
17394
18035
|
}
|
|
17395
18036
|
resolveQuoteClient(source, destination) {
|
|
@@ -17405,34 +18046,11 @@ var UniswapV4IntentQuoteStrategy = class {
|
|
|
17405
18046
|
this.baseQuoteClient = baseQuoteClient;
|
|
17406
18047
|
return baseQuoteClient;
|
|
17407
18048
|
}
|
|
17408
|
-
validateQuoteParams(params) {
|
|
17409
|
-
const hasAmountIn = params.amountIn !== void 0;
|
|
17410
|
-
const hasAmountOut = params.amountOut !== void 0;
|
|
17411
|
-
if (hasAmountIn === hasAmountOut) throw new Error("Provide exactly one of amountIn or amountOut");
|
|
17412
|
-
if (hasAmountIn && params.amountIn <= 0n) throw new Error("amountIn must be greater than zero");
|
|
17413
|
-
if (hasAmountOut && params.amountOut <= 0n) throw new Error("amountOut must be greater than zero");
|
|
17414
|
-
if (params.tokenIn.address.toLowerCase() === params.tokenOut.address.toLowerCase()) {
|
|
17415
|
-
throw new Error("tokenIn and tokenOut cannot be the same");
|
|
17416
|
-
}
|
|
17417
|
-
}
|
|
17418
|
-
async readProtocolFeeBps(client, chain) {
|
|
17419
|
-
const gatewayAddress = this.chainConfigService.getIntentGatewayAddress(chain);
|
|
17420
|
-
if (!gatewayAddress || gatewayAddress === "0x" || gatewayAddress === zeroAddress) {
|
|
17421
|
-
throw new Error(`IntentGatewayV2 is not configured for chain ${chain}`);
|
|
17422
|
-
}
|
|
17423
|
-
const gatewayParams = await client.readContract({
|
|
17424
|
-
address: gatewayAddress,
|
|
17425
|
-
abi: IntentGatewayV2_default.ABI,
|
|
17426
|
-
functionName: "params"
|
|
17427
|
-
});
|
|
17428
|
-
if (isGatewayParamsTuple(gatewayParams)) return BigInt(gatewayParams[4]);
|
|
17429
|
-
return BigInt(gatewayParams.protocolFeeBps ?? 0);
|
|
17430
|
-
}
|
|
17431
18049
|
resolvePoolConfig(params, source, destination) {
|
|
17432
18050
|
const override = params.uniswapV4?.poolKey;
|
|
17433
18051
|
if (override) {
|
|
17434
18052
|
const poolKey = normalizePoolKey(override);
|
|
17435
|
-
const tokenInForQuote = getAddress(override.currencyIn ?? params.tokenIn
|
|
18053
|
+
const tokenInForQuote = getAddress(override.currencyIn ?? params.tokenIn);
|
|
17436
18054
|
if (tokenInForQuote !== poolKey.currency0 && tokenInForQuote !== poolKey.currency1) {
|
|
17437
18055
|
throw new Error(
|
|
17438
18056
|
`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.`
|
|
@@ -17440,11 +18058,11 @@ var UniswapV4IntentQuoteStrategy = class {
|
|
|
17440
18058
|
}
|
|
17441
18059
|
return {
|
|
17442
18060
|
poolKey,
|
|
17443
|
-
quoterAddress: this.resolveQuoterAddress(
|
|
18061
|
+
quoterAddress: this.resolveQuoterAddress(UNISWAP_INTENT_QUOTE_CHAIN, override.quoterAddress),
|
|
17444
18062
|
tokenInForQuote
|
|
17445
18063
|
};
|
|
17446
18064
|
}
|
|
17447
|
-
const poolConfig = this.resolveConfiguredPool(params, destination);
|
|
18065
|
+
const poolConfig = this.resolveConfiguredPool(params, source, destination, UNISWAP_INTENT_QUOTE_CHAIN);
|
|
17448
18066
|
if (poolConfig) return poolConfig;
|
|
17449
18067
|
throw new UnsupportedIntentQuotePairError({
|
|
17450
18068
|
source,
|
|
@@ -17453,12 +18071,12 @@ var UniswapV4IntentQuoteStrategy = class {
|
|
|
17453
18071
|
tokenOut: params.tokenOut
|
|
17454
18072
|
});
|
|
17455
18073
|
}
|
|
17456
|
-
resolveConfiguredPool(params,
|
|
17457
|
-
for (const pool of this.chainConfigService.getUniswapV4PoolConfigs(
|
|
17458
|
-
const resolvedPool = this.resolveConfiguredPoolTokens(
|
|
18074
|
+
resolveConfiguredPool(params, sourceChain, destinationChain, quoteChain) {
|
|
18075
|
+
for (const pool of this.chainConfigService.getUniswapV4PoolConfigs(quoteChain)) {
|
|
18076
|
+
const resolvedPool = this.resolveConfiguredPoolTokens(quoteChain, pool);
|
|
17459
18077
|
if (!resolvedPool) continue;
|
|
17460
|
-
const tokenInForQuote = matchPoolToken(params.tokenIn, resolvedPool);
|
|
17461
|
-
const tokenOutForQuote = matchPoolToken(params.tokenOut, resolvedPool);
|
|
18078
|
+
const tokenInForQuote = this.matchPoolToken(params.tokenIn, sourceChain, resolvedPool);
|
|
18079
|
+
const tokenOutForQuote = this.matchPoolToken(params.tokenOut, destinationChain, resolvedPool);
|
|
17462
18080
|
if (!tokenInForQuote || !tokenOutForQuote || tokenInForQuote.symbol === tokenOutForQuote.symbol) continue;
|
|
17463
18081
|
const { currency0, currency1 } = sortCurrencies(resolvedPool[0].address, resolvedPool[1].address);
|
|
17464
18082
|
return {
|
|
@@ -17469,7 +18087,7 @@ var UniswapV4IntentQuoteStrategy = class {
|
|
|
17469
18087
|
tickSpacing: pool.tickSpacing,
|
|
17470
18088
|
hooks: getAddress(pool.hooks ?? zeroAddress)
|
|
17471
18089
|
},
|
|
17472
|
-
quoterAddress: this.resolveQuoterAddress(
|
|
18090
|
+
quoterAddress: this.resolveQuoterAddress(quoteChain),
|
|
17473
18091
|
tokenInForQuote: tokenInForQuote.address
|
|
17474
18092
|
};
|
|
17475
18093
|
}
|
|
@@ -17492,8 +18110,18 @@ var UniswapV4IntentQuoteStrategy = class {
|
|
|
17492
18110
|
if (!address || address === "0x") return null;
|
|
17493
18111
|
return { symbol, address: getAddress(address) };
|
|
17494
18112
|
}
|
|
18113
|
+
matchPoolToken(tokenAddress, orderChain, poolTokens) {
|
|
18114
|
+
const addressMatch = poolTokens.find(
|
|
18115
|
+
(poolToken) => poolToken.address.toLowerCase() === tokenAddress.toLowerCase()
|
|
18116
|
+
);
|
|
18117
|
+
if (addressMatch) return addressMatch;
|
|
18118
|
+
const metadata = this.chainConfigService.getAssetMetadataByAddress(orderChain, tokenAddress);
|
|
18119
|
+
if (!metadata) return null;
|
|
18120
|
+
return poolTokens.find((poolToken) => poolToken.symbol === metadata.symbol) ?? null;
|
|
18121
|
+
}
|
|
17495
18122
|
async quoteExactInput(args) {
|
|
17496
18123
|
const amountIn = args.params.amountIn;
|
|
18124
|
+
if (amountIn === void 0) throw new Error("amountIn is required for an exact-input quote");
|
|
17497
18125
|
const swapAmountIn = deductProtocolFee(amountIn, args.protocolFeeBps);
|
|
17498
18126
|
const amountOut = await this.readV4QuoteExactInput(args.client, args.poolConfig, swapAmountIn);
|
|
17499
18127
|
return {
|
|
@@ -17511,6 +18139,7 @@ var UniswapV4IntentQuoteStrategy = class {
|
|
|
17511
18139
|
}
|
|
17512
18140
|
async quoteExactOutput(args) {
|
|
17513
18141
|
const amountOut = args.params.amountOut;
|
|
18142
|
+
if (amountOut === void 0) throw new Error("amountOut is required for an exact-output quote");
|
|
17514
18143
|
const swapAmountIn = await this.readV4QuoteExactOutput(args.client, args.poolConfig, amountOut);
|
|
17515
18144
|
const amountIn = grossUpForProtocolFee(swapAmountIn, args.protocolFeeBps);
|
|
17516
18145
|
return {
|
|
@@ -17589,34 +18218,133 @@ function sortCurrencies(tokenIn, tokenOut) {
|
|
|
17589
18218
|
const output = getAddress(tokenOut);
|
|
17590
18219
|
return BigInt(input) < BigInt(output) ? { currency0: input, currency1: output } : { currency0: output, currency1: input };
|
|
17591
18220
|
}
|
|
17592
|
-
function matchPoolToken(token, poolTokens) {
|
|
17593
|
-
const tokenAddress = token.address.toLowerCase();
|
|
17594
|
-
const addressMatch = poolTokens.find((poolToken) => poolToken.address.toLowerCase() === tokenAddress);
|
|
17595
|
-
if (addressMatch) return addressMatch;
|
|
17596
|
-
const tokenSymbol = token.symbol?.toUpperCase();
|
|
17597
|
-
if (!tokenSymbol) return null;
|
|
17598
|
-
return poolTokens.find((poolToken) => poolToken.symbol.toUpperCase() === tokenSymbol) ?? null;
|
|
17599
|
-
}
|
|
17600
18221
|
function getZeroForOne(tokenIn, poolKey) {
|
|
17601
18222
|
return getAddress(tokenIn).toLowerCase() === getAddress(poolKey.currency0).toLowerCase();
|
|
17602
18223
|
}
|
|
17603
|
-
|
|
17604
|
-
|
|
17605
|
-
|
|
17606
|
-
|
|
17607
|
-
|
|
17608
|
-
|
|
17609
|
-
|
|
17610
|
-
}
|
|
17611
|
-
|
|
17612
|
-
|
|
17613
|
-
|
|
18224
|
+
|
|
18225
|
+
// src/protocols/intents/quote/phantomSnapshot.ts
|
|
18226
|
+
var PHANTOM_INTENT_QUOTE_CHAIN = "EVM-8453" /* BASE_MAINNET */;
|
|
18227
|
+
var BASE_SNAPSHOT_ASSET_BY_ORDER_ASSET = {
|
|
18228
|
+
USDC: "USDC",
|
|
18229
|
+
USDT: "USDC",
|
|
18230
|
+
cNGN: "cNGN"
|
|
18231
|
+
};
|
|
18232
|
+
var SUPPORTED_BASE_SNAPSHOT_PAIRS = /* @__PURE__ */ new Set(["USDC:cNGN", "cNGN:USDC"]);
|
|
18233
|
+
var PhantomSnapshotIntentQuoteStrategy = class {
|
|
18234
|
+
constructor(chainConfigService, getQueryClient) {
|
|
18235
|
+
this.chainConfigService = chainConfigService;
|
|
18236
|
+
this.getQueryClient = getQueryClient;
|
|
18237
|
+
this.pairResolver = new PhantomSnapshotPairResolver(chainConfigService);
|
|
18238
|
+
}
|
|
18239
|
+
chainConfigService;
|
|
18240
|
+
getQueryClient;
|
|
18241
|
+
pairResolver;
|
|
18242
|
+
async quote(params, source, destination) {
|
|
18243
|
+
validateQuoteParams(params);
|
|
18244
|
+
const pair = this.pairResolver.resolve(params, source.stateMachineId, destination.stateMachineId);
|
|
18245
|
+
if (!pair) {
|
|
18246
|
+
throw new UnsupportedIntentQuotePairError({
|
|
18247
|
+
source: source.stateMachineId,
|
|
18248
|
+
destination: destination.stateMachineId,
|
|
18249
|
+
tokenIn: params.tokenIn,
|
|
18250
|
+
tokenOut: params.tokenOut,
|
|
18251
|
+
quoteSource: "Phantom snapshot pair"
|
|
18252
|
+
});
|
|
18253
|
+
}
|
|
18254
|
+
const queryClient = this.getQueryClient();
|
|
18255
|
+
const [protocolFeeBps, snapshot] = await Promise.all([
|
|
18256
|
+
readProtocolFeeBps(this.chainConfigService, source),
|
|
18257
|
+
_queryLatestPhantomOrderPriceSnapshot({
|
|
18258
|
+
tokenA: pair.tokenA,
|
|
18259
|
+
tokenB: pair.tokenB,
|
|
18260
|
+
queryClient
|
|
18261
|
+
})
|
|
18262
|
+
]);
|
|
18263
|
+
if (!snapshot) throw new PhantomSnapshotUnavailableError(pair.tokenA, pair.tokenB);
|
|
18264
|
+
this.validateSnapshot(snapshot);
|
|
18265
|
+
return this.quoteSnapshot(params, protocolFeeBps, snapshot);
|
|
18266
|
+
}
|
|
18267
|
+
quoteSnapshot(params, protocolFeeBps, snapshot) {
|
|
18268
|
+
if (params.amountIn !== void 0) {
|
|
18269
|
+
const netAmountIn2 = deductProtocolFee(params.amountIn, protocolFeeBps);
|
|
18270
|
+
const amountOut = netAmountIn2 * snapshot.medianPrice / snapshot.standardAmount;
|
|
18271
|
+
if (amountOut <= 0n) {
|
|
18272
|
+
throw new InvalidPhantomSnapshotError(snapshot.commitment, "quote rounds down to zero output");
|
|
18273
|
+
}
|
|
18274
|
+
return this.buildResult("EXACT_INPUT", params.amountIn, amountOut, protocolFeeBps, snapshot);
|
|
18275
|
+
}
|
|
18276
|
+
if (params.amountOut === void 0) throw new Error("Quote amount is missing after validation");
|
|
18277
|
+
const netAmountIn = divCeil(params.amountOut * snapshot.standardAmount, snapshot.medianPrice);
|
|
18278
|
+
const amountIn = grossUpForProtocolFee(netAmountIn, protocolFeeBps);
|
|
18279
|
+
return this.buildResult("EXACT_OUTPUT", amountIn, params.amountOut, protocolFeeBps, snapshot);
|
|
18280
|
+
}
|
|
18281
|
+
buildResult(tradeType, amountIn, amountOut, protocolFeeBps, snapshot) {
|
|
18282
|
+
return {
|
|
18283
|
+
strategy: "phantom_snapshot",
|
|
18284
|
+
tradeType,
|
|
18285
|
+
amountIn,
|
|
18286
|
+
amountOut,
|
|
18287
|
+
quoteMetadata: {
|
|
18288
|
+
quoteChain: PHANTOM_INTENT_QUOTE_CHAIN,
|
|
18289
|
+
commitment: snapshot.commitment,
|
|
18290
|
+
tokenA: snapshot.tokenA,
|
|
18291
|
+
tokenB: snapshot.tokenB,
|
|
18292
|
+
standardAmount: snapshot.standardAmount,
|
|
18293
|
+
medianPrice: snapshot.medianPrice,
|
|
18294
|
+
lowestPrice: snapshot.lowestPrice,
|
|
18295
|
+
highestPrice: snapshot.highestPrice,
|
|
18296
|
+
blockNumber: snapshot.blockNumber,
|
|
18297
|
+
snapshotTime: snapshot.snapshotTime,
|
|
18298
|
+
bidCount: snapshot.bidCount,
|
|
18299
|
+
protocolFeeBps
|
|
18300
|
+
}
|
|
18301
|
+
};
|
|
18302
|
+
}
|
|
18303
|
+
validateSnapshot(snapshot) {
|
|
18304
|
+
if (snapshot.standardAmount <= 0n) {
|
|
18305
|
+
throw new InvalidPhantomSnapshotError(snapshot.commitment, "standardAmount must be greater than zero");
|
|
18306
|
+
}
|
|
18307
|
+
if (snapshot.medianPrice <= 0n) {
|
|
18308
|
+
throw new InvalidPhantomSnapshotError(snapshot.commitment, "medianPrice must be greater than zero");
|
|
18309
|
+
}
|
|
18310
|
+
if (snapshot.bidCount <= 0) {
|
|
18311
|
+
throw new InvalidPhantomSnapshotError(snapshot.commitment, "bidCount must be greater than zero");
|
|
18312
|
+
}
|
|
18313
|
+
if (Number.isNaN(snapshot.snapshotTime.getTime())) {
|
|
18314
|
+
throw new InvalidPhantomSnapshotError(snapshot.commitment, "snapshotTime is invalid");
|
|
18315
|
+
}
|
|
18316
|
+
}
|
|
18317
|
+
};
|
|
18318
|
+
var PhantomSnapshotPairResolver = class {
|
|
18319
|
+
constructor(chainConfigService) {
|
|
18320
|
+
this.chainConfigService = chainConfigService;
|
|
18321
|
+
}
|
|
18322
|
+
chainConfigService;
|
|
18323
|
+
resolve(params, sourceStateMachineId, destinationStateMachineId) {
|
|
18324
|
+
const tokenIn = this.resolveBaseSnapshotToken(sourceStateMachineId, params.tokenIn);
|
|
18325
|
+
const tokenOut = this.resolveBaseSnapshotToken(destinationStateMachineId, params.tokenOut);
|
|
18326
|
+
if (!tokenIn || !tokenOut || !isSupportedSnapshotPair(tokenIn.symbol, tokenOut.symbol)) return;
|
|
18327
|
+
return { tokenA: tokenIn.address, tokenB: tokenOut.address };
|
|
18328
|
+
}
|
|
18329
|
+
resolveBaseSnapshotToken(chain, tokenAddress) {
|
|
18330
|
+
const orderAsset = this.chainConfigService.getAssetMetadataByAddress(chain, tokenAddress)?.symbol;
|
|
18331
|
+
if (!orderAsset) return;
|
|
18332
|
+
const snapshotAsset = BASE_SNAPSHOT_ASSET_BY_ORDER_ASSET[orderAsset];
|
|
18333
|
+
if (!snapshotAsset) return;
|
|
18334
|
+
const address = this.chainConfigService.getAssetAddress(PHANTOM_INTENT_QUOTE_CHAIN, snapshotAsset);
|
|
18335
|
+
if (!isConfiguredAddress(address)) return;
|
|
18336
|
+
return { symbol: snapshotAsset, address };
|
|
18337
|
+
}
|
|
18338
|
+
};
|
|
18339
|
+
function isSupportedSnapshotPair(tokenA, tokenB) {
|
|
18340
|
+
return SUPPORTED_BASE_SNAPSHOT_PAIRS.has(`${tokenA}:${tokenB}`);
|
|
17614
18341
|
}
|
|
17615
|
-
function
|
|
17616
|
-
return (
|
|
18342
|
+
function isConfiguredAddress(address) {
|
|
18343
|
+
return Boolean(address && address !== "0x" && !/^0x0{40}$/i.test(address));
|
|
17617
18344
|
}
|
|
17618
18345
|
|
|
17619
18346
|
// src/protocols/intents/IntentGateway.ts
|
|
18347
|
+
var CROSS_CHAIN_ORDER_FEE_GAS_BUMP = 600000n;
|
|
17620
18348
|
var IntentGateway = class _IntentGateway {
|
|
17621
18349
|
/** EVM chain on which orders are placed and escrowed. */
|
|
17622
18350
|
source;
|
|
@@ -17644,6 +18372,8 @@ var IntentGateway = class _IntentGateway {
|
|
|
17644
18372
|
gasEstimator;
|
|
17645
18373
|
/** Quote strategies for pricing orders before placement, keyed by strategy name. */
|
|
17646
18374
|
quoteStrategies;
|
|
18375
|
+
/** Resolves order tokens to canonical Phantom snapshot market pairs. */
|
|
18376
|
+
phantomSnapshotPairResolver;
|
|
17647
18377
|
/**
|
|
17648
18378
|
* Private constructor — use {@link IntentGateway.create} instead.
|
|
17649
18379
|
*
|
|
@@ -17687,7 +18417,12 @@ var IntentGateway = class _IntentGateway {
|
|
|
17687
18417
|
this.bidManager = bidManager;
|
|
17688
18418
|
this.gasEstimator = gasEstimator;
|
|
17689
18419
|
this._crypto = crypto;
|
|
18420
|
+
this.phantomSnapshotPairResolver = new PhantomSnapshotPairResolver(dest.configService);
|
|
17690
18421
|
this.quoteStrategies = {
|
|
18422
|
+
phantom_snapshot: new PhantomSnapshotIntentQuoteStrategy(
|
|
18423
|
+
dest.configService,
|
|
18424
|
+
() => this.requireIndexer().queryClient
|
|
18425
|
+
),
|
|
17691
18426
|
uniswap_v4: new UniswapV4IntentQuoteStrategy(dest.configService)
|
|
17692
18427
|
};
|
|
17693
18428
|
}
|
|
@@ -17737,37 +18472,69 @@ var IntentGateway = class _IntentGateway {
|
|
|
17737
18472
|
/**
|
|
17738
18473
|
* Quotes an intent between this gateway's source and destination chains.
|
|
17739
18474
|
*
|
|
17740
|
-
*
|
|
17741
|
-
*
|
|
18475
|
+
* Uses the latest directional Phantom order price snapshot from the attached
|
|
18476
|
+
* indexer by default. Pass `strategy: "uniswap_v4"` only when explicitly
|
|
18477
|
+
* requesting a Uniswap quote. Provide exactly one of `amountIn` or `amountOut`.
|
|
17742
18478
|
*
|
|
17743
|
-
*
|
|
17744
|
-
*
|
|
18479
|
+
* Both built-in strategies resolve their canonical market on Base,
|
|
18480
|
+
* regardless of this gateway's destination chain. Returned
|
|
17745
18481
|
* `amountIn`/`amountOut` already account for the gateway's protocol fee
|
|
17746
18482
|
* (`quoteMetadata.protocolFeeBps`), which the gateway deducts from order
|
|
17747
|
-
* inputs;
|
|
18483
|
+
* inputs; use the returned amounts directly when placing the order.
|
|
17748
18484
|
*
|
|
17749
18485
|
* @param params - Token pair, amount, and optional strategy/pool overrides.
|
|
17750
18486
|
* @returns The quoted amounts plus strategy-specific metadata.
|
|
17751
18487
|
* @throws {UnsupportedIntentQuoteStrategyError} For unknown strategies.
|
|
17752
|
-
* @throws {UnsupportedIntentQuotePairError} When
|
|
18488
|
+
* @throws {UnsupportedIntentQuotePairError} When the selected strategy does not support the pair.
|
|
18489
|
+
* @throws {PhantomSnapshotUnavailableError} When an eligible cNGN pair has no snapshot.
|
|
17753
18490
|
*/
|
|
17754
18491
|
async quoteIntent(params) {
|
|
17755
|
-
const
|
|
18492
|
+
const source = { stateMachineId: this.source.config.stateMachineId, client: this.source.client };
|
|
18493
|
+
const destination = { stateMachineId: this.dest.config.stateMachineId, client: this.dest.client };
|
|
18494
|
+
const strategy = params.strategy ?? "phantom_snapshot";
|
|
17756
18495
|
const handler = this.quoteStrategies[strategy];
|
|
17757
18496
|
if (!handler) throw new UnsupportedIntentQuoteStrategyError(strategy);
|
|
17758
|
-
return handler.quote(
|
|
17759
|
-
|
|
17760
|
-
|
|
17761
|
-
|
|
17762
|
-
|
|
18497
|
+
return handler.quote({ ...params, strategy }, source, destination);
|
|
18498
|
+
}
|
|
18499
|
+
/**
|
|
18500
|
+
* Returns the output-token liquidity measured in the latest directional
|
|
18501
|
+
* Phantom snapshot for this gateway's source and destination.
|
|
18502
|
+
*
|
|
18503
|
+
* Pair resolution uses the same canonical Base market as {@link quoteIntent}.
|
|
18504
|
+
* The snapshot itself determines the output token and chain to aggregate. The
|
|
18505
|
+
* amount is in the token's smallest unit and reflects the indexer's
|
|
18506
|
+
* `snapshotTime`; it is not a live reservation or fill guarantee.
|
|
18507
|
+
*
|
|
18508
|
+
* Requires a prior call to {@link withQueryClient}.
|
|
18509
|
+
*/
|
|
18510
|
+
async queryAvailableLiquidity(params) {
|
|
18511
|
+
const { queryClient } = this.requireIndexer();
|
|
18512
|
+
const sourceStateMachineId = this.source.config.stateMachineId;
|
|
18513
|
+
const destinationStateMachineId = this.dest.config.stateMachineId;
|
|
18514
|
+
const pair = this.phantomSnapshotPairResolver.resolve(params, sourceStateMachineId, destinationStateMachineId);
|
|
18515
|
+
if (!pair) {
|
|
18516
|
+
throw new UnsupportedIntentQuotePairError({
|
|
18517
|
+
source: sourceStateMachineId,
|
|
18518
|
+
destination: destinationStateMachineId,
|
|
18519
|
+
tokenIn: params.tokenIn,
|
|
18520
|
+
tokenOut: params.tokenOut,
|
|
18521
|
+
quoteSource: "Phantom snapshot pair"
|
|
18522
|
+
});
|
|
18523
|
+
}
|
|
18524
|
+
return new LiquidityEngine(queryClient, this.dest.configService).getAvailableLiquiditySnapshot({
|
|
18525
|
+
tokenIn: pair.tokenA,
|
|
18526
|
+
tokenOut: pair.tokenB
|
|
18527
|
+
});
|
|
17763
18528
|
}
|
|
17764
18529
|
/**
|
|
17765
18530
|
* Bidirectional async generator that orchestrates the full order lifecycle:
|
|
17766
18531
|
* placement, fee estimation, bid collection, and execution.
|
|
17767
18532
|
*
|
|
17768
18533
|
* **Yield/receive protocol:**
|
|
17769
|
-
* 1. If `order.fees` is unset or zero, estimates gas and sets
|
|
17770
|
-
*
|
|
18534
|
+
* 1. If `order.fees` is unset or zero, estimates gas on an internal copy and sets
|
|
18535
|
+
* same-chain fees to twice the estimate. Cross-chain orders retain a 1% buffer
|
|
18536
|
+
* and include an additional 600k-gas fee uplift, while the wei cost used for
|
|
18537
|
+
* the `value` field receives a 2% buffer.
|
|
17771
18538
|
* 2. Yields `AWAITING_PLACE_ORDER` with `{ to, data, value, sessionPrivateKey }`.
|
|
17772
18539
|
* The caller must sign the transaction and pass it back via `gen.next(signedTx)`.
|
|
17773
18540
|
* 3. Yields `ORDER_PLACED` with the finalised order and transaction hash once
|
|
@@ -17775,8 +18542,8 @@ var IntentGateway = class _IntentGateway {
|
|
|
17775
18542
|
* 4. Delegates to {@link OrderExecutor.executeOrder} and forwards all
|
|
17776
18543
|
* subsequent status updates until the order is filled, exhausted, or fails.
|
|
17777
18544
|
*
|
|
17778
|
-
* @param order - The order to place and execute. `order.fees`
|
|
17779
|
-
*
|
|
18545
|
+
* @param order - The order to place and execute. It is not mutated. `order.fees`
|
|
18546
|
+
* may be 0; fees are estimated automatically if so.
|
|
17780
18547
|
* @param graffiti - Optional bytes32 tag for orderflow attribution /
|
|
17781
18548
|
* revenue share. Defaults to {@link DEFAULT_GRAFFITI}.
|
|
17782
18549
|
* @param options - Optional tuning parameters:
|
|
@@ -17789,20 +18556,28 @@ var IntentGateway = class _IntentGateway {
|
|
|
17789
18556
|
* estimation returns zero.
|
|
17790
18557
|
*/
|
|
17791
18558
|
async *execute(order, graffiti = DEFAULT_GRAFFITI, options) {
|
|
18559
|
+
const executionOrder = { ...order };
|
|
17792
18560
|
let value;
|
|
17793
|
-
if (!
|
|
18561
|
+
if (!executionOrder.fees || executionOrder.fees === 0n) {
|
|
17794
18562
|
const estimate = await this.gasEstimator.estimateFillOrder({
|
|
17795
|
-
order,
|
|
18563
|
+
order: executionOrder,
|
|
17796
18564
|
maxPriorityFeePerGasBumpPercent: options?.maxPriorityFeePerGasBumpPercent,
|
|
17797
18565
|
maxFeePerGasBumpPercent: options?.maxFeePerGasBumpPercent
|
|
17798
18566
|
});
|
|
17799
18567
|
if (estimate.totalGasCostWei === 0n || estimate.totalGasInFeeToken === 0n) {
|
|
17800
18568
|
throw new Error("Gas estimation failed");
|
|
17801
18569
|
}
|
|
18570
|
+
const isSameChain = this.source.config.stateMachineId === this.dest.config.stateMachineId;
|
|
17802
18571
|
value = estimate.totalGasCostWei + estimate.totalGasCostWei * 2n / 100n;
|
|
17803
|
-
|
|
18572
|
+
const crossChainFeeBump = isSameChain ? 0n : await convertGasToFeeToken(
|
|
18573
|
+
this.ctx,
|
|
18574
|
+
CROSS_CHAIN_ORDER_FEE_GAS_BUMP,
|
|
18575
|
+
"source",
|
|
18576
|
+
this.source.config.stateMachineId
|
|
18577
|
+
);
|
|
18578
|
+
executionOrder.fees = isSameChain ? estimate.totalGasInFeeToken * 2n : estimate.totalGasInFeeToken + (crossChainFeeBump + estimate.totalGasInFeeToken * 1n / 100n);
|
|
17804
18579
|
}
|
|
17805
|
-
const placeOrderGen = this.orderPlacer.placeOrder(
|
|
18580
|
+
const placeOrderGen = this.orderPlacer.placeOrder(executionOrder, graffiti);
|
|
17806
18581
|
const placeOrderFirst = await placeOrderGen.next();
|
|
17807
18582
|
if (placeOrderFirst.done) {
|
|
17808
18583
|
throw new Error("placeOrder generator completed without yielding");
|
|
@@ -17913,13 +18688,20 @@ var IntentGateway = class _IntentGateway {
|
|
|
17913
18688
|
const gen = this.execute(order, graffiti, options);
|
|
17914
18689
|
try {
|
|
17915
18690
|
let input;
|
|
18691
|
+
let finalizedOrder;
|
|
17916
18692
|
while (true) {
|
|
17917
18693
|
const { value, done } = await gen.next(input);
|
|
17918
18694
|
input = void 0;
|
|
17919
18695
|
if (done) break;
|
|
17920
|
-
if (value.status === "
|
|
18696
|
+
if (value.status === "ORDER_PLACED") {
|
|
18697
|
+
finalizedOrder = value.order;
|
|
17921
18698
|
yield value;
|
|
17922
|
-
|
|
18699
|
+
} else if (value.status === "BIDS_RECEIVED") {
|
|
18700
|
+
if (!finalizedOrder) {
|
|
18701
|
+
throw new Error("Received bids before the order was finalized");
|
|
18702
|
+
}
|
|
18703
|
+
yield value;
|
|
18704
|
+
input = await this.autoSelect(finalizedOrder, value.bids);
|
|
17923
18705
|
} else if (value.status === "AWAITING_PLACE_ORDER") {
|
|
17924
18706
|
input = yield value;
|
|
17925
18707
|
} else {
|
|
@@ -18181,7 +18963,9 @@ var IntentGateway = class _IntentGateway {
|
|
|
18181
18963
|
}
|
|
18182
18964
|
requireIndexer() {
|
|
18183
18965
|
if (!this.indexer) {
|
|
18184
|
-
throw new Error(
|
|
18966
|
+
throw new Error(
|
|
18967
|
+
"IntentGateway: call withQueryClient(queryClient) before using indexer-backed methods or Phantom quotes"
|
|
18968
|
+
);
|
|
18185
18969
|
}
|
|
18186
18970
|
return this.indexer;
|
|
18187
18971
|
}
|
|
@@ -22695,6 +23479,6 @@ async function teleportDot(param_) {
|
|
|
22695
23479
|
return stream;
|
|
22696
23480
|
}
|
|
22697
23481
|
|
|
22698
|
-
export { ADDRESS_ZERO2 as ADDRESS_ZERO, BundlerMethod, ChainConfigService, Chains, CryptoUtils, DEFAULT_ADDRESS, DEFAULT_GRAFFITI, DOMAIN_TYPEHASH, DUMMY_PRIVATE_KEY, ERC20Method, ERC7821_BATCH_MODE, EvmChain, ABI as EvmHostABI, EvmLanguage, HyperClientStatus, HyperFungibleToken, HyperFungibleTokenABI, IntentGateway, ABI3 as IntentGatewayABI, IntentOrderStatus, IntentsCoprocessor, IsmpClient, MOCK_ADDRESS, ORDER_V2_PARAM_TYPE, OrderStatus, OrderStatusChecker, PACKED_USEROP_TYPEHASH, PLACE_ORDER_SELECTOR, PharosChain, PolkadotHubChain, REQUEST_COMMITMENTS_SLOT, REQUEST_RECEIPTS_SLOT, RESPONSE_COMMITMENTS_SLOT, RESPONSE_RECEIPTS_SLOT, RequestKind, RequestStatus, SELECT_SOLVER_TYPEHASH, STATE_COMMITMENTS_SLOT, SubstrateChain, Swap, TESTNET_CHAINS, TeleportStatus, TimeoutStatus, TokenGateway, TronChain, USE_ETHERSCAN_CHAINS, UnsupportedIntentQuotePairError, UnsupportedIntentQuoteStrategyError, WrappedHyperFungibleTokenABI, __test, adjustDecimals, bytes20ToBytes32, bytes32ToBytes20, calculateAllowanceMappingLocation, calculateBalanceMappingLocation, chainConfigs, constructRedeemEscrowRequestBody, constructRefundEscrowRequestBody, convertCodecToIGetRequest, convertCodecToIProof, convertIGetRequestToCodec, convertIProofToCodec, convertStateIdToStateMachineId, convertStateMachineEnumToString, convertStateMachineIdToEnum, createEvmChain, createQueryClient, decodeERC7821ExecuteBatch, decodeUserOpScale, encodeERC7821ExecuteBatch, encodeISMPMessage, encodeStateMachineId, encodeUserOpScale, encodeWithdrawalRequest, estimateGasForPost, fetchPrice, fetchSourceProof, generateRootWithProof, getChainId, getConfigByStateMachineId, getContractCallInput, getContractCallInputs, getGasPriceFromEtherscan, getOrFetchStorageSlot, getOrderPlacedFromTx, getPostRequestEventFromTx, getPostResponseEventFromTx, getRequestCommitment, getStateCommitmentFieldSlot, getStateCommitmentSlot, getStorageSlot, getViemChain, hexToString, hyperbridgeAddress, maxBigInt, normalizeAddressForEvmBytes32, normalizeAddressForStateMachine, normalizeEvmChainId, normalizeStateMachineId, orderCommitment, parseStateMachineId, pharosAtlantic, pharosMainnet, polkadotAssetHubPaseo, polkadotHubMainnet, postRequestCommitment, queryAssetTeleported, queryGetRequest, queryPostRequest, quoteUniswap, requestCommitmentKey, responseCommitmentKey, retryPromise, teleport, teleportDot, transformOrderForContract, tronChainIds, tronNile };
|
|
23482
|
+
export { ADDRESS_ZERO2 as ADDRESS_ZERO, BundlerMethod, ChainConfigService, Chains, CryptoUtils, DEFAULT_ADDRESS, DEFAULT_GRAFFITI, DOMAIN_TYPEHASH, DUMMY_PRIVATE_KEY, ERC20Method, ERC7821_BATCH_MODE, EvmChain, ABI as EvmHostABI, EvmLanguage, HyperClientStatus, HyperFungibleToken, HyperFungibleTokenABI, IntentGateway, ABI3 as IntentGatewayABI, IntentOrderStatus, IntentsCoprocessor, InvalidPhantomSnapshotError, IsmpClient, MOCK_ADDRESS, ORDER_V2_PARAM_TYPE, OrderStatus, OrderStatusChecker, PACKED_USEROP_TYPEHASH, PLACE_ORDER_SELECTOR, PhantomSnapshotUnavailableError, PharosChain, PolkadotHubChain, REQUEST_COMMITMENTS_SLOT, REQUEST_RECEIPTS_SLOT, RESPONSE_COMMITMENTS_SLOT, RESPONSE_RECEIPTS_SLOT, RequestKind, RequestStatus, SELECT_SOLVER_TYPEHASH, STATE_COMMITMENTS_SLOT, SubstrateChain, Swap, TESTNET_CHAINS, TeleportStatus, TimeoutStatus, TokenGateway, TronChain, USE_ETHERSCAN_CHAINS, UnsupportedIntentQuotePairError, UnsupportedIntentQuoteStrategyError, WrappedHyperFungibleTokenABI, __test, adjustDecimals, bytes20ToBytes32, bytes32ToBytes20, calculateAllowanceMappingLocation, calculateBalanceMappingLocation, chainConfigs, constructRedeemEscrowRequestBody, constructRefundEscrowRequestBody, convertCodecToIGetRequest, convertCodecToIProof, convertIGetRequestToCodec, convertIProofToCodec, convertStateIdToStateMachineId, convertStateMachineEnumToString, convertStateMachineIdToEnum, createEvmChain, createQueryClient, decodeERC7821ExecuteBatch, decodeUserOpScale, encodeERC7821ExecuteBatch, encodeISMPMessage, encodeStateMachineId, encodeUserOpScale, encodeWithdrawalRequest, estimateGasForPost, fetchPrice, fetchSourceProof, generateRootWithProof, getChainId, getConfigByStateMachineId, getContractCallInput, getContractCallInputs, getGasPriceFromEtherscan, getOrFetchStorageSlot, getOrderPlacedFromTx, getPostRequestEventFromTx, getPostResponseEventFromTx, getRequestCommitment, getStateCommitmentFieldSlot, getStateCommitmentSlot, getStorageSlot, getViemChain, hexToString, hyperbridgeAddress, maxBigInt, normalizeAddressForEvmBytes32, normalizeAddressForStateMachine, normalizeEvmAddress, normalizeEvmChainId, normalizeStateMachineId, orderCommitment, parseStateMachineId, pharosAtlantic, pharosMainnet, polkadotAssetHubPaseo, polkadotHubMainnet, postRequestCommitment, queryAssetTeleported, queryGetRequest, queryPostRequest, quoteUniswap, requestCommitmentKey, responseCommitmentKey, retryPromise, teleport, teleportDot, transformOrderForContract, tronChainIds, tronNile };
|
|
22699
23483
|
//# sourceMappingURL=index.js.map
|
|
22700
23484
|
//# sourceMappingURL=index.js.map
|