@hyperbridge/sdk 2.4.2 → 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 +87 -12
- package/dist/browser/index.js +662 -92
- package/dist/browser/index.js.map +1 -1
- package/dist/node/{IntentGatewayV2-PzbhFn_7.d.cts → IntentGatewayV2-tYGohDdW.d.cts} +62 -5
- package/dist/node/{IntentGatewayV2-PzbhFn_7.d.ts → IntentGatewayV2-tYGohDdW.d.ts} +62 -5
- package/dist/node/index.cjs +661 -90
- package/dist/node/index.cjs.map +1 -1
- package/dist/node/index.d.cts +28 -10
- package/dist/node/index.d.ts +28 -10
- package/dist/node/index.js +662 -92
- 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';
|
|
@@ -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",
|
|
@@ -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",
|
|
@@ -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",
|
|
@@ -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",
|
|
@@ -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",
|
|
@@ -5281,6 +5286,9 @@ var ChainConfigService = class {
|
|
|
5281
5286
|
getCirclePaymasterAddress(chain) {
|
|
5282
5287
|
return this.getConfig(chain)?.addresses.CirclePaymaster;
|
|
5283
5288
|
}
|
|
5289
|
+
getSimplexPaymasterAddress(chain) {
|
|
5290
|
+
return this.getConfig(chain)?.addresses.SimplexPaymaster;
|
|
5291
|
+
}
|
|
5284
5292
|
getHyperbridgeAddress() {
|
|
5285
5293
|
return hyperbridgeAddress;
|
|
5286
5294
|
}
|
|
@@ -7101,6 +7109,16 @@ var ExpectedError = class _ExpectedError extends Error {
|
|
|
7101
7109
|
return error instanceof _ExpectedError;
|
|
7102
7110
|
}
|
|
7103
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
|
+
};
|
|
7104
7122
|
|
|
7105
7123
|
// src/configs/constants.ts
|
|
7106
7124
|
var ISMP_PREFIX = ":child_storage:default:ISMPv2";
|
|
@@ -7414,8 +7432,15 @@ var SubstrateChain = class _SubstrateChain {
|
|
|
7414
7432
|
id: stateMachineId,
|
|
7415
7433
|
height: Number(stateMachineHeight.height)
|
|
7416
7434
|
};
|
|
7417
|
-
|
|
7418
|
-
|
|
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
|
+
}
|
|
7419
7444
|
}
|
|
7420
7445
|
/**
|
|
7421
7446
|
* Get the challenge period for a given state machine id.
|
|
@@ -8161,26 +8186,76 @@ var IntentsCoprocessor = class _IntentsCoprocessor {
|
|
|
8161
8186
|
};
|
|
8162
8187
|
}
|
|
8163
8188
|
/**
|
|
8164
|
-
*
|
|
8165
|
-
|
|
8166
|
-
|
|
8167
|
-
|
|
8168
|
-
|
|
8169
|
-
const
|
|
8170
|
-
|
|
8171
|
-
|
|
8172
|
-
|
|
8173
|
-
|
|
8174
|
-
|
|
8175
|
-
|
|
8176
|
-
|
|
8177
|
-
|
|
8178
|
-
|
|
8179
|
-
|
|
8180
|
-
|
|
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;
|
|
8181
8251
|
}
|
|
8182
|
-
}
|
|
8183
|
-
|
|
8252
|
+
};
|
|
8253
|
+
void tick();
|
|
8254
|
+
const timer = setInterval(() => void tick(), intervalMs);
|
|
8255
|
+
return () => {
|
|
8256
|
+
stopped = true;
|
|
8257
|
+
clearInterval(timer);
|
|
8258
|
+
};
|
|
8184
8259
|
}
|
|
8185
8260
|
};
|
|
8186
8261
|
var TronChain = class _TronChain {
|
|
@@ -9313,7 +9388,12 @@ function sleep(ms) {
|
|
|
9313
9388
|
async function waitForChallengePeriod(chain, stateMachineHeight) {
|
|
9314
9389
|
const challengePeriod = await chain.challengePeriod(stateMachineHeight.id);
|
|
9315
9390
|
if (challengePeriod === BigInt(0)) return;
|
|
9316
|
-
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
|
+
});
|
|
9317
9397
|
let currentTimestamp = await chain.timestamp();
|
|
9318
9398
|
let timeElapsed = currentTimestamp - updateTime;
|
|
9319
9399
|
if (timeElapsed > challengePeriod) return;
|
|
@@ -9460,6 +9540,10 @@ function normalizeAddressForEvmBytes32(address) {
|
|
|
9460
9540
|
if (address.length === 66) return address;
|
|
9461
9541
|
return bytes20ToBytes32(address);
|
|
9462
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
|
+
}
|
|
9463
9547
|
function normalizeAddressForStateMachine(address, stateMachineId) {
|
|
9464
9548
|
return isEvmChain(normalizeStateMachineId(stateMachineId)) ? normalizeAddressForEvmBytes32(address) : address;
|
|
9465
9549
|
}
|
|
@@ -9467,14 +9551,16 @@ var DEFAULT_LOGGER = createConsola({
|
|
|
9467
9551
|
level: LogLevels.silent
|
|
9468
9552
|
});
|
|
9469
9553
|
async function retryPromise(operation, retryConfig) {
|
|
9470
|
-
const { logger = DEFAULT_LOGGER, logMessage = "Retry operation failed" } = retryConfig;
|
|
9554
|
+
const { logger = DEFAULT_LOGGER, logMessage = "Retry operation failed", shouldRetry } = retryConfig;
|
|
9471
9555
|
let lastError;
|
|
9472
9556
|
for (let i = 0; i < retryConfig.maxRetries; i++) {
|
|
9473
9557
|
try {
|
|
9474
9558
|
return await operation();
|
|
9475
9559
|
} catch (error) {
|
|
9560
|
+
if (shouldRetry && !shouldRetry(error)) throw error;
|
|
9476
9561
|
logger.trace(`Retrying(${i}) > ${logMessage}`);
|
|
9477
9562
|
lastError = error;
|
|
9563
|
+
if (i === retryConfig.maxRetries - 1) break;
|
|
9478
9564
|
await new Promise((resolve) => setTimeout(resolve, retryConfig.backoffMs * 2 ** i));
|
|
9479
9565
|
}
|
|
9480
9566
|
}
|
|
@@ -11545,6 +11631,55 @@ query LatestPhantomOrderPriceSnapshot($tokenA: String!, $tokenB: String!) {
|
|
|
11545
11631
|
}
|
|
11546
11632
|
}
|
|
11547
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
|
+
}`;
|
|
11548
11683
|
var TOKEN_GATEWAY_ASSET_TELEPORTED_STATUS = `
|
|
11549
11684
|
query TokenGatewayAssetTeleportedStatus($commitment: String!) {
|
|
11550
11685
|
tokenGatewayAssetTeleportedV2s(
|
|
@@ -12139,6 +12274,7 @@ function createCancellationStorage(options = {}) {
|
|
|
12139
12274
|
const decoded = decodeIProof(value);
|
|
12140
12275
|
return decoded;
|
|
12141
12276
|
}
|
|
12277
|
+
if (key2.includes("postCommitment")) return value;
|
|
12142
12278
|
throw new Error(`Unknown storage key type: ${key2}`);
|
|
12143
12279
|
};
|
|
12144
12280
|
const setItem = async (key2, value) => {
|
|
@@ -12152,6 +12288,10 @@ function createCancellationStorage(options = {}) {
|
|
|
12152
12288
|
await baseStorage.setItem(key2, encoded);
|
|
12153
12289
|
return;
|
|
12154
12290
|
}
|
|
12291
|
+
if (key2.includes("postCommitment") && typeof value === "string") {
|
|
12292
|
+
await baseStorage.setItem(key2, value);
|
|
12293
|
+
return;
|
|
12294
|
+
}
|
|
12155
12295
|
throw new Error(`Unknown storage key type: ${key2}`);
|
|
12156
12296
|
};
|
|
12157
12297
|
const removeItem = async (key2) => {
|
|
@@ -12165,11 +12305,25 @@ function createCancellationStorage(options = {}) {
|
|
|
12165
12305
|
});
|
|
12166
12306
|
}
|
|
12167
12307
|
var STORAGE_KEYS = Object.freeze({
|
|
12168
|
-
destProof: (orderId) => `cancel-order:${orderId}:destProof`,
|
|
12169
|
-
getRequest: (orderId) => `cancel-order:${orderId}:getRequest`,
|
|
12170
|
-
sourceProof: (orderId) => `cancel-order:${orderId}:sourceProof`,
|
|
12171
|
-
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`
|
|
12172
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
|
+
}
|
|
12173
12327
|
function createUsedUserOpsStorage(options = {}) {
|
|
12174
12328
|
const key = options.env ?? detectEnvironment();
|
|
12175
12329
|
const driver = loadDriver({ key}) ?? inMemoryDriver();
|
|
@@ -15335,6 +15489,29 @@ async function convertFeeTokenToWei(ctx, feeTokenAmount, feeTokenIn, evmChainID)
|
|
|
15335
15489
|
}
|
|
15336
15490
|
|
|
15337
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
|
+
}
|
|
15338
15515
|
var OrderPlacer = class {
|
|
15339
15516
|
/**
|
|
15340
15517
|
* @param ctx - Shared IntentsV2 context providing the source chain client,
|
|
@@ -15351,17 +15528,16 @@ var OrderPlacer = class {
|
|
|
15351
15528
|
* 1. Yields `{ to, data, sessionPrivateKey }` — the caller must sign a
|
|
15352
15529
|
* transaction sending `data` to `to` and pass the signed transaction back
|
|
15353
15530
|
* via `gen.next(signedTx)`.
|
|
15354
|
-
* 2. Returns `{ order, transactionHash }` — the finalized order
|
|
15355
|
-
*
|
|
15356
|
-
* 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.
|
|
15357
15534
|
*
|
|
15358
15535
|
* A fresh ephemeral session key is generated for every call. The key is
|
|
15359
15536
|
* stored immediately (without a commitment) so it can be retrieved by
|
|
15360
15537
|
* address, then updated with the commitment once the `OrderPlaced` event
|
|
15361
|
-
* confirms the
|
|
15538
|
+
* confirms the canonical order.
|
|
15362
15539
|
*
|
|
15363
|
-
* @param order - The order to place.
|
|
15364
|
-
* with the generated session key address before yielding.
|
|
15540
|
+
* @param order - The order to place. It is not mutated.
|
|
15365
15541
|
* @param graffiti - Optional bytes32 tag for orderflow attribution /
|
|
15366
15542
|
* revenue share. Defaults to {@link DEFAULT_GRAFFITI} (bytes32 zero).
|
|
15367
15543
|
* @yields `{ to, data, sessionPrivateKey }` — target contract address,
|
|
@@ -15376,7 +15552,7 @@ var OrderPlacer = class {
|
|
|
15376
15552
|
const account = privateKeyToAccount(privateKey);
|
|
15377
15553
|
const sessionKeyAddress = account.address;
|
|
15378
15554
|
const createdAt = Date.now();
|
|
15379
|
-
order
|
|
15555
|
+
const placementOrder = { ...order, session: sessionKeyAddress };
|
|
15380
15556
|
await this.ctx.sessionKeyStorage.setSessionKeyByAddress(sessionKeyAddress, {
|
|
15381
15557
|
privateKey,
|
|
15382
15558
|
address: sessionKeyAddress,
|
|
@@ -15385,7 +15561,7 @@ var OrderPlacer = class {
|
|
|
15385
15561
|
const data = encodeFunctionData({
|
|
15386
15562
|
abi: ABI3,
|
|
15387
15563
|
functionName: "placeOrder",
|
|
15388
|
-
args: [transformOrderForContract(
|
|
15564
|
+
args: [transformOrderForContract(placementOrder), graffiti]
|
|
15389
15565
|
});
|
|
15390
15566
|
const intentGatewayAddress = this.ctx.source.configService.getIntentGatewayAddress(
|
|
15391
15567
|
normalizeStateMachineId(order.source)
|
|
@@ -15405,20 +15581,15 @@ var OrderPlacer = class {
|
|
|
15405
15581
|
if (!orderPlacedEvent) {
|
|
15406
15582
|
throw new Error("OrderPlaced event not found in transaction receipt");
|
|
15407
15583
|
}
|
|
15408
|
-
|
|
15409
|
-
order.inputs = orderPlacedEvent.args.inputs.map((input) => ({
|
|
15410
|
-
token: input.token,
|
|
15411
|
-
amount: input.amount
|
|
15412
|
-
}));
|
|
15413
|
-
order.id = orderCommitment(order);
|
|
15584
|
+
const finalizedOrder = deriveCanonicalPlacedOrder(placementOrder, orderPlacedEvent.args);
|
|
15414
15585
|
const sessionKeyData = {
|
|
15415
15586
|
privateKey,
|
|
15416
15587
|
address: sessionKeyAddress,
|
|
15417
|
-
commitment:
|
|
15588
|
+
commitment: finalizedOrder.id,
|
|
15418
15589
|
createdAt
|
|
15419
15590
|
};
|
|
15420
15591
|
await this.ctx.sessionKeyStorage.setSessionKeyByAddress(sessionKeyAddress, sessionKeyData);
|
|
15421
|
-
return { order, receipt };
|
|
15592
|
+
return { order: finalizedOrder, receipt };
|
|
15422
15593
|
}
|
|
15423
15594
|
};
|
|
15424
15595
|
|
|
@@ -15748,7 +15919,7 @@ var OrderExecutor = class {
|
|
|
15748
15919
|
}
|
|
15749
15920
|
}
|
|
15750
15921
|
};
|
|
15751
|
-
var OrderCanceller = class {
|
|
15922
|
+
var OrderCanceller = class _OrderCanceller {
|
|
15752
15923
|
/**
|
|
15753
15924
|
* @param ctx - Shared IntentsV2 context providing the source and destination
|
|
15754
15925
|
* chain clients, config service, and cancellation storage.
|
|
@@ -15757,6 +15928,9 @@ var OrderCanceller = class {
|
|
|
15757
15928
|
this.ctx = ctx;
|
|
15758
15929
|
}
|
|
15759
15930
|
ctx;
|
|
15931
|
+
static DEFAULT_MAX_RECOVERY_RESTARTS = 1;
|
|
15932
|
+
static PROOF_FRESHNESS_MAX_RETRIES = 3;
|
|
15933
|
+
static PROOF_FRESHNESS_BACKOFF_MS = 500;
|
|
15760
15934
|
logger = createConsola({
|
|
15761
15935
|
level: LogLevels.info,
|
|
15762
15936
|
formatOptions: { columns: 80, colors: true, compact: true, date: false }
|
|
@@ -15788,11 +15962,14 @@ var OrderCanceller = class {
|
|
|
15788
15962
|
* @returns The native token dispatch fee in wei.
|
|
15789
15963
|
*/
|
|
15790
15964
|
async quoteCancelFromSource(order) {
|
|
15791
|
-
if (order.source === order.destination) return { nativeValue: 0n, relayerFee: 0n };
|
|
15792
15965
|
const sourceStateMachine = normalizeStateMachineId(order.source);
|
|
15966
|
+
const destStateMachine = normalizeStateMachineId(order.destination);
|
|
15967
|
+
if (sourceStateMachine === destStateMachine) {
|
|
15968
|
+
return { nativeValue: 0n, relayerFee: 0n };
|
|
15969
|
+
}
|
|
15793
15970
|
const height = order.deadline + 1n;
|
|
15794
15971
|
const destIntentGateway = this.ctx.dest.configService.getIntentGatewayAddress(
|
|
15795
|
-
|
|
15972
|
+
destStateMachine
|
|
15796
15973
|
);
|
|
15797
15974
|
const slotHash = await this.ctx.dest.client.readContract({
|
|
15798
15975
|
abi: ABI3,
|
|
@@ -15804,8 +15981,8 @@ var OrderCanceller = class {
|
|
|
15804
15981
|
const context = encodeWithdrawalRequest(order, order.user);
|
|
15805
15982
|
const getRequest = {
|
|
15806
15983
|
source: sourceStateMachine,
|
|
15807
|
-
dest:
|
|
15808
|
-
from: this.ctx.source.configService.getIntentGatewayAddress(
|
|
15984
|
+
dest: destStateMachine,
|
|
15985
|
+
from: this.ctx.source.configService.getIntentGatewayAddress(destStateMachine),
|
|
15809
15986
|
nonce: await this.ctx.source.getHostNonce(),
|
|
15810
15987
|
height,
|
|
15811
15988
|
keys: [key],
|
|
@@ -15822,7 +15999,9 @@ var OrderCanceller = class {
|
|
|
15822
15999
|
* cancellation is complete.
|
|
15823
16000
|
*
|
|
15824
16001
|
* Delegates to `cancelOrderFromSource` or `cancelOrderFromDest` based on
|
|
15825
|
-
* 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.
|
|
15826
16005
|
*
|
|
15827
16006
|
* @param order - The order to cancel.
|
|
15828
16007
|
* @param indexerClient - Indexer client used to stream ISMP request status
|
|
@@ -15832,12 +16011,32 @@ var OrderCanceller = class {
|
|
|
15832
16011
|
* cancellation lifecycle.
|
|
15833
16012
|
*/
|
|
15834
16013
|
async *cancelOrder(order, indexerClient, options = {}) {
|
|
15835
|
-
const
|
|
16014
|
+
const sourceStateMachine = normalizeStateMachineId(order.source);
|
|
16015
|
+
const destStateMachine = normalizeStateMachineId(order.destination);
|
|
16016
|
+
const isSameChain = sourceStateMachine === destStateMachine;
|
|
15836
16017
|
if (options.from === "destination" && !isSameChain) {
|
|
15837
16018
|
yield* this.cancelOrderFromDest(order, indexerClient);
|
|
15838
16019
|
return;
|
|
15839
16020
|
}
|
|
15840
|
-
|
|
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
|
+
}
|
|
15841
16040
|
}
|
|
15842
16041
|
/**
|
|
15843
16042
|
* Async generator that cancels an order by initiating the cancel from the
|
|
@@ -15863,11 +16062,10 @@ var OrderCanceller = class {
|
|
|
15863
16062
|
* @throws If the cancel transaction does not contain the expected on-chain event.
|
|
15864
16063
|
*/
|
|
15865
16064
|
async *cancelOrderFromSource(order, indexerClient) {
|
|
15866
|
-
const
|
|
15867
|
-
const
|
|
15868
|
-
const
|
|
15869
|
-
|
|
15870
|
-
);
|
|
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);
|
|
15871
16069
|
if (isSameChain) {
|
|
15872
16070
|
const data = encodeFunctionData({
|
|
15873
16071
|
abi: ABI3,
|
|
@@ -15896,18 +16094,37 @@ var OrderCanceller = class {
|
|
|
15896
16094
|
};
|
|
15897
16095
|
return;
|
|
15898
16096
|
}
|
|
16097
|
+
const storageKeys = this.recoveryStorageKeys(order);
|
|
16098
|
+
const legacyStorageKeys = this.legacyRecoveryStorageKeys(order);
|
|
15899
16099
|
const hyperbridge = indexerClient.hyperbridge;
|
|
15900
|
-
const sourceStateMachine = normalizeStateMachineId(order.source);
|
|
15901
16100
|
const sourceConsensusStateId = this.ctx.source.configService.getConsensusStateId(sourceStateMachine);
|
|
15902
|
-
let destIProof = await this.
|
|
16101
|
+
let destIProof = await this.getRecoveryItem(
|
|
16102
|
+
storageKeys.destProof,
|
|
16103
|
+
legacyStorageKeys.map((keys) => keys.destProof)
|
|
16104
|
+
);
|
|
15903
16105
|
if (!destIProof) {
|
|
15904
16106
|
destIProof = yield* this.fetchDestinationProof(order, indexerClient);
|
|
15905
|
-
await this.ctx.cancellationStorage.setItem(
|
|
16107
|
+
await this.ctx.cancellationStorage.setItem(storageKeys.destProof, destIProof);
|
|
15906
16108
|
} else {
|
|
15907
|
-
|
|
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 };
|
|
15908
16123
|
}
|
|
15909
|
-
|
|
15910
|
-
|
|
16124
|
+
await this.assertProofFresh(hyperbridge, destIProof);
|
|
16125
|
+
let getRequest = await this.getRecoveryItem(
|
|
16126
|
+
storageKeys.getRequest,
|
|
16127
|
+
legacyStorageKeys.map((keys) => keys.getRequest)
|
|
15911
16128
|
);
|
|
15912
16129
|
if (!getRequest) {
|
|
15913
16130
|
const quote = await this.quoteCancelFromSource(order);
|
|
@@ -15927,7 +16144,7 @@ var OrderCanceller = class {
|
|
|
15927
16144
|
const request = events.find((e) => e.eventName === "GetRequestEvent");
|
|
15928
16145
|
if (!request) throw new Error("GetRequest missing");
|
|
15929
16146
|
getRequest = request.args;
|
|
15930
|
-
await this.ctx.cancellationStorage.setItem(
|
|
16147
|
+
await this.ctx.cancellationStorage.setItem(storageKeys.getRequest, getRequest);
|
|
15931
16148
|
yield {
|
|
15932
16149
|
status: "CANCEL_STARTED",
|
|
15933
16150
|
receipt
|
|
@@ -15946,8 +16163,9 @@ var OrderCanceller = class {
|
|
|
15946
16163
|
metadata: statusUpdate.metadata
|
|
15947
16164
|
};
|
|
15948
16165
|
const sourceHeight = BigInt(statusUpdate.metadata.blockNumber);
|
|
15949
|
-
let sourceIProof = await this.
|
|
15950
|
-
|
|
16166
|
+
let sourceIProof = await this.getRecoveryItem(
|
|
16167
|
+
storageKeys.sourceProof,
|
|
16168
|
+
legacyStorageKeys.map((keys) => keys.sourceProof)
|
|
15951
16169
|
);
|
|
15952
16170
|
if (!sourceIProof) {
|
|
15953
16171
|
sourceIProof = await fetchSourceProof(
|
|
@@ -15957,8 +16175,9 @@ var OrderCanceller = class {
|
|
|
15957
16175
|
sourceConsensusStateId,
|
|
15958
16176
|
sourceHeight
|
|
15959
16177
|
);
|
|
15960
|
-
await this.ctx.cancellationStorage.setItem(
|
|
16178
|
+
await this.ctx.cancellationStorage.setItem(storageKeys.sourceProof, sourceIProof);
|
|
15961
16179
|
}
|
|
16180
|
+
await this.assertProofFresh(hyperbridge, sourceIProof);
|
|
15962
16181
|
await waitForChallengePeriod(hyperbridge, {
|
|
15963
16182
|
height: sourceIProof.height,
|
|
15964
16183
|
id: {
|
|
@@ -15966,6 +16185,10 @@ var OrderCanceller = class {
|
|
|
15966
16185
|
consensusStateId: sourceConsensusStateId
|
|
15967
16186
|
}
|
|
15968
16187
|
});
|
|
16188
|
+
await Promise.all([
|
|
16189
|
+
this.assertProofFresh(hyperbridge, sourceIProof),
|
|
16190
|
+
this.assertProofFresh(hyperbridge, destIProof)
|
|
16191
|
+
]);
|
|
15969
16192
|
const getRequestMessage = {
|
|
15970
16193
|
kind: "GetRequest",
|
|
15971
16194
|
requests: [getRequest],
|
|
@@ -15987,9 +16210,12 @@ var OrderCanceller = class {
|
|
|
15987
16210
|
status: "HYPERBRIDGE_FINALIZED",
|
|
15988
16211
|
metadata: statusUpdate.metadata
|
|
15989
16212
|
};
|
|
15990
|
-
await this.
|
|
15991
|
-
|
|
15992
|
-
|
|
16213
|
+
await this.removeRecoveryItems(
|
|
16214
|
+
storageKeys.destProof,
|
|
16215
|
+
storageKeys.getRequest,
|
|
16216
|
+
storageKeys.sourceProof,
|
|
16217
|
+
...legacyStorageKeys.flatMap((keys) => [keys.destProof, keys.getRequest, keys.sourceProof])
|
|
16218
|
+
);
|
|
15993
16219
|
return;
|
|
15994
16220
|
}
|
|
15995
16221
|
}
|
|
@@ -16006,9 +16232,11 @@ var OrderCanceller = class {
|
|
|
16006
16232
|
* @returns The native token dispatch fee in wei.
|
|
16007
16233
|
*/
|
|
16008
16234
|
async quoteCancelFromDest(order) {
|
|
16009
|
-
if (order.source === order.destination) return { nativeValue: 0n, relayerFee: 0n };
|
|
16010
|
-
const destStateMachine = normalizeStateMachineId(order.destination);
|
|
16011
16235
|
const sourceStateMachine = normalizeStateMachineId(order.source);
|
|
16236
|
+
const destStateMachine = normalizeStateMachineId(order.destination);
|
|
16237
|
+
if (sourceStateMachine === destStateMachine) {
|
|
16238
|
+
return { nativeValue: 0n, relayerFee: 0n };
|
|
16239
|
+
}
|
|
16012
16240
|
const destIntentGateway = this.ctx.dest.configService.getIntentGatewayAddress(destStateMachine);
|
|
16013
16241
|
const sourceIntentGateway = this.ctx.source.configService.getIntentGatewayAddress(sourceStateMachine);
|
|
16014
16242
|
const relayerFee = await this.estimateRelayerFee(sourceStateMachine, destStateMachine);
|
|
@@ -16046,11 +16274,13 @@ var OrderCanceller = class {
|
|
|
16046
16274
|
* @throws If the cancel transaction does not contain a `PostRequestEvent`.
|
|
16047
16275
|
*/
|
|
16048
16276
|
async *cancelOrderFromDest(order, indexerClient) {
|
|
16049
|
-
const
|
|
16277
|
+
const storageKeys = this.recoveryStorageKeys(order);
|
|
16050
16278
|
const destStateMachine = normalizeStateMachineId(order.destination);
|
|
16051
16279
|
const intentGatewayAddress = this.ctx.dest.configService.getIntentGatewayAddress(destStateMachine);
|
|
16052
|
-
|
|
16053
|
-
|
|
16280
|
+
const legacyStorageKeys = this.legacyRecoveryStorageKeys(order);
|
|
16281
|
+
let commitment = await this.getRecoveryItem(
|
|
16282
|
+
storageKeys.postCommitment,
|
|
16283
|
+
legacyStorageKeys.map((keys) => keys.postCommitment)
|
|
16054
16284
|
);
|
|
16055
16285
|
if (!commitment) {
|
|
16056
16286
|
const quote = await this.quoteCancelFromDest(order);
|
|
@@ -16075,7 +16305,7 @@ var OrderCanceller = class {
|
|
|
16075
16305
|
if (!postEvent) throw new Error("PostRequestEvent not found in cancel transaction receipt");
|
|
16076
16306
|
const postArgs = postEvent.args;
|
|
16077
16307
|
commitment = postRequestCommitment(postArgs).commitment;
|
|
16078
|
-
await this.ctx.cancellationStorage.setItem(
|
|
16308
|
+
await this.ctx.cancellationStorage.setItem(storageKeys.postCommitment, commitment);
|
|
16079
16309
|
}
|
|
16080
16310
|
const statusStream = indexerClient.postRequestStatusStream(commitment);
|
|
16081
16311
|
for await (const statusUpdate of statusStream) {
|
|
@@ -16109,7 +16339,10 @@ var OrderCanceller = class {
|
|
|
16109
16339
|
if (refundEvents.length === 0) {
|
|
16110
16340
|
throw new Error("EscrowRefunded event not found in source-chain delivery receipt");
|
|
16111
16341
|
}
|
|
16112
|
-
await this.
|
|
16342
|
+
await this.removeRecoveryItems(
|
|
16343
|
+
storageKeys.postCommitment,
|
|
16344
|
+
...legacyStorageKeys.map((keys) => keys.postCommitment)
|
|
16345
|
+
);
|
|
16113
16346
|
yield {
|
|
16114
16347
|
status: "CANCELLATION_COMPLETE",
|
|
16115
16348
|
blockNumber: statusUpdate.metadata.blockNumber,
|
|
@@ -16152,7 +16385,7 @@ var OrderCanceller = class {
|
|
|
16152
16385
|
const intentGatewayV2Address = this.ctx.dest.configService.getIntentGatewayAddress(
|
|
16153
16386
|
this.ctx.dest.config.stateMachineId
|
|
16154
16387
|
);
|
|
16155
|
-
const orderId = order
|
|
16388
|
+
const orderId = this.orderId(order);
|
|
16156
16389
|
const slotHash = await this.ctx.dest.client.readContract({
|
|
16157
16390
|
abi: ABI3,
|
|
16158
16391
|
address: intentGatewayV2Address,
|
|
@@ -16169,6 +16402,7 @@ var OrderCanceller = class {
|
|
|
16169
16402
|
yield { status: "DESTINATION_FINALIZED", proof };
|
|
16170
16403
|
return proof;
|
|
16171
16404
|
} catch (e) {
|
|
16405
|
+
if (MissingConsensusUpdateTimeError.isError(e)) throw e;
|
|
16172
16406
|
lastFailedHeight = latestHeight;
|
|
16173
16407
|
await sleep(1e4);
|
|
16174
16408
|
}
|
|
@@ -16199,6 +16433,7 @@ var OrderCanceller = class {
|
|
|
16199
16433
|
this.logger.info(`Unsigned GET ${commitment} submitted; waiting for Hyperbridge response receipt`);
|
|
16200
16434
|
await sleep(3e4);
|
|
16201
16435
|
} catch (error) {
|
|
16436
|
+
if (MissingConsensusUpdateTimeError.isError(error)) throw error;
|
|
16202
16437
|
this.logger.warn(
|
|
16203
16438
|
`Unsigned GET submit failed for ${commitment}; polling response receipt before failing: ${String(error)}`
|
|
16204
16439
|
);
|
|
@@ -16207,14 +16442,128 @@ var OrderCanceller = class {
|
|
|
16207
16442
|
await this.pollDeliveredReceipt(hyperbridge, commitment);
|
|
16208
16443
|
this.logger.info(`Confirmed Hyperbridge GET delivery for ${commitment}`);
|
|
16209
16444
|
} catch (error) {
|
|
16445
|
+
if (MissingConsensusUpdateTimeError.isError(error)) throw error;
|
|
16210
16446
|
const message2 = `Failed to deliver GET request to Hyperbridge; no response receipt found for ${commitment}: ${String(error)}`;
|
|
16211
16447
|
this.logger.error(message2);
|
|
16212
16448
|
throw new Error(message2);
|
|
16213
16449
|
}
|
|
16214
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
|
+
*/
|
|
16215
16556
|
async queryDeliveredReceipt(hyperbridge, commitment) {
|
|
16216
16557
|
return hyperbridge.queryResponseReceipt(commitment);
|
|
16217
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
|
+
*/
|
|
16218
16567
|
async pollDeliveredReceipt(hyperbridge, commitment) {
|
|
16219
16568
|
this.logger.info(`Polling Hyperbridge GET response receipt for ${commitment}`);
|
|
16220
16569
|
return retryPromise(
|
|
@@ -17427,6 +17776,178 @@ var OrderStatusChecker = class {
|
|
|
17427
17776
|
return true;
|
|
17428
17777
|
}
|
|
17429
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
|
+
}
|
|
17430
17951
|
|
|
17431
17952
|
// src/protocols/intents/quote/types.ts
|
|
17432
17953
|
var UnsupportedIntentQuoteStrategyError = class extends Error {
|
|
@@ -17713,12 +18234,14 @@ var PhantomSnapshotIntentQuoteStrategy = class {
|
|
|
17713
18234
|
constructor(chainConfigService, getQueryClient) {
|
|
17714
18235
|
this.chainConfigService = chainConfigService;
|
|
17715
18236
|
this.getQueryClient = getQueryClient;
|
|
18237
|
+
this.pairResolver = new PhantomSnapshotPairResolver(chainConfigService);
|
|
17716
18238
|
}
|
|
17717
18239
|
chainConfigService;
|
|
17718
18240
|
getQueryClient;
|
|
18241
|
+
pairResolver;
|
|
17719
18242
|
async quote(params, source, destination) {
|
|
17720
18243
|
validateQuoteParams(params);
|
|
17721
|
-
const pair = this.
|
|
18244
|
+
const pair = this.pairResolver.resolve(params, source.stateMachineId, destination.stateMachineId);
|
|
17722
18245
|
if (!pair) {
|
|
17723
18246
|
throw new UnsupportedIntentQuotePairError({
|
|
17724
18247
|
source: source.stateMachineId,
|
|
@@ -17791,7 +18314,13 @@ var PhantomSnapshotIntentQuoteStrategy = class {
|
|
|
17791
18314
|
throw new InvalidPhantomSnapshotError(snapshot.commitment, "snapshotTime is invalid");
|
|
17792
18315
|
}
|
|
17793
18316
|
}
|
|
17794
|
-
|
|
18317
|
+
};
|
|
18318
|
+
var PhantomSnapshotPairResolver = class {
|
|
18319
|
+
constructor(chainConfigService) {
|
|
18320
|
+
this.chainConfigService = chainConfigService;
|
|
18321
|
+
}
|
|
18322
|
+
chainConfigService;
|
|
18323
|
+
resolve(params, sourceStateMachineId, destinationStateMachineId) {
|
|
17795
18324
|
const tokenIn = this.resolveBaseSnapshotToken(sourceStateMachineId, params.tokenIn);
|
|
17796
18325
|
const tokenOut = this.resolveBaseSnapshotToken(destinationStateMachineId, params.tokenOut);
|
|
17797
18326
|
if (!tokenIn || !tokenOut || !isSupportedSnapshotPair(tokenIn.symbol, tokenOut.symbol)) return;
|
|
@@ -17843,6 +18372,8 @@ var IntentGateway = class _IntentGateway {
|
|
|
17843
18372
|
gasEstimator;
|
|
17844
18373
|
/** Quote strategies for pricing orders before placement, keyed by strategy name. */
|
|
17845
18374
|
quoteStrategies;
|
|
18375
|
+
/** Resolves order tokens to canonical Phantom snapshot market pairs. */
|
|
18376
|
+
phantomSnapshotPairResolver;
|
|
17846
18377
|
/**
|
|
17847
18378
|
* Private constructor — use {@link IntentGateway.create} instead.
|
|
17848
18379
|
*
|
|
@@ -17886,6 +18417,7 @@ var IntentGateway = class _IntentGateway {
|
|
|
17886
18417
|
this.bidManager = bidManager;
|
|
17887
18418
|
this.gasEstimator = gasEstimator;
|
|
17888
18419
|
this._crypto = crypto;
|
|
18420
|
+
this.phantomSnapshotPairResolver = new PhantomSnapshotPairResolver(dest.configService);
|
|
17889
18421
|
this.quoteStrategies = {
|
|
17890
18422
|
phantom_snapshot: new PhantomSnapshotIntentQuoteStrategy(
|
|
17891
18423
|
dest.configService,
|
|
@@ -17964,13 +18496,43 @@ var IntentGateway = class _IntentGateway {
|
|
|
17964
18496
|
if (!handler) throw new UnsupportedIntentQuoteStrategyError(strategy);
|
|
17965
18497
|
return handler.quote({ ...params, strategy }, source, destination);
|
|
17966
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
|
+
});
|
|
18528
|
+
}
|
|
17967
18529
|
/**
|
|
17968
18530
|
* Bidirectional async generator that orchestrates the full order lifecycle:
|
|
17969
18531
|
* placement, fee estimation, bid collection, and execution.
|
|
17970
18532
|
*
|
|
17971
18533
|
* **Yield/receive protocol:**
|
|
17972
|
-
* 1. If `order.fees` is unset or zero, estimates gas and sets
|
|
17973
|
-
*
|
|
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
|
|
17974
18536
|
* and include an additional 600k-gas fee uplift, while the wei cost used for
|
|
17975
18537
|
* the `value` field receives a 2% buffer.
|
|
17976
18538
|
* 2. Yields `AWAITING_PLACE_ORDER` with `{ to, data, value, sessionPrivateKey }`.
|
|
@@ -17980,8 +18542,8 @@ var IntentGateway = class _IntentGateway {
|
|
|
17980
18542
|
* 4. Delegates to {@link OrderExecutor.executeOrder} and forwards all
|
|
17981
18543
|
* subsequent status updates until the order is filled, exhausted, or fails.
|
|
17982
18544
|
*
|
|
17983
|
-
* @param order - The order to place and execute. `order.fees`
|
|
17984
|
-
*
|
|
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.
|
|
17985
18547
|
* @param graffiti - Optional bytes32 tag for orderflow attribution /
|
|
17986
18548
|
* revenue share. Defaults to {@link DEFAULT_GRAFFITI}.
|
|
17987
18549
|
* @param options - Optional tuning parameters:
|
|
@@ -17994,10 +18556,11 @@ var IntentGateway = class _IntentGateway {
|
|
|
17994
18556
|
* estimation returns zero.
|
|
17995
18557
|
*/
|
|
17996
18558
|
async *execute(order, graffiti = DEFAULT_GRAFFITI, options) {
|
|
18559
|
+
const executionOrder = { ...order };
|
|
17997
18560
|
let value;
|
|
17998
|
-
if (!
|
|
18561
|
+
if (!executionOrder.fees || executionOrder.fees === 0n) {
|
|
17999
18562
|
const estimate = await this.gasEstimator.estimateFillOrder({
|
|
18000
|
-
order,
|
|
18563
|
+
order: executionOrder,
|
|
18001
18564
|
maxPriorityFeePerGasBumpPercent: options?.maxPriorityFeePerGasBumpPercent,
|
|
18002
18565
|
maxFeePerGasBumpPercent: options?.maxFeePerGasBumpPercent
|
|
18003
18566
|
});
|
|
@@ -18012,9 +18575,9 @@ var IntentGateway = class _IntentGateway {
|
|
|
18012
18575
|
"source",
|
|
18013
18576
|
this.source.config.stateMachineId
|
|
18014
18577
|
);
|
|
18015
|
-
|
|
18578
|
+
executionOrder.fees = isSameChain ? estimate.totalGasInFeeToken * 2n : estimate.totalGasInFeeToken + (crossChainFeeBump + estimate.totalGasInFeeToken * 1n / 100n);
|
|
18016
18579
|
}
|
|
18017
|
-
const placeOrderGen = this.orderPlacer.placeOrder(
|
|
18580
|
+
const placeOrderGen = this.orderPlacer.placeOrder(executionOrder, graffiti);
|
|
18018
18581
|
const placeOrderFirst = await placeOrderGen.next();
|
|
18019
18582
|
if (placeOrderFirst.done) {
|
|
18020
18583
|
throw new Error("placeOrder generator completed without yielding");
|
|
@@ -18125,13 +18688,20 @@ var IntentGateway = class _IntentGateway {
|
|
|
18125
18688
|
const gen = this.execute(order, graffiti, options);
|
|
18126
18689
|
try {
|
|
18127
18690
|
let input;
|
|
18691
|
+
let finalizedOrder;
|
|
18128
18692
|
while (true) {
|
|
18129
18693
|
const { value, done } = await gen.next(input);
|
|
18130
18694
|
input = void 0;
|
|
18131
18695
|
if (done) break;
|
|
18132
|
-
if (value.status === "
|
|
18696
|
+
if (value.status === "ORDER_PLACED") {
|
|
18697
|
+
finalizedOrder = value.order;
|
|
18133
18698
|
yield value;
|
|
18134
|
-
|
|
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);
|
|
18135
18705
|
} else if (value.status === "AWAITING_PLACE_ORDER") {
|
|
18136
18706
|
input = yield value;
|
|
18137
18707
|
} else {
|
|
@@ -22909,6 +23479,6 @@ async function teleportDot(param_) {
|
|
|
22909
23479
|
return stream;
|
|
22910
23480
|
}
|
|
22911
23481
|
|
|
22912
|
-
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, 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 };
|
|
22913
23483
|
//# sourceMappingURL=index.js.map
|
|
22914
23484
|
//# sourceMappingURL=index.js.map
|