@pushchain/core 5.1.3 → 5.1.4-alpha.1
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/package.json +29 -6
- package/src/lib/constants/abi/prc20.evm.d.ts +22 -2
- package/src/lib/constants/abi/prc20.evm.js +11 -3
- package/src/lib/constants/abi/universalGatewayPC.evm.d.ts +59 -0
- package/src/lib/constants/abi/universalGatewayPC.evm.js +26 -0
- package/src/lib/constants/chain.d.ts +4 -0
- package/src/lib/constants/chain.js +6 -2
- package/src/lib/index.d.ts +2 -2
- package/src/lib/internal/bs58.d.ts +2 -0
- package/src/lib/internal/bs58.js +7 -0
- package/src/lib/orchestrator/cea-utils.d.ts +0 -9
- package/src/lib/orchestrator/cea-utils.js +15 -4
- package/src/lib/orchestrator/internals/account-manager.d.ts +16 -0
- package/src/lib/orchestrator/internals/account-manager.js +191 -0
- package/src/lib/orchestrator/internals/cascade.d.ts +23 -0
- package/src/lib/orchestrator/internals/cascade.js +945 -0
- package/src/lib/orchestrator/internals/confirmation.d.ts +9 -0
- package/src/lib/orchestrator/internals/confirmation.js +123 -0
- package/src/lib/orchestrator/internals/context.d.ts +38 -0
- package/src/lib/orchestrator/internals/context.js +49 -0
- package/src/lib/orchestrator/internals/execute-funds-only.d.ts +11 -0
- package/src/lib/orchestrator/internals/execute-funds-only.js +219 -0
- package/src/lib/orchestrator/internals/execute-funds-payload.d.ts +11 -0
- package/src/lib/orchestrator/internals/execute-funds-payload.js +222 -0
- package/src/lib/orchestrator/internals/execute-standard.d.ts +13 -0
- package/src/lib/orchestrator/internals/execute-standard.js +225 -0
- package/src/lib/orchestrator/internals/gas-calculator.d.ts +38 -0
- package/src/lib/orchestrator/internals/gas-calculator.js +424 -0
- package/src/lib/orchestrator/internals/gateway-client.d.ts +24 -0
- package/src/lib/orchestrator/internals/gateway-client.js +191 -0
- package/src/lib/orchestrator/internals/helpers.d.ts +26 -0
- package/src/lib/orchestrator/internals/helpers.js +181 -0
- package/src/lib/orchestrator/internals/index.d.ts +24 -0
- package/src/lib/orchestrator/internals/index.js +132 -0
- package/src/lib/orchestrator/internals/outbound-sync.d.ts +49 -0
- package/src/lib/orchestrator/internals/outbound-sync.js +357 -0
- package/src/lib/orchestrator/internals/outbound-tracker.d.ts +8 -0
- package/src/lib/orchestrator/internals/outbound-tracker.js +64 -0
- package/src/lib/orchestrator/internals/payload-builder.d.ts +24 -0
- package/src/lib/orchestrator/internals/payload-builder.js +178 -0
- package/src/lib/orchestrator/internals/push-chain-tx.d.ts +32 -0
- package/src/lib/orchestrator/internals/push-chain-tx.js +207 -0
- package/src/lib/orchestrator/internals/quote.d.ts +9 -0
- package/src/lib/orchestrator/internals/quote.js +114 -0
- package/src/lib/orchestrator/internals/rescue.d.ts +20 -0
- package/src/lib/orchestrator/internals/rescue.js +112 -0
- package/src/lib/orchestrator/internals/response-builder.d.ts +26 -0
- package/src/lib/orchestrator/internals/response-builder.js +504 -0
- package/src/lib/orchestrator/internals/route-handlers.d.ts +77 -0
- package/src/lib/orchestrator/internals/route-handlers.js +1192 -0
- package/src/lib/orchestrator/internals/signing.d.ts +27 -0
- package/src/lib/orchestrator/internals/signing.js +258 -0
- package/src/lib/orchestrator/internals/svm-bridge.d.ts +21 -0
- package/src/lib/orchestrator/internals/svm-bridge.js +122 -0
- package/src/lib/orchestrator/internals/svm-helpers.d.ts +35 -0
- package/src/lib/orchestrator/internals/svm-helpers.js +143 -0
- package/src/lib/orchestrator/internals/tx-transformer.d.ts +12 -0
- package/src/lib/orchestrator/internals/tx-transformer.js +120 -0
- package/src/lib/orchestrator/internals/uea-manager.d.ts +17 -0
- package/src/lib/orchestrator/internals/uea-manager.js +164 -0
- package/src/lib/orchestrator/orchestrator.d.ts +33 -431
- package/src/lib/orchestrator/orchestrator.js +124 -6125
- package/src/lib/orchestrator/orchestrator.types.d.ts +11 -10
- package/src/lib/orchestrator/payload-builders.js +34 -8
- package/src/lib/price-fetch/price-fetch.js +19 -7
- package/src/lib/push-chain/push-chain.d.ts +6 -0
- package/src/lib/push-chain/push-chain.js +10 -2
- package/src/lib/push-client/push-client.d.ts +3 -0
- package/src/lib/push-client/push-client.js +21 -31
- package/src/lib/universal/account/account.d.ts +35 -16
- package/src/lib/universal/account/account.js +298 -16
- package/src/lib/universal/signer/signer.d.ts +2 -3
- package/src/lib/universal/signer/signer.js +65 -115
- package/src/lib/universal/universal.types.d.ts +41 -0
- package/src/lib/utils.d.ts +7 -2
- package/src/lib/utils.js +65 -34
- package/src/lib/vm-client/evm-client.js +3 -11
- package/src/lib/vm-client/svm-client.d.ts +0 -4
- package/src/lib/vm-client/svm-client.js +2 -8
- package/src/index.js.map +0 -1
- package/src/lib/cache/cache.js.map +0 -1
- package/src/lib/constants/abi/cea.evm.js.map +0 -1
- package/src/lib/constants/abi/ceaFactory.evm.js.map +0 -1
- package/src/lib/constants/abi/erc20.evm.js.map +0 -1
- package/src/lib/constants/abi/factoryV1.js.map +0 -1
- package/src/lib/constants/abi/feeLocker.evm.js.map +0 -1
- package/src/lib/constants/abi/index.js.map +0 -1
- package/src/lib/constants/abi/prc20.evm.js.map +0 -1
- package/src/lib/constants/abi/uea-factory.js.map +0 -1
- package/src/lib/constants/abi/uea.evm.js.map +0 -1
- package/src/lib/constants/abi/uea.svm.js.map +0 -1
- package/src/lib/constants/abi/universalGateway.evm.js.map +0 -1
- package/src/lib/constants/abi/universalGatewayPC.evm.js.map +0 -1
- package/src/lib/constants/abi/universalGatewayV0.evm.js.map +0 -1
- package/src/lib/constants/chain.js.map +0 -1
- package/src/lib/constants/enums.js.map +0 -1
- package/src/lib/constants/index.js.map +0 -1
- package/src/lib/constants/selectors.js.map +0 -1
- package/src/lib/constants/tokens.js.map +0 -1
- package/src/lib/generated/uexecutor/v1/query.js.map +0 -1
- package/src/lib/generated/uexecutor/v1/types.js.map +0 -1
- package/src/lib/generated/uexecutor/v2/index.js.map +0 -1
- package/src/lib/generated/uexecutor/v2/query.js.map +0 -1
- package/src/lib/generated/uexecutor/v2/types.js.map +0 -1
- package/src/lib/generated/v1/tx.js.map +0 -1
- package/src/lib/index.js.map +0 -1
- package/src/lib/internal/buffer.js.map +0 -1
- package/src/lib/internal/global-buffer-polyfill.js.map +0 -1
- package/src/lib/orchestrator/cea-utils.js.map +0 -1
- package/src/lib/orchestrator/orchestrator.js.map +0 -1
- package/src/lib/orchestrator/orchestrator.types.js.map +0 -1
- package/src/lib/orchestrator/payload-builders.js.map +0 -1
- package/src/lib/orchestrator/route-detector.js.map +0 -1
- package/src/lib/price-fetch/price-fetch.js.map +0 -1
- package/src/lib/progress-hook/progress-hook.js.map +0 -1
- package/src/lib/progress-hook/progress-hook.types.js.map +0 -1
- package/src/lib/push-chain/helpers/abis.js.map +0 -1
- package/src/lib/push-chain/helpers/addresses.js.map +0 -1
- package/src/lib/push-chain/push-chain.js.map +0 -1
- package/src/lib/push-client/push-client.js.map +0 -1
- package/src/lib/push-client/push-client.types.js.map +0 -1
- package/src/lib/universal/account/account.js.map +0 -1
- package/src/lib/universal/account/index.js.map +0 -1
- package/src/lib/universal/signer/index.js.map +0 -1
- package/src/lib/universal/signer/signer.js.map +0 -1
- package/src/lib/universal/signer/signer.types.js.map +0 -1
- package/src/lib/universal/universal.types.js.map +0 -1
- package/src/lib/utils.js.map +0 -1
- package/src/lib/vm-client/evm-client.js.map +0 -1
- package/src/lib/vm-client/svm-client.js.map +0 -1
- package/src/lib/vm-client/vm-client.types.js.map +0 -1
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Outbound transaction sync: polling helpers that wait for outbound
|
|
4
|
+
* transactions to complete on external chains.
|
|
5
|
+
*
|
|
6
|
+
* Extracted from Orchestrator.waitForOutboundTx / waitForAllOutboundTxsV2.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.OUTBOUND_MAX_TIMEOUT_MS = exports.OUTBOUND_POLL_INTERVAL_MS = exports.OUTBOUND_INITIAL_WAIT_MS = void 0;
|
|
10
|
+
exports.waitForOutboundTx = waitForOutboundTx;
|
|
11
|
+
exports.waitForAllOutboundTxsV2 = waitForAllOutboundTxsV2;
|
|
12
|
+
const tslib_1 = require("tslib");
|
|
13
|
+
const bs58_1 = require("../../internal/bs58");
|
|
14
|
+
const chain_1 = require("../../constants/chain");
|
|
15
|
+
const enums_1 = require("../../constants/enums");
|
|
16
|
+
const types_1 = require("../../generated/uexecutor/v1/types");
|
|
17
|
+
const types_2 = require("../../generated/uexecutor/v2/types");
|
|
18
|
+
const context_1 = require("./context");
|
|
19
|
+
const helpers_1 = require("./helpers");
|
|
20
|
+
const outbound_tracker_1 = require("./outbound-tracker");
|
|
21
|
+
// ============================================================================
|
|
22
|
+
// Outbound sync configuration constants
|
|
23
|
+
// ============================================================================
|
|
24
|
+
/** Initial wait before the first poll (ms). */
|
|
25
|
+
exports.OUTBOUND_INITIAL_WAIT_MS = 20000; // 20s
|
|
26
|
+
/** Interval between consecutive polls (ms). */
|
|
27
|
+
exports.OUTBOUND_POLL_INTERVAL_MS = 5000; // 5s
|
|
28
|
+
/** Maximum total timeout for the polling loop (ms). */
|
|
29
|
+
exports.OUTBOUND_MAX_TIMEOUT_MS = 180000; // 180s (3 min)
|
|
30
|
+
// ============================================================================
|
|
31
|
+
// waitForOutboundTx
|
|
32
|
+
// ============================================================================
|
|
33
|
+
/**
|
|
34
|
+
* Wait for outbound transaction to complete and return external chain details.
|
|
35
|
+
* @internal Used by .wait() for outbound routes - not part of public API.
|
|
36
|
+
* Uses polling with configurable initial wait, interval, and timeout.
|
|
37
|
+
*
|
|
38
|
+
* Default strategy: 30s initial wait, then poll every 5s, 120s total timeout.
|
|
39
|
+
*
|
|
40
|
+
* @param ctx - Orchestrator context
|
|
41
|
+
* @param pushChainTxHash - The Push Chain transaction hash
|
|
42
|
+
* @param options - Polling configuration options
|
|
43
|
+
* @returns External chain tx details
|
|
44
|
+
* @throws Error on timeout
|
|
45
|
+
*/
|
|
46
|
+
function waitForOutboundTx(ctx_1, pushChainTxHash_1) {
|
|
47
|
+
return tslib_1.__awaiter(this, arguments, void 0, function* (ctx, pushChainTxHash, options = {}) {
|
|
48
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
|
|
49
|
+
const { initialWaitMs = exports.OUTBOUND_INITIAL_WAIT_MS, pollingIntervalMs = exports.OUTBOUND_POLL_INTERVAL_MS, timeout = exports.OUTBOUND_MAX_TIMEOUT_MS, progressHook, _resolvedSubTxId, _expectedDestinationChain, } = options;
|
|
50
|
+
// Terminal failure states — fail fast instead of polling until timeout
|
|
51
|
+
const TERMINAL_FAILURE_STATES = new Set([
|
|
52
|
+
types_1.UniversalTxStatus.OUTBOUND_FAILED,
|
|
53
|
+
types_1.UniversalTxStatus.PC_EXECUTED_FAILED,
|
|
54
|
+
types_1.UniversalTxStatus.CANCELED,
|
|
55
|
+
]);
|
|
56
|
+
const startTime = Date.now();
|
|
57
|
+
(0, context_1.printLog)(ctx, `[waitForOutboundTx] Starting | txHash: ${pushChainTxHash} | initialWait: ${initialWaitMs}ms | pollInterval: ${pollingIntervalMs}ms | timeout: ${timeout}ms`);
|
|
58
|
+
progressHook === null || progressHook === void 0 ? void 0 : progressHook({ status: 'waiting', elapsed: 0 });
|
|
59
|
+
(0, context_1.printLog)(ctx, `[waitForOutboundTx] Initial wait of ${initialWaitMs}ms...`);
|
|
60
|
+
yield new Promise((resolve) => setTimeout(resolve, initialWaitMs));
|
|
61
|
+
// Start polling
|
|
62
|
+
(0, context_1.printLog)(ctx, `[waitForOutboundTx] Initial wait done. Starting polling. Elapsed: ${Date.now() - startTime}ms`);
|
|
63
|
+
progressHook === null || progressHook === void 0 ? void 0 : progressHook({ status: 'polling', elapsed: Date.now() - startTime });
|
|
64
|
+
// Cache the universalSubTxId after first extraction to avoid redundant receipt fetches.
|
|
65
|
+
// If a pre-resolved ID was provided (cascade per-hop tracking), use it directly.
|
|
66
|
+
let cachedUniversalSubTxId = _resolvedSubTxId;
|
|
67
|
+
let pollCount = 0;
|
|
68
|
+
while (Date.now() - startTime < timeout) {
|
|
69
|
+
pollCount++;
|
|
70
|
+
const pollStart = Date.now();
|
|
71
|
+
(0, context_1.printLog)(ctx, `[waitForOutboundTx] Poll #${pollCount} | Elapsed: ${pollStart - startTime}ms / ${timeout}ms`);
|
|
72
|
+
if (!cachedUniversalSubTxId) {
|
|
73
|
+
cachedUniversalSubTxId = (_a = (yield (0, outbound_tracker_1.extractUniversalSubTxIdFromTx)(ctx, pushChainTxHash))) !== null && _a !== void 0 ? _a : undefined;
|
|
74
|
+
if (!cachedUniversalSubTxId) {
|
|
75
|
+
cachedUniversalSubTxId = (0, outbound_tracker_1.computeUniversalTxId)(ctx.pushNetwork, pushChainTxHash);
|
|
76
|
+
}
|
|
77
|
+
(0, context_1.printLog)(ctx, `[waitForOutboundTx] Extracted & cached universalSubTxId: ${cachedUniversalSubTxId}`);
|
|
78
|
+
}
|
|
79
|
+
// Query with cached ID
|
|
80
|
+
const queryId = cachedUniversalSubTxId.startsWith('0x')
|
|
81
|
+
? cachedUniversalSubTxId.slice(2)
|
|
82
|
+
: cachedUniversalSubTxId;
|
|
83
|
+
try {
|
|
84
|
+
const utxResponse = yield ctx.pushClient.getUniversalTxByIdV2(queryId);
|
|
85
|
+
const statusNum = (_b = utxResponse === null || utxResponse === void 0 ? void 0 : utxResponse.universalTx) === null || _b === void 0 ? void 0 : _b.universalStatus;
|
|
86
|
+
const statusName = (_c = types_1.UniversalTxStatus[statusNum]) !== null && _c !== void 0 ? _c : statusNum;
|
|
87
|
+
const outbounds = ((_d = utxResponse === null || utxResponse === void 0 ? void 0 : utxResponse.universalTx) === null || _d === void 0 ? void 0 : _d.outboundTx) || [];
|
|
88
|
+
(0, context_1.printLog)(ctx, `[waitForOutboundTx] Poll #${pollCount} | status: ${statusNum} (${statusName}) | outboundTx count: ${outbounds.length} | first txHash: '${((_f = (_e = outbounds[0]) === null || _e === void 0 ? void 0 : _e.observedTx) === null || _f === void 0 ? void 0 : _f.txHash) || ''}' | first dest: '${((_g = outbounds[0]) === null || _g === void 0 ? void 0 : _g.destinationChain) || ''}'`);
|
|
89
|
+
// Check for terminal failure states — fail fast
|
|
90
|
+
if (TERMINAL_FAILURE_STATES.has(statusNum)) {
|
|
91
|
+
(0, context_1.printLog)(ctx, `[waitForOutboundTx] Terminal failure state: ${statusName}`);
|
|
92
|
+
progressHook === null || progressHook === void 0 ? void 0 : progressHook({ status: 'failed', elapsed: Date.now() - startTime });
|
|
93
|
+
throw new Error(`Outbound transaction failed with status ${statusName}. Push Chain TX: ${pushChainTxHash}.`);
|
|
94
|
+
}
|
|
95
|
+
// Iterate V2 outbound array
|
|
96
|
+
for (const ob of outbounds) {
|
|
97
|
+
// Fail fast on per-outbound REVERTED status
|
|
98
|
+
if (ob.outboundStatus === types_2.OutboundStatus.REVERTED) {
|
|
99
|
+
(0, context_1.printLog)(ctx, `[waitForOutboundTx] Outbound to ${ob.destinationChain} REVERTED`);
|
|
100
|
+
progressHook === null || progressHook === void 0 ? void 0 : progressHook({ status: 'failed', elapsed: Date.now() - startTime });
|
|
101
|
+
throw new Error(`Outbound to ${ob.destinationChain} reverted: ${((_h = ob.observedTx) === null || _h === void 0 ? void 0 : _h.errorMsg) || 'Unknown'}. Push Chain TX: ${pushChainTxHash}.`);
|
|
102
|
+
}
|
|
103
|
+
if ((_j = ob.observedTx) === null || _j === void 0 ? void 0 : _j.txHash) {
|
|
104
|
+
// If a destination chain filter is set, skip outbound entries that don't match
|
|
105
|
+
if (_expectedDestinationChain && ob.destinationChain !== _expectedDestinationChain) {
|
|
106
|
+
(0, context_1.printLog)(ctx, `[waitForOutboundTx] Poll #${pollCount} | outbound chain '${ob.destinationChain}' does not match expected '${_expectedDestinationChain}', skipping`);
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
const chain = (0, helpers_1.chainFromNamespace)(ob.destinationChain);
|
|
110
|
+
if (chain) {
|
|
111
|
+
const explorerBaseUrl = (_k = chain_1.CHAIN_INFO[chain]) === null || _k === void 0 ? void 0 : _k.explorerUrl;
|
|
112
|
+
const isSvm = ((_l = chain_1.CHAIN_INFO[chain]) === null || _l === void 0 ? void 0 : _l.vm) === enums_1.VM.SVM;
|
|
113
|
+
// For SVM chains, convert hex txHash to base58 and append cluster param
|
|
114
|
+
let displayTxHash = ob.observedTx.txHash;
|
|
115
|
+
let explorerUrl = '';
|
|
116
|
+
if (isSvm && ob.observedTx.txHash.startsWith('0x')) {
|
|
117
|
+
const bytes = new Uint8Array(Buffer.from(ob.observedTx.txHash.slice(2), 'hex'));
|
|
118
|
+
displayTxHash = bs58_1.bs58.encode(Buffer.from(bytes));
|
|
119
|
+
const cluster = chain === enums_1.CHAIN.SOLANA_DEVNET ? '?cluster=devnet'
|
|
120
|
+
: chain === enums_1.CHAIN.SOLANA_TESTNET ? '?cluster=testnet' : '';
|
|
121
|
+
explorerUrl = explorerBaseUrl ? `${explorerBaseUrl}/tx/${displayTxHash}${cluster}` : '';
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
explorerUrl = explorerBaseUrl ? `${explorerBaseUrl}/tx/${ob.observedTx.txHash}` : '';
|
|
125
|
+
}
|
|
126
|
+
const details = {
|
|
127
|
+
externalTxHash: ob.observedTx.txHash,
|
|
128
|
+
destinationChain: chain,
|
|
129
|
+
explorerUrl,
|
|
130
|
+
recipient: ob.recipient,
|
|
131
|
+
amount: ob.amount,
|
|
132
|
+
assetAddr: ob.externalAssetAddr,
|
|
133
|
+
};
|
|
134
|
+
(0, context_1.printLog)(ctx, `[waitForOutboundTx] FOUND on poll #${pollCount} | elapsed: ${Date.now() - startTime}ms | externalTxHash: ${details.externalTxHash}`);
|
|
135
|
+
progressHook === null || progressHook === void 0 ? void 0 : progressHook({ status: 'found', elapsed: Date.now() - startTime });
|
|
136
|
+
return details;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
catch (error) {
|
|
142
|
+
// Re-throw terminal failure and reverted errors
|
|
143
|
+
if (error instanceof Error && (error.message.includes('Outbound transaction failed') || error.message.includes('reverted'))) {
|
|
144
|
+
throw error;
|
|
145
|
+
}
|
|
146
|
+
(0, context_1.printLog)(ctx, `[waitForOutboundTx] Poll #${pollCount} ERROR: ${error instanceof Error ? error.message : String(error)}`);
|
|
147
|
+
}
|
|
148
|
+
(0, context_1.printLog)(ctx, `[waitForOutboundTx] Poll #${pollCount} not ready yet (${Date.now() - pollStart}ms). Waiting ${pollingIntervalMs}ms...`);
|
|
149
|
+
// Wait before next poll
|
|
150
|
+
yield new Promise((resolve) => setTimeout(resolve, pollingIntervalMs));
|
|
151
|
+
}
|
|
152
|
+
(0, context_1.printLog)(ctx, `[waitForOutboundTx] TIMEOUT after ${pollCount} polls | elapsed: ${Date.now() - startTime}ms`);
|
|
153
|
+
progressHook === null || progressHook === void 0 ? void 0 : progressHook({ status: 'timeout', elapsed: Date.now() - startTime });
|
|
154
|
+
throw new Error(`Timeout waiting for outbound transaction. Push Chain TX: ${pushChainTxHash}. ` +
|
|
155
|
+
`Timeout: ${timeout}ms. The relay may still be processing.`);
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
// ============================================================================
|
|
159
|
+
// waitForAllOutboundTxsV2
|
|
160
|
+
// ============================================================================
|
|
161
|
+
/**
|
|
162
|
+
* Tracks ALL outbound transactions for a cascade with multiple outbound hops
|
|
163
|
+
* (e.g., BNB + Solana). Uses V2 API which returns outboundTx[] with per-outbound
|
|
164
|
+
* status tracking, matching each outbound to the correct hop by destination chain.
|
|
165
|
+
*/
|
|
166
|
+
function waitForAllOutboundTxsV2(ctx, pushChainTxHash, outboundHops, options) {
|
|
167
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
168
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
169
|
+
const { initialWaitMs, pollingIntervalMs, timeout, progressHook } = options;
|
|
170
|
+
const startTime = Date.now();
|
|
171
|
+
// Build a map: CAIP-2 namespace -> hop(s) for matching outbound entries
|
|
172
|
+
const chainToHops = new Map();
|
|
173
|
+
for (const hop of outboundHops) {
|
|
174
|
+
const chainInfo = chain_1.CHAIN_INFO[hop.executionChain];
|
|
175
|
+
if (chainInfo) {
|
|
176
|
+
const namespace = `${chain_1.VM_NAMESPACE[chainInfo.vm]}:${chainInfo.chainId}`;
|
|
177
|
+
const existing = chainToHops.get(namespace) || [];
|
|
178
|
+
existing.push(hop);
|
|
179
|
+
chainToHops.set(namespace, existing);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
const expectedChains = [...chainToHops.keys()];
|
|
183
|
+
(0, context_1.printLog)(ctx, `[waitForAllOutboundTxsV2] Starting | txHash: ${pushChainTxHash} | expectedChains: ${expectedChains.join(', ')} | timeout: ${timeout}ms`);
|
|
184
|
+
// Emit initial waiting status for all outbound hops
|
|
185
|
+
for (const hop of outboundHops) {
|
|
186
|
+
progressHook === null || progressHook === void 0 ? void 0 : progressHook({
|
|
187
|
+
hopIndex: hop.hopIndex,
|
|
188
|
+
route: hop.route,
|
|
189
|
+
chain: hop.executionChain,
|
|
190
|
+
status: 'waiting',
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
// Initial wait before first poll
|
|
194
|
+
const waitMs = Math.min(initialWaitMs, timeout);
|
|
195
|
+
(0, context_1.printLog)(ctx, `[waitForAllOutboundTxsV2] Initial wait of ${waitMs}ms...`);
|
|
196
|
+
yield new Promise((resolve) => setTimeout(resolve, waitMs));
|
|
197
|
+
// Emit polling status for all hops
|
|
198
|
+
for (const hop of outboundHops) {
|
|
199
|
+
progressHook === null || progressHook === void 0 ? void 0 : progressHook({
|
|
200
|
+
hopIndex: hop.hopIndex,
|
|
201
|
+
route: hop.route,
|
|
202
|
+
chain: hop.executionChain,
|
|
203
|
+
status: 'polling',
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
// Extract sub-tx ID for V2 query
|
|
207
|
+
let cachedQueryId;
|
|
208
|
+
let pollCount = 0;
|
|
209
|
+
let consecutiveErrors = 0;
|
|
210
|
+
const MAX_CONSECUTIVE_ERRORS = 10;
|
|
211
|
+
while (Date.now() - startTime < timeout) {
|
|
212
|
+
pollCount++;
|
|
213
|
+
const elapsed = Date.now() - startTime;
|
|
214
|
+
(0, context_1.printLog)(ctx, `[waitForAllOutboundTxsV2] Poll #${pollCount} | Elapsed: ${elapsed}ms / ${timeout}ms`);
|
|
215
|
+
// Resolve query ID on first poll
|
|
216
|
+
if (!cachedQueryId) {
|
|
217
|
+
const allSubTxIds = yield (0, outbound_tracker_1.extractAllUniversalSubTxIds)(ctx, pushChainTxHash);
|
|
218
|
+
const subTxId = allSubTxIds.length > 0 ? allSubTxIds[0] : (0, outbound_tracker_1.computeUniversalTxId)(ctx.pushNetwork, pushChainTxHash);
|
|
219
|
+
cachedQueryId = subTxId.startsWith('0x') ? subTxId.slice(2) : subTxId;
|
|
220
|
+
(0, context_1.printLog)(ctx, `[waitForAllOutboundTxsV2] Resolved queryId: ${cachedQueryId}`);
|
|
221
|
+
}
|
|
222
|
+
try {
|
|
223
|
+
const v2Response = yield ctx.pushClient.getUniversalTxByIdV2(cachedQueryId);
|
|
224
|
+
consecutiveErrors = 0; // Reset on successful RPC call
|
|
225
|
+
const utx = v2Response === null || v2Response === void 0 ? void 0 : v2Response.universalTx;
|
|
226
|
+
const statusNum = utx === null || utx === void 0 ? void 0 : utx.universalStatus;
|
|
227
|
+
const statusName = (_a = types_1.UniversalTxStatus[statusNum]) !== null && _a !== void 0 ? _a : statusNum;
|
|
228
|
+
(0, context_1.printLog)(ctx, `[waitForAllOutboundTxsV2] Poll #${pollCount} | status: ${statusNum} (${statusName}) | outboundTx count: ${(_c = (_b = utx === null || utx === void 0 ? void 0 : utx.outboundTx) === null || _b === void 0 ? void 0 : _b.length) !== null && _c !== void 0 ? _c : 0}`);
|
|
229
|
+
if ((_d = utx === null || utx === void 0 ? void 0 : utx.outboundTx) === null || _d === void 0 ? void 0 : _d.length) {
|
|
230
|
+
for (const ob of utx.outboundTx) {
|
|
231
|
+
const destChain = ob.destinationChain;
|
|
232
|
+
const hopsForChain = chainToHops.get(destChain);
|
|
233
|
+
if (!hopsForChain)
|
|
234
|
+
continue;
|
|
235
|
+
const unconfirmedForChain = hopsForChain.filter((h) => h.status !== 'confirmed' && h.status !== 'failed');
|
|
236
|
+
if (unconfirmedForChain.length === 0)
|
|
237
|
+
continue;
|
|
238
|
+
// Fail fast on per-outbound REVERTED
|
|
239
|
+
if (ob.outboundStatus === types_2.OutboundStatus.REVERTED) {
|
|
240
|
+
for (const hop of unconfirmedForChain) {
|
|
241
|
+
hop.status = 'failed';
|
|
242
|
+
(0, context_1.printLog)(ctx, `[waitForAllOutboundTxsV2] Outbound to ${destChain} REVERTED | hop ${hop.hopIndex} | error: ${((_e = ob.observedTx) === null || _e === void 0 ? void 0 : _e.errorMsg) || 'Unknown'}`);
|
|
243
|
+
progressHook === null || progressHook === void 0 ? void 0 : progressHook({
|
|
244
|
+
hopIndex: hop.hopIndex,
|
|
245
|
+
route: hop.route,
|
|
246
|
+
chain: hop.executionChain,
|
|
247
|
+
status: 'failed',
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
return { success: false, failedAt: unconfirmedForChain[0].hopIndex };
|
|
251
|
+
}
|
|
252
|
+
// Check for OBSERVED with txHash
|
|
253
|
+
const externalTxHash = (_f = ob.observedTx) === null || _f === void 0 ? void 0 : _f.txHash;
|
|
254
|
+
if (externalTxHash && (ob.outboundStatus === types_2.OutboundStatus.OBSERVED || ob.outboundStatus === 0)) {
|
|
255
|
+
const chain = (0, helpers_1.chainFromNamespace)(destChain);
|
|
256
|
+
let explorerUrl = '';
|
|
257
|
+
if (chain && externalTxHash) {
|
|
258
|
+
const explorerBaseUrl = (_g = chain_1.CHAIN_INFO[chain]) === null || _g === void 0 ? void 0 : _g.explorerUrl;
|
|
259
|
+
const isSvm = ((_h = chain_1.CHAIN_INFO[chain]) === null || _h === void 0 ? void 0 : _h.vm) === enums_1.VM.SVM;
|
|
260
|
+
if (isSvm && externalTxHash.startsWith('0x')) {
|
|
261
|
+
const bytes = new Uint8Array(Buffer.from(externalTxHash.slice(2), 'hex'));
|
|
262
|
+
const base58Hash = bs58_1.bs58.encode(Buffer.from(bytes));
|
|
263
|
+
const cluster = chain === enums_1.CHAIN.SOLANA_DEVNET ? '?cluster=devnet'
|
|
264
|
+
: chain === enums_1.CHAIN.SOLANA_TESTNET ? '?cluster=testnet' : '';
|
|
265
|
+
explorerUrl = explorerBaseUrl ? `${explorerBaseUrl}/tx/${base58Hash}${cluster}` : '';
|
|
266
|
+
}
|
|
267
|
+
else {
|
|
268
|
+
explorerUrl = explorerBaseUrl ? `${explorerBaseUrl}/tx/${externalTxHash}` : '';
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
for (const hop of unconfirmedForChain) {
|
|
272
|
+
hop.status = 'confirmed';
|
|
273
|
+
hop.txHash = externalTxHash;
|
|
274
|
+
hop.outboundDetails = {
|
|
275
|
+
externalTxHash,
|
|
276
|
+
destinationChain: chain || hop.executionChain,
|
|
277
|
+
explorerUrl,
|
|
278
|
+
recipient: ob.recipient,
|
|
279
|
+
amount: ob.amount,
|
|
280
|
+
assetAddr: ob.externalAssetAddr,
|
|
281
|
+
};
|
|
282
|
+
(0, context_1.printLog)(ctx, `[waitForAllOutboundTxsV2] FOUND outbound for ${destChain} | hop ${hop.hopIndex} | externalTxHash: ${externalTxHash}`);
|
|
283
|
+
progressHook === null || progressHook === void 0 ? void 0 : progressHook({
|
|
284
|
+
hopIndex: hop.hopIndex,
|
|
285
|
+
route: hop.route,
|
|
286
|
+
chain: hop.executionChain,
|
|
287
|
+
status: 'confirmed',
|
|
288
|
+
txHash: externalTxHash,
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
// Check if all hops are now confirmed
|
|
295
|
+
if (outboundHops.every((h) => h.status === 'confirmed')) {
|
|
296
|
+
(0, context_1.printLog)(ctx, `[waitForAllOutboundTxsV2] All ${outboundHops.length} hops confirmed via V2`);
|
|
297
|
+
return { success: true };
|
|
298
|
+
}
|
|
299
|
+
// If PC_EXECUTED_SUCCESS but some hops still unresolved, check outbound status.
|
|
300
|
+
// Only auto-confirm if there are NO pending outbound txs (status=1 with empty hash).
|
|
301
|
+
// Pending outbounds are still in flight on the relay — keep polling for their hashes.
|
|
302
|
+
if (statusNum === types_1.UniversalTxStatus.PC_EXECUTED_SUCCESS) {
|
|
303
|
+
const stillUnresolved = outboundHops.filter((h) => h.status !== 'confirmed');
|
|
304
|
+
if (stillUnresolved.length > 0) {
|
|
305
|
+
const hasPendingOutbound = (_j = utx === null || utx === void 0 ? void 0 : utx.outboundTx) === null || _j === void 0 ? void 0 : _j.some((ob) => {
|
|
306
|
+
var _a;
|
|
307
|
+
return ob.outboundStatus === types_2.OutboundStatus.PENDING &&
|
|
308
|
+
(!((_a = ob.observedTx) === null || _a === void 0 ? void 0 : _a.txHash) || ob.observedTx.txHash === 'EMPTY');
|
|
309
|
+
});
|
|
310
|
+
if (!hasPendingOutbound) {
|
|
311
|
+
// No pending outbounds — safe to auto-confirm remaining hops
|
|
312
|
+
for (const hop of stillUnresolved) {
|
|
313
|
+
hop.status = 'confirmed';
|
|
314
|
+
(0, context_1.printLog)(ctx, `[waitForAllOutboundTxsV2] Auto-confirmed hop ${hop.hopIndex} (${hop.executionChain}) based on PC_EXECUTED_SUCCESS (no pending outbounds)`);
|
|
315
|
+
progressHook === null || progressHook === void 0 ? void 0 : progressHook({
|
|
316
|
+
hopIndex: hop.hopIndex,
|
|
317
|
+
route: hop.route,
|
|
318
|
+
chain: hop.executionChain,
|
|
319
|
+
status: 'confirmed',
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
return { success: true };
|
|
323
|
+
}
|
|
324
|
+
// Pending outbound txs still in flight — continue polling
|
|
325
|
+
(0, context_1.printLog)(ctx, `[waitForAllOutboundTxsV2] ${stillUnresolved.length} hop(s) unresolved, pending outbound txs in flight — continuing to poll`);
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
catch (error) {
|
|
330
|
+
consecutiveErrors++;
|
|
331
|
+
(0, context_1.printLog)(ctx, `[waitForAllOutboundTxsV2] Poll #${pollCount} ERROR (${consecutiveErrors}/${MAX_CONSECUTIVE_ERRORS}): ${error instanceof Error ? error.message : String(error)}`);
|
|
332
|
+
if (consecutiveErrors >= MAX_CONSECUTIVE_ERRORS) {
|
|
333
|
+
(0, context_1.printLog)(ctx, `[waitForAllOutboundTxsV2] Aborting — ${MAX_CONSECUTIVE_ERRORS} consecutive RPC errors`);
|
|
334
|
+
break;
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
yield new Promise((resolve) => setTimeout(resolve, pollingIntervalMs));
|
|
338
|
+
}
|
|
339
|
+
// Timeout: fail any unresolved hops
|
|
340
|
+
const timedOutHops = outboundHops.filter((h) => h.status !== 'confirmed');
|
|
341
|
+
if (timedOutHops.length > 0) {
|
|
342
|
+
(0, context_1.printLog)(ctx, `[waitForAllOutboundTxsV2] TIMEOUT after ${pollCount} polls | ${timedOutHops.length} hop(s) unresolved`);
|
|
343
|
+
for (const hop of timedOutHops) {
|
|
344
|
+
hop.status = 'failed';
|
|
345
|
+
progressHook === null || progressHook === void 0 ? void 0 : progressHook({
|
|
346
|
+
hopIndex: hop.hopIndex,
|
|
347
|
+
route: hop.route,
|
|
348
|
+
chain: hop.executionChain,
|
|
349
|
+
status: 'failed',
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
return { success: false, failedAt: timedOutHops[0].hopIndex };
|
|
353
|
+
}
|
|
354
|
+
return { success: true };
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
//# sourceMappingURL=outbound-sync.js.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Outbound transaction tracking and UTX ID extraction, extracted from Orchestrator.
|
|
3
|
+
*/
|
|
4
|
+
import type { PUSH_NETWORK } from '../../constants/enums';
|
|
5
|
+
import type { OrchestratorContext } from './context';
|
|
6
|
+
export declare function computeUniversalTxId(pushNetwork: PUSH_NETWORK, pushChainTxHash: string): string;
|
|
7
|
+
export declare function extractAllUniversalSubTxIds(ctx: OrchestratorContext, pushChainTxHash: string): Promise<string[]>;
|
|
8
|
+
export declare function extractUniversalSubTxIdFromTx(ctx: OrchestratorContext, pushChainTxHash: string): Promise<string | null>;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Outbound transaction tracking and UTX ID extraction, extracted from Orchestrator.
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.computeUniversalTxId = computeUniversalTxId;
|
|
7
|
+
exports.extractAllUniversalSubTxIds = extractAllUniversalSubTxIds;
|
|
8
|
+
exports.extractUniversalSubTxIdFromTx = extractUniversalSubTxIdFromTx;
|
|
9
|
+
const tslib_1 = require("tslib");
|
|
10
|
+
const viem_1 = require("viem");
|
|
11
|
+
const chain_1 = require("../../constants/chain");
|
|
12
|
+
const context_1 = require("./context");
|
|
13
|
+
const helpers_1 = require("./helpers");
|
|
14
|
+
// ============================================================================
|
|
15
|
+
// UTX ID Computation
|
|
16
|
+
// ============================================================================
|
|
17
|
+
function computeUniversalTxId(pushNetwork, pushChainTxHash) {
|
|
18
|
+
const pushChain = (0, helpers_1.getPushChainForNetwork)(pushNetwork);
|
|
19
|
+
const pushChainId = chain_1.CHAIN_INFO[pushChain].chainId;
|
|
20
|
+
const input = `eip155:${pushChainId}:${pushChainTxHash}`;
|
|
21
|
+
return (0, viem_1.keccak256)((0, viem_1.toBytes)(input));
|
|
22
|
+
}
|
|
23
|
+
// ============================================================================
|
|
24
|
+
// UTX ID Extraction from Cosmos Events
|
|
25
|
+
// ============================================================================
|
|
26
|
+
function extractAllUniversalSubTxIds(ctx, pushChainTxHash) {
|
|
27
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
28
|
+
var _a;
|
|
29
|
+
(0, context_1.printLog)(ctx, `[extractAllUniversalSubTxIds] Fetching Cosmos tx for: ${pushChainTxHash}`);
|
|
30
|
+
try {
|
|
31
|
+
const cosmosTx = yield ctx.pushClient.getCosmosTx(pushChainTxHash);
|
|
32
|
+
if (!(cosmosTx === null || cosmosTx === void 0 ? void 0 : cosmosTx.events)) {
|
|
33
|
+
(0, context_1.printLog)(ctx, `[extractAllUniversalSubTxIds] No events in Cosmos tx`);
|
|
34
|
+
return [];
|
|
35
|
+
}
|
|
36
|
+
const subTxIds = [];
|
|
37
|
+
for (const event of cosmosTx.events) {
|
|
38
|
+
if (event.type === 'outbound_created') {
|
|
39
|
+
const utxIdAttr = (_a = event.attributes) === null || _a === void 0 ? void 0 : _a.find((attr) => attr.key === 'utx_id');
|
|
40
|
+
if (utxIdAttr === null || utxIdAttr === void 0 ? void 0 : utxIdAttr.value) {
|
|
41
|
+
const id = utxIdAttr.value.startsWith('0x')
|
|
42
|
+
? utxIdAttr.value
|
|
43
|
+
: `0x${utxIdAttr.value}`;
|
|
44
|
+
subTxIds.push(id);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
(0, context_1.printLog)(ctx, `[extractAllUniversalSubTxIds] Found ${subTxIds.length} sub-tx IDs: ${subTxIds.join(', ')}`);
|
|
49
|
+
return subTxIds;
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
(0, context_1.printLog)(ctx, `[extractAllUniversalSubTxIds] Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
53
|
+
return [];
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
function extractUniversalSubTxIdFromTx(ctx, pushChainTxHash) {
|
|
58
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
59
|
+
var _a;
|
|
60
|
+
const ids = yield extractAllUniversalSubTxIds(ctx, pushChainTxHash);
|
|
61
|
+
return (_a = ids[0]) !== null && _a !== void 0 ? _a : null;
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=outbound-tracker.js.map
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Payload construction functions for the orchestrator.
|
|
3
|
+
*
|
|
4
|
+
* buildUniversalTxRequest: Creates gateway request with revert instruction
|
|
5
|
+
* buildMulticallPayloadData: Encodes UEA_MULTICALL selector + abi-encoded calls
|
|
6
|
+
* buildGatewayPayloadAndGas: Constructs UniversalPayload + gateway request for fund flows
|
|
7
|
+
*/
|
|
8
|
+
import type { ExecuteParams, MultiCall, UniversalTxRequest } from '../orchestrator.types';
|
|
9
|
+
import type { OrchestratorContext } from './context';
|
|
10
|
+
export declare function buildUniversalTxRequest(signerAddress: `0x${string}`, { recipient, token, amount, payload, }: {
|
|
11
|
+
recipient: `0x${string}`;
|
|
12
|
+
token: `0x${string}`;
|
|
13
|
+
amount: bigint;
|
|
14
|
+
payload: `0x${string}`;
|
|
15
|
+
}): UniversalTxRequest;
|
|
16
|
+
export declare function buildMulticallPayloadData(ctx: OrchestratorContext, to: `0x${string}`, data: MultiCall[]): `0x${string}`;
|
|
17
|
+
/**
|
|
18
|
+
* Builds the universal payload and gateway request for sendFunds / sendTxWithFunds flows.
|
|
19
|
+
*/
|
|
20
|
+
export declare function buildGatewayPayloadAndGas(ctx: OrchestratorContext, execute: ExecuteParams, nonce: bigint, type: 'sendFunds' | 'sendTxWithFunds', fundsValue?: bigint): Promise<{
|
|
21
|
+
payload: never;
|
|
22
|
+
gasAmount: bigint;
|
|
23
|
+
req: UniversalTxRequest;
|
|
24
|
+
}>;
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Payload construction functions for the orchestrator.
|
|
4
|
+
*
|
|
5
|
+
* buildUniversalTxRequest: Creates gateway request with revert instruction
|
|
6
|
+
* buildMulticallPayloadData: Encodes UEA_MULTICALL selector + abi-encoded calls
|
|
7
|
+
* buildGatewayPayloadAndGas: Constructs UniversalPayload + gateway request for fund flows
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.buildUniversalTxRequest = buildUniversalTxRequest;
|
|
11
|
+
exports.buildMulticallPayloadData = buildMulticallPayloadData;
|
|
12
|
+
exports.buildGatewayPayloadAndGas = buildGatewayPayloadAndGas;
|
|
13
|
+
const tslib_1 = require("tslib");
|
|
14
|
+
const viem_1 = require("viem");
|
|
15
|
+
const tx_1 = require("../../generated/v1/tx");
|
|
16
|
+
const payload_builders_1 = require("../payload-builders");
|
|
17
|
+
const context_1 = require("./context");
|
|
18
|
+
const helpers_1 = require("./helpers");
|
|
19
|
+
const signing_1 = require("./signing");
|
|
20
|
+
const uea_manager_1 = require("./uea-manager");
|
|
21
|
+
// ============================================================================
|
|
22
|
+
// Universal Tx Request Builder
|
|
23
|
+
// ============================================================================
|
|
24
|
+
function buildUniversalTxRequest(signerAddress, { recipient, token, amount, payload, }) {
|
|
25
|
+
const revertInstruction = {
|
|
26
|
+
fundRecipient: signerAddress,
|
|
27
|
+
revertMsg: '0x',
|
|
28
|
+
};
|
|
29
|
+
return {
|
|
30
|
+
recipient,
|
|
31
|
+
token,
|
|
32
|
+
amount,
|
|
33
|
+
payload,
|
|
34
|
+
revertInstruction,
|
|
35
|
+
signatureData: '0x',
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
// ============================================================================
|
|
39
|
+
// Multicall Encoding
|
|
40
|
+
// ============================================================================
|
|
41
|
+
function buildMulticallPayloadData(ctx, to, data) {
|
|
42
|
+
(0, context_1.printLog)(ctx, '_buildMulticallPayloadData — input: ' +
|
|
43
|
+
data.length +
|
|
44
|
+
' calls: ' +
|
|
45
|
+
JSON.stringify(data, (_, v) => (typeof v === 'bigint' ? v.toString() : v), 2));
|
|
46
|
+
if (!helpers_1.SUPPORTED_GATEWAY_CHAINS.includes(ctx.universalSigner.account.chain)) {
|
|
47
|
+
throw new Error('Multicall is only enabled for Ethereum Sepolia, Arbitrum Sepolia, Base Sepolia, BNB Testnet and Solana Devnet');
|
|
48
|
+
}
|
|
49
|
+
// Normalize and validate calls
|
|
50
|
+
const normalizedCalls = data.map((c) => ({
|
|
51
|
+
to: (0, viem_1.getAddress)(c.to),
|
|
52
|
+
value: c.value,
|
|
53
|
+
data: c.data,
|
|
54
|
+
}));
|
|
55
|
+
// bytes4(keccak256("UEA_MULTICALL")) selector
|
|
56
|
+
const selector = (0, viem_1.keccak256)((0, viem_1.toBytes)('UEA_MULTICALL')).slice(0, 10);
|
|
57
|
+
// abi.encode(Call[]), where Call = { address to; uint256 value; bytes data; }
|
|
58
|
+
const encodedCalls = (0, viem_1.encodeAbiParameters)([
|
|
59
|
+
{
|
|
60
|
+
type: 'tuple[]',
|
|
61
|
+
components: [
|
|
62
|
+
{ name: 'to', type: 'address' },
|
|
63
|
+
{ name: 'value', type: 'uint256' },
|
|
64
|
+
{ name: 'data', type: 'bytes' },
|
|
65
|
+
],
|
|
66
|
+
},
|
|
67
|
+
], [normalizedCalls]);
|
|
68
|
+
return (selector + encodedCalls.slice(2));
|
|
69
|
+
}
|
|
70
|
+
// ============================================================================
|
|
71
|
+
// Gateway Payload + Gas Builder
|
|
72
|
+
// ============================================================================
|
|
73
|
+
/**
|
|
74
|
+
* Builds the universal payload and gateway request for sendFunds / sendTxWithFunds flows.
|
|
75
|
+
*/
|
|
76
|
+
function buildGatewayPayloadAndGas(ctx, execute, nonce, type, fundsValue) {
|
|
77
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
78
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6;
|
|
79
|
+
const gasEstimate = execute.gasLimit || BigInt(1e7);
|
|
80
|
+
const gasAmount = (_a = execute.value) !== null && _a !== void 0 ? _a : BigInt(0);
|
|
81
|
+
const ueaAddress = (0, uea_manager_1.computeUEAOffchain)(ctx);
|
|
82
|
+
if (type === 'sendTxWithFunds') {
|
|
83
|
+
if (!((_b = execute.funds) === null || _b === void 0 ? void 0 : _b.token))
|
|
84
|
+
throw new Error(`Invalid ${(_c = execute.funds) === null || _c === void 0 ? void 0 : _c.token}`);
|
|
85
|
+
const multicallData = (0, payload_builders_1.buildExecuteMulticall)({
|
|
86
|
+
execute,
|
|
87
|
+
ueaAddress,
|
|
88
|
+
});
|
|
89
|
+
const universalPayload = {
|
|
90
|
+
to: viem_1.zeroAddress,
|
|
91
|
+
value: (_d = execute.value) !== null && _d !== void 0 ? _d : BigInt(0),
|
|
92
|
+
data: buildMulticallPayloadData(ctx, execute.to, multicallData),
|
|
93
|
+
gasLimit: gasEstimate,
|
|
94
|
+
maxFeePerGas: execute.maxFeePerGas || BigInt(1e10),
|
|
95
|
+
maxPriorityFeePerGas: execute.maxPriorityFeePerGas || BigInt(0),
|
|
96
|
+
nonce,
|
|
97
|
+
deadline: execute.deadline || BigInt(9999999999),
|
|
98
|
+
vType: tx_1.VerificationType.universalTxVerification,
|
|
99
|
+
};
|
|
100
|
+
(0, context_1.printLog)(ctx, '(universalPayload) ' + universalPayload);
|
|
101
|
+
let tokenAddress = (_f = (_e = execute.funds) === null || _e === void 0 ? void 0 : _e.token) === null || _f === void 0 ? void 0 : _f.address;
|
|
102
|
+
if (((_h = (_g = execute.funds) === null || _g === void 0 ? void 0 : _g.token) === null || _h === void 0 ? void 0 : _h.address) ===
|
|
103
|
+
'0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee') {
|
|
104
|
+
tokenAddress = viem_1.zeroAddress;
|
|
105
|
+
}
|
|
106
|
+
const req = buildUniversalTxRequest(ctx.universalSigner.account.address, {
|
|
107
|
+
recipient: viem_1.zeroAddress,
|
|
108
|
+
token: tokenAddress,
|
|
109
|
+
amount: (_j = execute.funds) === null || _j === void 0 ? void 0 : _j.amount,
|
|
110
|
+
payload: (0, signing_1.encodeUniversalPayload)(universalPayload),
|
|
111
|
+
});
|
|
112
|
+
return { payload: universalPayload, gasAmount, req };
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
if (!fundsValue)
|
|
116
|
+
throw new Error('fundsValue property must not be empty');
|
|
117
|
+
const multicallData = (0, payload_builders_1.buildExecuteMulticall)({
|
|
118
|
+
execute,
|
|
119
|
+
ueaAddress,
|
|
120
|
+
});
|
|
121
|
+
(0, context_1.printLog)(ctx, 'sendFunds — execute params: ' + JSON.stringify({
|
|
122
|
+
to: execute.to,
|
|
123
|
+
value: (_l = (_k = execute.value) === null || _k === void 0 ? void 0 : _k.toString()) !== null && _l !== void 0 ? _l : 'undefined',
|
|
124
|
+
data: (_m = execute.data) !== null && _m !== void 0 ? _m : 'undefined',
|
|
125
|
+
fundsAmount: (_p = (_o = execute.funds) === null || _o === void 0 ? void 0 : _o.amount) === null || _p === void 0 ? void 0 : _p.toString(),
|
|
126
|
+
fundsToken: (_r = (_q = execute.funds) === null || _q === void 0 ? void 0 : _q.token) === null || _r === void 0 ? void 0 : _r.symbol,
|
|
127
|
+
tokenMechanism: (_t = (_s = execute.funds) === null || _s === void 0 ? void 0 : _s.token) === null || _t === void 0 ? void 0 : _t.mechanism,
|
|
128
|
+
tokenAddress: (_v = (_u = execute.funds) === null || _u === void 0 ? void 0 : _u.token) === null || _v === void 0 ? void 0 : _v.address,
|
|
129
|
+
gasLimit: (_x = (_w = execute.gasLimit) === null || _w === void 0 ? void 0 : _w.toString()) !== null && _x !== void 0 ? _x : 'undefined',
|
|
130
|
+
}, null, 2));
|
|
131
|
+
(0, context_1.printLog)(ctx, 'sendFunds — multicallData: ' + JSON.stringify(multicallData, (_, v) => typeof v === 'bigint' ? v.toString() : v, 2) + ' (length: ' + multicallData.length + ')');
|
|
132
|
+
const multicallPayloadData = buildMulticallPayloadData(ctx, execute.to, multicallData);
|
|
133
|
+
(0, context_1.printLog)(ctx, 'sendFunds — multicallPayloadData (first 66 chars): ' + multicallPayloadData.slice(0, 66) + ' (full length: ' + multicallPayloadData.length + ')');
|
|
134
|
+
const universalPayload = {
|
|
135
|
+
to: viem_1.zeroAddress,
|
|
136
|
+
value: (_y = execute.value) !== null && _y !== void 0 ? _y : BigInt(0),
|
|
137
|
+
data: multicallPayloadData,
|
|
138
|
+
gasLimit: gasEstimate,
|
|
139
|
+
maxFeePerGas: execute.maxFeePerGas || BigInt(1e10),
|
|
140
|
+
maxPriorityFeePerGas: execute.maxPriorityFeePerGas || BigInt(0),
|
|
141
|
+
nonce,
|
|
142
|
+
deadline: execute.deadline || BigInt(9999999999),
|
|
143
|
+
vType: tx_1.VerificationType.universalTxVerification,
|
|
144
|
+
};
|
|
145
|
+
(0, context_1.printLog)(ctx, 'sendFunds — universalPayload (pre-encode): ' + JSON.stringify({
|
|
146
|
+
to: viem_1.zeroAddress,
|
|
147
|
+
value: ((_z = execute.value) !== null && _z !== void 0 ? _z : BigInt(0)).toString(),
|
|
148
|
+
data: multicallPayloadData,
|
|
149
|
+
gasLimit: gasEstimate.toString(),
|
|
150
|
+
maxFeePerGas: (execute.maxFeePerGas || BigInt(1e10)).toString(),
|
|
151
|
+
maxPriorityFeePerGas: (execute.maxPriorityFeePerGas || BigInt(0)).toString(),
|
|
152
|
+
nonce: nonce.toString(),
|
|
153
|
+
deadline: (execute.deadline || BigInt(9999999999)).toString(),
|
|
154
|
+
}, null, 2));
|
|
155
|
+
let tokenAddress = (_1 = (_0 = execute.funds) === null || _0 === void 0 ? void 0 : _0.token) === null || _1 === void 0 ? void 0 : _1.address;
|
|
156
|
+
if (((_3 = (_2 = execute.funds) === null || _2 === void 0 ? void 0 : _2.token) === null || _3 === void 0 ? void 0 : _3.address) ===
|
|
157
|
+
'0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee') {
|
|
158
|
+
tokenAddress = viem_1.zeroAddress;
|
|
159
|
+
}
|
|
160
|
+
const encodedPayload = (0, signing_1.encodeUniversalPayload)(universalPayload);
|
|
161
|
+
(0, context_1.printLog)(ctx, 'sendFunds — encodedPayload (first 66 chars): ' + encodedPayload.slice(0, 66) + ' (full length: ' + encodedPayload.length + ')');
|
|
162
|
+
const req = buildUniversalTxRequest(ctx.universalSigner.account.address, {
|
|
163
|
+
recipient: viem_1.zeroAddress,
|
|
164
|
+
token: tokenAddress,
|
|
165
|
+
amount: (_4 = execute.funds) === null || _4 === void 0 ? void 0 : _4.amount,
|
|
166
|
+
payload: encodedPayload,
|
|
167
|
+
});
|
|
168
|
+
(0, context_1.printLog)(ctx, 'sendFunds — final req: ' + JSON.stringify({
|
|
169
|
+
recipient: viem_1.zeroAddress,
|
|
170
|
+
token: tokenAddress,
|
|
171
|
+
amount: (_6 = (_5 = execute.funds) === null || _5 === void 0 ? void 0 : _5.amount) === null || _6 === void 0 ? void 0 : _6.toString(),
|
|
172
|
+
payloadLength: encodedPayload.length,
|
|
173
|
+
}, null, 2));
|
|
174
|
+
return { payload: universalPayload, gasAmount, req };
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
//# sourceMappingURL=payload-builder.js.map
|