@pushchain/core 6.0.19 → 6.0.21
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/CHANGELOG.md +54 -0
- package/package.json +1 -1
- package/src/lib/cache/cache.js +2 -0
- package/src/lib/constants/abi/index.d.ts +1 -0
- package/src/lib/constants/abi/index.js +8 -1
- package/src/lib/constants/abi/pc20.evm.d.ts +217 -0
- package/src/lib/constants/abi/pc20.evm.js +150 -0
- package/src/lib/constants/abi/prc20.evm.d.ts +172 -0
- package/src/lib/constants/abi/prc20.evm.js +97 -0
- package/src/lib/constants/abi/universalGatewayV0.json +1 -1
- package/src/lib/constants/chain.js +38 -8
- package/src/lib/constants/selectors.js +2 -2
- package/src/lib/constants/tokens.js +4 -3
- package/src/lib/formatters.js +16 -6
- package/src/lib/generated/uexecutor/v1/query.js +2 -4
- package/src/lib/generated/uexecutor/v1/types.d.ts +14 -0
- package/src/lib/generated/uexecutor/v1/types.js +90 -47
- package/src/lib/generated/uexecutor/v2/query.js +2 -4
- package/src/lib/generated/uexecutor/v2/types.d.ts +20 -0
- package/src/lib/generated/uexecutor/v2/types.js +49 -33
- package/src/lib/generated/v1/tx.js +30 -37
- package/src/lib/index.d.ts +4 -1
- package/src/lib/index.js +21 -3
- package/src/lib/internal/buffer.js +1 -2
- package/src/lib/orchestrator/cea-utils.js +73 -83
- package/src/lib/orchestrator/internals/account-manager.js +130 -139
- package/src/lib/orchestrator/internals/cascade.d.ts +0 -6
- package/src/lib/orchestrator/internals/cascade.js +1184 -1059
- package/src/lib/orchestrator/internals/confirmation.js +138 -148
- package/src/lib/orchestrator/internals/error-decoder.js +1 -1
- package/src/lib/orchestrator/internals/errors.js +12 -3
- package/src/lib/orchestrator/internals/execute-funds-only.d.ts +2 -2
- package/src/lib/orchestrator/internals/execute-funds-only.js +297 -259
- package/src/lib/orchestrator/internals/execute-funds-payload.d.ts +2 -2
- package/src/lib/orchestrator/internals/execute-funds-payload.js +220 -220
- package/src/lib/orchestrator/internals/execute-standard.d.ts +0 -8
- package/src/lib/orchestrator/internals/execute-standard.js +339 -342
- package/src/lib/orchestrator/internals/gas-calculator.js +497 -520
- package/src/lib/orchestrator/internals/gas-usd-sizer.js +101 -110
- package/src/lib/orchestrator/internals/gateway-client.js +102 -103
- package/src/lib/orchestrator/internals/helpers.js +30 -27
- package/src/lib/orchestrator/internals/inbound-tracker.js +234 -238
- package/src/lib/orchestrator/internals/outbound-sync.js +463 -452
- package/src/lib/orchestrator/internals/outbound-tracker.js +27 -34
- package/src/lib/orchestrator/internals/payload-builder.d.ts +2 -2
- package/src/lib/orchestrator/internals/payload-builder.js +119 -100
- package/src/lib/orchestrator/internals/pc-usd-oracle.js +121 -129
- package/src/lib/orchestrator/internals/pc20/address-codec.d.ts +31 -0
- package/src/lib/orchestrator/internals/pc20/address-codec.js +124 -0
- package/src/lib/orchestrator/internals/pc20/chain-namespace.d.ts +68 -0
- package/src/lib/orchestrator/internals/pc20/chain-namespace.js +136 -0
- package/src/lib/orchestrator/internals/pc20/errors.d.ts +160 -0
- package/src/lib/orchestrator/internals/pc20/errors.js +236 -0
- package/src/lib/orchestrator/internals/pc20/export.d.ts +172 -0
- package/src/lib/orchestrator/internals/pc20/export.js +412 -0
- package/src/lib/orchestrator/internals/pc20/gate.d.ts +67 -0
- package/src/lib/orchestrator/internals/pc20/gate.js +184 -0
- package/src/lib/orchestrator/internals/pc20/resolver.d.ts +187 -0
- package/src/lib/orchestrator/internals/pc20/resolver.js +658 -0
- package/src/lib/orchestrator/internals/pc20/svm.d.ts +189 -0
- package/src/lib/orchestrator/internals/pc20/svm.js +286 -0
- package/src/lib/orchestrator/internals/pc20/tracking.d.ts +46 -0
- package/src/lib/orchestrator/internals/pc20/tracking.js +109 -0
- package/src/lib/orchestrator/internals/preflight.js +1 -1
- package/src/lib/orchestrator/internals/progress-route-hooks.js +2 -2
- package/src/lib/orchestrator/internals/push-chain-tx.js +319 -331
- package/src/lib/orchestrator/internals/quote.js +90 -94
- package/src/lib/orchestrator/internals/rescue.js +76 -79
- package/src/lib/orchestrator/internals/response-builder.d.ts +28 -1
- package/src/lib/orchestrator/internals/response-builder.js +817 -701
- package/src/lib/orchestrator/internals/route-handlers.d.ts +7 -15
- package/src/lib/orchestrator/internals/route-handlers.js +1512 -1178
- package/src/lib/orchestrator/internals/signing.js +78 -83
- package/src/lib/orchestrator/internals/svm-bridge.d.ts +2 -2
- package/src/lib/orchestrator/internals/svm-bridge.js +161 -93
- package/src/lib/orchestrator/internals/svm-helpers.d.ts +15 -1
- package/src/lib/orchestrator/internals/svm-helpers.js +68 -24
- package/src/lib/orchestrator/internals/svm-rent.d.ts +19 -1
- package/src/lib/orchestrator/internals/svm-rent.js +163 -141
- package/src/lib/orchestrator/internals/tx-transformer.js +26 -23
- package/src/lib/orchestrator/internals/uea-manager.js +89 -86
- package/src/lib/orchestrator/max-pc-for-gas.js +5 -6
- package/src/lib/orchestrator/orchestrator.js +217 -200
- package/src/lib/orchestrator/orchestrator.types.d.ts +121 -1
- package/src/lib/orchestrator/orchestrator.types.js +19 -0
- package/src/lib/orchestrator/payload-builders.d.ts +2 -2
- package/src/lib/orchestrator/payload-builders.js +26 -24
- package/src/lib/orchestrator/route-detector.js +26 -9
- package/src/lib/orchestrator/svm-idl/ix-encoder.js +1 -2
- package/src/lib/orchestrator/svm-idl/normalize-address.js +2 -2
- package/src/lib/orchestrator/svm-idl/resolve.js +1 -2
- package/src/lib/price-fetch/price-fetch.js +67 -68
- package/src/lib/progress-hook/progress-hook.js +124 -72
- package/src/lib/push-chain/push-chain.js +171 -153
- package/src/lib/push-client/push-client.js +223 -237
- package/src/lib/universal/account/account.js +349 -365
- package/src/lib/universal/signer/signer.d.ts +2 -1
- package/src/lib/universal/signer/signer.js +315 -299
- package/src/lib/universal-tx-detector/auto-detect.js +55 -60
- package/src/lib/universal-tx-detector/cascade.js +160 -172
- package/src/lib/universal-tx-detector/child-inbounds.js +67 -75
- package/src/lib/universal-tx-detector/classify.js +2 -3
- package/src/lib/universal-tx-detector/detector-svm.js +139 -147
- package/src/lib/universal-tx-detector/detector.js +145 -157
- package/src/lib/universal-tx-detector/normalize.js +7 -7
- package/src/lib/utils/external-tx-hash.js +1 -2
- package/src/lib/utils.d.ts +44 -0
- package/src/lib/utils.js +762 -683
- package/src/lib/vm-client/evm-client.js +186 -202
- package/src/lib/vm-client/svm-client.d.ts +1 -1
- package/src/lib/vm-client/svm-client.js +220 -224
- package/src/lib/vm-client/vm-client.types.d.ts +14 -2
|
@@ -26,6 +26,10 @@ export declare const SVM_FINALIZE_COMPUTE_BUFFER_LAMPORTS: bigint;
|
|
|
26
26
|
export declare const SVM_EXECUTED_SUB_TX_RENT_FALLBACK: bigint;
|
|
27
27
|
/** Devnet/mainnet rent-exempt minimum for a 165-byte SPL token account. */
|
|
28
28
|
export declare const SVM_TOKEN_ACCOUNT_RENT_FALLBACK: bigint;
|
|
29
|
+
/** Rent-exempt minimum for an 82-byte SPL mint — created on a first PC20 export. */
|
|
30
|
+
export declare const SVM_MINT_RENT_FALLBACK: bigint;
|
|
31
|
+
/** Rent-exempt minimum for the 62-byte Pc20State PDA (state.rs: 8+20+32+1+1). */
|
|
32
|
+
export declare const SVM_PC20_STATE_RENT_FALLBACK: bigint;
|
|
29
33
|
/** Back-compat export for older tests/callers: ATA rent + base finalization overhead. */
|
|
30
34
|
export declare const CEA_ATA_RENT_LAMPORTS_BUMP: bigint;
|
|
31
35
|
/** Derive CEA PDA from a 20-byte EVM address. Seeds: ["push_identity", evmBytes]. */
|
|
@@ -50,10 +54,14 @@ export interface SvmFinalizeGasBudgetInput {
|
|
|
50
54
|
splMintBase58: string | undefined;
|
|
51
55
|
/** Burn amount in token units. 0 means no SPL staging. */
|
|
52
56
|
burnAmount: bigint;
|
|
57
|
+
/** PC20 export: use the id=5 finalize rent profile instead of the SPL one. */
|
|
58
|
+
pc20?: {
|
|
59
|
+
isFirstExport: boolean;
|
|
60
|
+
};
|
|
53
61
|
}
|
|
54
62
|
export declare function gasLimitForSvmGasFeeBudget(gasFeeBudget: bigint, gasPrice: bigint): bigint;
|
|
55
63
|
type OutboundGasQuote = Awaited<ReturnType<typeof queryOutboundGasFee>>;
|
|
56
|
-
export declare function ensureSvmFinalizeGasBudgetQuote({ ctx, ueaAddress, targetChain, prc20Token, quote, splMintBase58, burnAmount, pathTag, }: {
|
|
64
|
+
export declare function ensureSvmFinalizeGasBudgetQuote({ ctx, ueaAddress, targetChain, prc20Token, quote, splMintBase58, burnAmount, pathTag, pc20, requoteFn, }: {
|
|
57
65
|
ctx: OrchestratorContext;
|
|
58
66
|
ueaAddress: `0x${string}`;
|
|
59
67
|
targetChain: ChainType;
|
|
@@ -62,6 +70,16 @@ export declare function ensureSvmFinalizeGasBudgetQuote({ ctx, ueaAddress, targe
|
|
|
62
70
|
splMintBase58: string | undefined;
|
|
63
71
|
burnAmount: bigint;
|
|
64
72
|
pathTag: string;
|
|
73
|
+
/** PC20 export: switches the floor to the id=5 rent profile. */
|
|
74
|
+
pc20?: {
|
|
75
|
+
isFirstExport: boolean;
|
|
76
|
+
};
|
|
77
|
+
/**
|
|
78
|
+
* Re-quote function for the bump path. PC20 exports MUST pass one backed by
|
|
79
|
+
* getPC20ExportGasAndFees — the default getOutboundTxGasAndFees reverts for a
|
|
80
|
+
* PC20 token, which has no PRC20 config.
|
|
81
|
+
*/
|
|
82
|
+
requoteFn?: (gasLimit: bigint) => Promise<OutboundGasQuote>;
|
|
65
83
|
}): Promise<OutboundGasQuote>;
|
|
66
84
|
/**
|
|
67
85
|
* Returns the minimum SVM `gas_fee` budget in lamports for the gateway
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.CEA_ATA_RENT_LAMPORTS_BUMP = exports.SVM_TOKEN_ACCOUNT_RENT_FALLBACK = exports.SVM_EXECUTED_SUB_TX_RENT_FALLBACK = exports.SVM_FINALIZE_COMPUTE_BUFFER_LAMPORTS = exports.SVM_SIGNATURE_FEE_LAMPORTS = void 0;
|
|
3
|
+
exports.CEA_ATA_RENT_LAMPORTS_BUMP = exports.SVM_PC20_STATE_RENT_FALLBACK = exports.SVM_MINT_RENT_FALLBACK = exports.SVM_TOKEN_ACCOUNT_RENT_FALLBACK = exports.SVM_EXECUTED_SUB_TX_RENT_FALLBACK = exports.SVM_FINALIZE_COMPUTE_BUFFER_LAMPORTS = exports.SVM_SIGNATURE_FEE_LAMPORTS = void 0;
|
|
4
4
|
exports.deriveSvmCeaPda = deriveSvmCeaPda;
|
|
5
5
|
exports.deriveAtaPubkey = deriveAtaPubkey;
|
|
6
6
|
exports.gasLimitForSvmGasFeeBudget = gasLimitForSvmGasFeeBudget;
|
|
7
7
|
exports.ensureSvmFinalizeGasBudgetQuote = ensureSvmFinalizeGasBudgetQuote;
|
|
8
8
|
exports.getSvmFinalizeGasBudget = getSvmFinalizeGasBudget;
|
|
9
9
|
exports.maybeBumpForCeaAtaRent = maybeBumpForCeaAtaRent;
|
|
10
|
-
const tslib_1 = require("tslib");
|
|
11
10
|
/**
|
|
12
11
|
* SVM finalize gas-budget helpers.
|
|
13
12
|
*
|
|
@@ -34,13 +33,17 @@ const gas_calculator_1 = require("./gas-calculator");
|
|
|
34
33
|
// they only change if Solana itself adjusts rent rates (effectively never).
|
|
35
34
|
// ---------------------------------------------------------------------------
|
|
36
35
|
/** Base Solana fee per relayer signature, mirrored from SVM gateway execute.rs. */
|
|
37
|
-
exports.SVM_SIGNATURE_FEE_LAMPORTS = BigInt(
|
|
36
|
+
exports.SVM_SIGNATURE_FEE_LAMPORTS = BigInt(5_000);
|
|
38
37
|
/** Operational buffer used by SVM gateway tests for tx fees / compute. */
|
|
39
|
-
exports.SVM_FINALIZE_COMPUTE_BUFFER_LAMPORTS = BigInt(
|
|
38
|
+
exports.SVM_FINALIZE_COMPUTE_BUFFER_LAMPORTS = BigInt(100_000);
|
|
40
39
|
/** Devnet/mainnet rent-exempt minimum for ExecutedSubTx::LEN = 8 bytes. */
|
|
41
|
-
exports.SVM_EXECUTED_SUB_TX_RENT_FALLBACK = BigInt(
|
|
40
|
+
exports.SVM_EXECUTED_SUB_TX_RENT_FALLBACK = BigInt(946_560);
|
|
42
41
|
/** Devnet/mainnet rent-exempt minimum for a 165-byte SPL token account. */
|
|
43
|
-
exports.SVM_TOKEN_ACCOUNT_RENT_FALLBACK = BigInt(
|
|
42
|
+
exports.SVM_TOKEN_ACCOUNT_RENT_FALLBACK = BigInt(2_039_280);
|
|
43
|
+
/** Rent-exempt minimum for an 82-byte SPL mint — created on a first PC20 export. */
|
|
44
|
+
exports.SVM_MINT_RENT_FALLBACK = BigInt(1_461_600);
|
|
45
|
+
/** Rent-exempt minimum for the 62-byte Pc20State PDA (state.rs: 8+20+32+1+1). */
|
|
46
|
+
exports.SVM_PC20_STATE_RENT_FALLBACK = BigInt(1_322_400);
|
|
44
47
|
/** Back-compat export for older tests/callers: ATA rent + base finalization overhead. */
|
|
45
48
|
exports.CEA_ATA_RENT_LAMPORTS_BUMP = exports.SVM_SIGNATURE_FEE_LAMPORTS +
|
|
46
49
|
exports.SVM_EXECUTED_SUB_TX_RENT_FALLBACK +
|
|
@@ -50,7 +53,7 @@ exports.CEA_ATA_RENT_LAMPORTS_BUMP = exports.SVM_SIGNATURE_FEE_LAMPORTS +
|
|
|
50
53
|
const SVM_GATEWAY_PROGRAM = new web3_js_1.PublicKey('CFVSincHYbETh2k7w6u1ENEkjbSLtveRCEBupKidw2VS');
|
|
51
54
|
const TOKEN_PROGRAM_ID = new web3_js_1.PublicKey('TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA');
|
|
52
55
|
const ASSOCIATED_TOKEN_PROGRAM_ID = new web3_js_1.PublicKey('ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL');
|
|
53
|
-
const SVM_RENT_RPC_TIMEOUT_MS =
|
|
56
|
+
const SVM_RENT_RPC_TIMEOUT_MS = 3_000;
|
|
54
57
|
// ---------------------------------------------------------------------------
|
|
55
58
|
// PDA derivations
|
|
56
59
|
// ---------------------------------------------------------------------------
|
|
@@ -66,30 +69,27 @@ function deriveAtaPubkey(owner, mint) {
|
|
|
66
69
|
return ata;
|
|
67
70
|
}
|
|
68
71
|
function getRpcUrl(ctx, targetChain) {
|
|
69
|
-
|
|
70
|
-
|
|
72
|
+
return (ctx.rpcUrls?.[targetChain]?.[0] ??
|
|
73
|
+
chain_1.CHAIN_INFO[targetChain]?.defaultRPC?.[0]);
|
|
71
74
|
}
|
|
72
75
|
function isAccountInitialized(info) {
|
|
73
76
|
return info !== null && info.data.length > 0;
|
|
74
77
|
}
|
|
75
|
-
function withSvmRentRpcTimeout(promise, label) {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
clearTimeout(timer);
|
|
91
|
-
}
|
|
92
|
-
});
|
|
78
|
+
async function withSvmRentRpcTimeout(promise, label) {
|
|
79
|
+
let timer;
|
|
80
|
+
try {
|
|
81
|
+
return await Promise.race([
|
|
82
|
+
promise,
|
|
83
|
+
new Promise((_, reject) => {
|
|
84
|
+
timer = setTimeout(() => reject(new Error(`${label} timed out after ${SVM_RENT_RPC_TIMEOUT_MS}ms`)), SVM_RENT_RPC_TIMEOUT_MS);
|
|
85
|
+
timer.unref?.();
|
|
86
|
+
}),
|
|
87
|
+
]);
|
|
88
|
+
}
|
|
89
|
+
finally {
|
|
90
|
+
if (timer)
|
|
91
|
+
clearTimeout(timer);
|
|
92
|
+
}
|
|
93
93
|
}
|
|
94
94
|
function gasLimitForSvmGasFeeBudget(gasFeeBudget, gasPrice) {
|
|
95
95
|
if (gasPrice <= BigInt(0)) {
|
|
@@ -103,99 +103,123 @@ function resolveSvmGasLimitUsed(quote) {
|
|
|
103
103
|
quote.gasPrice <= BigInt(0)) {
|
|
104
104
|
return quote;
|
|
105
105
|
}
|
|
106
|
-
return
|
|
106
|
+
return {
|
|
107
|
+
...quote,
|
|
108
|
+
gasLimitUsed: gasLimitForSvmGasFeeBudget(quote.gasFee, quote.gasPrice),
|
|
109
|
+
};
|
|
107
110
|
}
|
|
108
|
-
function ensureSvmFinalizeGasBudgetQuote(
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
});
|
|
117
|
-
if (quote.gasFee >= minGasFee) {
|
|
118
|
-
const resolvedQuote = resolveSvmGasLimitUsed(quote);
|
|
119
|
-
(0, context_1.printLog)(ctx, `${pathTag} — SVM finalize gas budget ok: gasFee=${resolvedQuote.gasFee.toString()}, ` +
|
|
120
|
-
`minimum=${minGasFee.toString()}, gasLimit=${resolvedQuote.gasLimitUsed.toString()}`);
|
|
121
|
-
return resolvedQuote;
|
|
122
|
-
}
|
|
123
|
-
const bumpedGasLimit = gasLimitForSvmGasFeeBudget(minGasFee, quote.gasPrice);
|
|
124
|
-
(0, context_1.printLog)(ctx, `${pathTag} — bumping SVM gasLimit ${quote.gasLimitUsed.toString()} → ${bumpedGasLimit.toString()}; ` +
|
|
125
|
-
`gasFee=${quote.gasFee.toString()} below finalize minimum=${minGasFee.toString()}`);
|
|
126
|
-
const bumpedQuote = yield (0, gas_calculator_1.queryOutboundGasFee)(ctx, prc20Token, bumpedGasLimit, targetChain);
|
|
127
|
-
if (bumpedQuote.gasFee < minGasFee) {
|
|
128
|
-
(0, context_1.printLog)(ctx, `${pathTag} — WARNING: bumped SVM gasFee=${bumpedQuote.gasFee.toString()} ` +
|
|
129
|
-
`still below finalize minimum=${minGasFee.toString()}`);
|
|
130
|
-
}
|
|
131
|
-
return resolveSvmGasLimitUsed(bumpedQuote);
|
|
111
|
+
async function ensureSvmFinalizeGasBudgetQuote({ ctx, ueaAddress, targetChain, prc20Token, quote, splMintBase58, burnAmount, pathTag, pc20, requoteFn, }) {
|
|
112
|
+
const minGasFee = await getSvmFinalizeGasBudget({
|
|
113
|
+
ctx,
|
|
114
|
+
ueaAddress,
|
|
115
|
+
targetChain,
|
|
116
|
+
splMintBase58,
|
|
117
|
+
burnAmount,
|
|
118
|
+
pc20,
|
|
132
119
|
});
|
|
120
|
+
if (quote.gasFee >= minGasFee) {
|
|
121
|
+
const resolvedQuote = resolveSvmGasLimitUsed(quote);
|
|
122
|
+
(0, context_1.printLog)(ctx, `${pathTag} — SVM finalize gas budget ok: gasFee=${resolvedQuote.gasFee.toString()}, ` +
|
|
123
|
+
`minimum=${minGasFee.toString()}, gasLimit=${resolvedQuote.gasLimitUsed.toString()}`);
|
|
124
|
+
return resolvedQuote;
|
|
125
|
+
}
|
|
126
|
+
const bumpedGasLimit = gasLimitForSvmGasFeeBudget(minGasFee, quote.gasPrice);
|
|
127
|
+
(0, context_1.printLog)(ctx, `${pathTag} — bumping SVM gasLimit ${quote.gasLimitUsed.toString()} → ${bumpedGasLimit.toString()}; ` +
|
|
128
|
+
`gasFee=${quote.gasFee.toString()} below finalize minimum=${minGasFee.toString()}`);
|
|
129
|
+
const bumpedQuote = requoteFn
|
|
130
|
+
? await requoteFn(bumpedGasLimit)
|
|
131
|
+
: await (0, gas_calculator_1.queryOutboundGasFee)(ctx, prc20Token, bumpedGasLimit, targetChain);
|
|
132
|
+
if (bumpedQuote.gasFee < minGasFee) {
|
|
133
|
+
(0, context_1.printLog)(ctx, `${pathTag} — WARNING: bumped SVM gasFee=${bumpedQuote.gasFee.toString()} ` +
|
|
134
|
+
`still below finalize minimum=${minGasFee.toString()}`);
|
|
135
|
+
}
|
|
136
|
+
return resolveSvmGasLimitUsed(bumpedQuote);
|
|
133
137
|
}
|
|
134
138
|
/**
|
|
135
139
|
* Returns the minimum SVM `gas_fee` budget in lamports for the gateway
|
|
136
140
|
* finalize instruction, including a small compute buffer. If RPC is not
|
|
137
141
|
* available, falls back to Solana protocol rent constants.
|
|
138
142
|
*/
|
|
139
|
-
function getSvmFinalizeGasBudget(input) {
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
executedTxRent +
|
|
160
|
-
ataRent +
|
|
161
|
-
exports.SVM_FINALIZE_COMPUTE_BUFFER_LAMPORTS).toString()}`);
|
|
162
|
-
return (exports.SVM_SIGNATURE_FEE_LAMPORTS +
|
|
163
|
-
executedTxRent +
|
|
164
|
-
ataRent +
|
|
165
|
-
exports.SVM_FINALIZE_COMPUTE_BUFFER_LAMPORTS);
|
|
166
|
-
}
|
|
167
|
-
try {
|
|
168
|
-
const conn = new web3_js_1.Connection(rpcUrl, 'confirmed');
|
|
169
|
-
executedTxRent = BigInt(yield withSvmRentRpcTimeout(conn.getMinimumBalanceForRentExemption(8), 'getMinimumBalanceForRentExemption(8)'));
|
|
170
|
-
if (needsSplAta && splMintBase58) {
|
|
171
|
-
const ceaPda = deriveSvmCeaPda(ueaAddress);
|
|
172
|
-
const splMint = new web3_js_1.PublicKey(splMintBase58);
|
|
173
|
-
const ceaAta = deriveAtaPubkey(ceaPda, splMint);
|
|
174
|
-
const info = yield withSvmRentRpcTimeout(conn.getAccountInfo(ceaAta), `getAccountInfo(${ceaAta.toBase58()})`);
|
|
175
|
-
if (!isAccountInitialized(info)) {
|
|
176
|
-
ataRent = BigInt(yield withSvmRentRpcTimeout(conn.getMinimumBalanceForRentExemption(165), 'getMinimumBalanceForRentExemption(165)'));
|
|
177
|
-
(0, context_1.printLog)(ctx, `getSvmFinalizeGasBudget — CEA ATA ${ceaAta.toBase58()} not deployed on ${targetChain}; ` +
|
|
178
|
-
`including ${ataRent.toString()} lamports ATA rent`);
|
|
179
|
-
}
|
|
180
|
-
else {
|
|
181
|
-
(0, context_1.printLog)(ctx, `getSvmFinalizeGasBudget — CEA ATA ${ceaAta.toBase58()} already deployed on ${targetChain}; no ATA rent`);
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
catch (err) {
|
|
186
|
-
ataRent = exports.SVM_TOKEN_ACCOUNT_RENT_FALLBACK;
|
|
187
|
-
(0, context_1.printLog)(ctx, `getSvmFinalizeGasBudget — RPC error on ${targetChain}: ` +
|
|
188
|
-
`${err instanceof Error ? err.message : String(err)}; using fallback rents`);
|
|
143
|
+
async function getSvmFinalizeGasBudget(input) {
|
|
144
|
+
const { ctx, ueaAddress, targetChain, splMintBase58, burnAmount, pc20 } = input;
|
|
145
|
+
const needsSplAta = Boolean(splMintBase58) && burnAmount > BigInt(0);
|
|
146
|
+
// PC20 export finalize (id=5) has its own rent profile — settle_pc20_finalize_gas
|
|
147
|
+
// (pc20.rs) requires gas_fee to cover, beyond the base costs:
|
|
148
|
+
// - CEA ATA rent for the *wrapper mint* (created at settlement);
|
|
149
|
+
// - on a first export, the mint account (82B) and Pc20State PDA (62B) rents.
|
|
150
|
+
// The on-chain quote does not know about Solana rent, so without this floor a
|
|
151
|
+
// first export reverts InsufficientGasBudget on the destination — after the
|
|
152
|
+
// source token is locked. Fallback constants are used rather than RPC reads:
|
|
153
|
+
// the mint does not exist yet on a first export, so there is nothing to query,
|
|
154
|
+
// and rent-exempt minimums are Solana protocol values that effectively never
|
|
155
|
+
// change.
|
|
156
|
+
if (pc20) {
|
|
157
|
+
let budget = exports.SVM_SIGNATURE_FEE_LAMPORTS +
|
|
158
|
+
exports.SVM_EXECUTED_SUB_TX_RENT_FALLBACK +
|
|
159
|
+
exports.SVM_TOKEN_ACCOUNT_RENT_FALLBACK + // CEA ATA for the wrapper mint
|
|
160
|
+
exports.SVM_FINALIZE_COMPUTE_BUFFER_LAMPORTS;
|
|
161
|
+
if (pc20.isFirstExport) {
|
|
162
|
+
budget += exports.SVM_MINT_RENT_FALLBACK + exports.SVM_PC20_STATE_RENT_FALLBACK;
|
|
189
163
|
}
|
|
164
|
+
(0, context_1.printLog)(ctx, `getSvmFinalizeGasBudget — PC20 budget=${budget.toString()} ` +
|
|
165
|
+
`(isFirstExport=${pc20.isFirstExport})`);
|
|
166
|
+
return budget;
|
|
167
|
+
}
|
|
168
|
+
const rpcUrl = getRpcUrl(ctx, targetChain);
|
|
169
|
+
let executedTxRent = exports.SVM_EXECUTED_SUB_TX_RENT_FALLBACK;
|
|
170
|
+
let ataRent = BigInt(0);
|
|
171
|
+
if (!needsSplAta) {
|
|
190
172
|
const budget = exports.SVM_SIGNATURE_FEE_LAMPORTS +
|
|
191
173
|
executedTxRent +
|
|
192
174
|
ataRent +
|
|
193
175
|
exports.SVM_FINALIZE_COMPUTE_BUFFER_LAMPORTS;
|
|
194
|
-
(0, context_1.printLog)(ctx, `getSvmFinalizeGasBudget —
|
|
195
|
-
`
|
|
196
|
-
`computeBuffer=${exports.SVM_FINALIZE_COMPUTE_BUFFER_LAMPORTS})`);
|
|
176
|
+
(0, context_1.printLog)(ctx, `getSvmFinalizeGasBudget — no SPL ATA needed for ${targetChain}; ` +
|
|
177
|
+
`using fallback base budget ${budget.toString()}`);
|
|
197
178
|
return budget;
|
|
198
|
-
}
|
|
179
|
+
}
|
|
180
|
+
if (!rpcUrl) {
|
|
181
|
+
ataRent = exports.SVM_TOKEN_ACCOUNT_RENT_FALLBACK;
|
|
182
|
+
(0, context_1.printLog)(ctx, `getSvmFinalizeGasBudget — no Solana RPC URL for ${targetChain}; ` +
|
|
183
|
+
`using fallback budget ${(exports.SVM_SIGNATURE_FEE_LAMPORTS +
|
|
184
|
+
executedTxRent +
|
|
185
|
+
ataRent +
|
|
186
|
+
exports.SVM_FINALIZE_COMPUTE_BUFFER_LAMPORTS).toString()}`);
|
|
187
|
+
return (exports.SVM_SIGNATURE_FEE_LAMPORTS +
|
|
188
|
+
executedTxRent +
|
|
189
|
+
ataRent +
|
|
190
|
+
exports.SVM_FINALIZE_COMPUTE_BUFFER_LAMPORTS);
|
|
191
|
+
}
|
|
192
|
+
try {
|
|
193
|
+
const conn = new web3_js_1.Connection(rpcUrl, 'confirmed');
|
|
194
|
+
executedTxRent = BigInt(await withSvmRentRpcTimeout(conn.getMinimumBalanceForRentExemption(8), 'getMinimumBalanceForRentExemption(8)'));
|
|
195
|
+
if (needsSplAta && splMintBase58) {
|
|
196
|
+
const ceaPda = deriveSvmCeaPda(ueaAddress);
|
|
197
|
+
const splMint = new web3_js_1.PublicKey(splMintBase58);
|
|
198
|
+
const ceaAta = deriveAtaPubkey(ceaPda, splMint);
|
|
199
|
+
const info = await withSvmRentRpcTimeout(conn.getAccountInfo(ceaAta), `getAccountInfo(${ceaAta.toBase58()})`);
|
|
200
|
+
if (!isAccountInitialized(info)) {
|
|
201
|
+
ataRent = BigInt(await withSvmRentRpcTimeout(conn.getMinimumBalanceForRentExemption(165), 'getMinimumBalanceForRentExemption(165)'));
|
|
202
|
+
(0, context_1.printLog)(ctx, `getSvmFinalizeGasBudget — CEA ATA ${ceaAta.toBase58()} not deployed on ${targetChain}; ` +
|
|
203
|
+
`including ${ataRent.toString()} lamports ATA rent`);
|
|
204
|
+
}
|
|
205
|
+
else {
|
|
206
|
+
(0, context_1.printLog)(ctx, `getSvmFinalizeGasBudget — CEA ATA ${ceaAta.toBase58()} already deployed on ${targetChain}; no ATA rent`);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
catch (err) {
|
|
211
|
+
ataRent = exports.SVM_TOKEN_ACCOUNT_RENT_FALLBACK;
|
|
212
|
+
(0, context_1.printLog)(ctx, `getSvmFinalizeGasBudget — RPC error on ${targetChain}: ` +
|
|
213
|
+
`${err instanceof Error ? err.message : String(err)}; using fallback rents`);
|
|
214
|
+
}
|
|
215
|
+
const budget = exports.SVM_SIGNATURE_FEE_LAMPORTS +
|
|
216
|
+
executedTxRent +
|
|
217
|
+
ataRent +
|
|
218
|
+
exports.SVM_FINALIZE_COMPUTE_BUFFER_LAMPORTS;
|
|
219
|
+
(0, context_1.printLog)(ctx, `getSvmFinalizeGasBudget — budget=${budget.toString()} ` +
|
|
220
|
+
`(signature=${exports.SVM_SIGNATURE_FEE_LAMPORTS}, executedTxRent=${executedTxRent}, ataRent=${ataRent}, ` +
|
|
221
|
+
`computeBuffer=${exports.SVM_FINALIZE_COMPUTE_BUFFER_LAMPORTS})`);
|
|
222
|
+
return budget;
|
|
199
223
|
}
|
|
200
224
|
/**
|
|
201
225
|
* Returns the (possibly bumped) effectiveGasLimit. Logs the decision via
|
|
@@ -203,41 +227,39 @@ function getSvmFinalizeGasBudget(input) {
|
|
|
203
227
|
* the input unchanged — better to risk one underflow than to block all SPL
|
|
204
228
|
* outbounds on RPC flake; pre-flight will surface insufficient gas anyway.
|
|
205
229
|
*/
|
|
206
|
-
function maybeBumpForCeaAtaRent(input) {
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
return bumped;
|
|
232
|
-
}
|
|
233
|
-
(0, context_1.printLog)(ctx, `maybeBumpForCeaAtaRent — CEA ATA ${ceaAta.toBase58()} already deployed on ${targetChain}; no rent bump`);
|
|
234
|
-
return effectiveGasLimit;
|
|
235
|
-
}
|
|
236
|
-
catch (err) {
|
|
237
|
-
(0, context_1.printLog)(ctx, `maybeBumpForCeaAtaRent — RPC error querying CEA ATA on ${targetChain}: ` +
|
|
238
|
-
`${err instanceof Error ? err.message : String(err)}; proceeding without bump`);
|
|
239
|
-
return effectiveGasLimit;
|
|
230
|
+
async function maybeBumpForCeaAtaRent(input) {
|
|
231
|
+
const { ctx, ueaAddress, targetChain, splMintBase58, burnAmount, effectiveGasLimit, } = input;
|
|
232
|
+
// Only applies to SPL outbounds. Native SOL outbounds use the gateway's
|
|
233
|
+
// calculateSolExecuteFees which has no ATA conditional.
|
|
234
|
+
if (!splMintBase58 || burnAmount === BigInt(0)) {
|
|
235
|
+
return effectiveGasLimit;
|
|
236
|
+
}
|
|
237
|
+
const rpcUrl = getRpcUrl(ctx, targetChain);
|
|
238
|
+
if (!rpcUrl) {
|
|
239
|
+
(0, context_1.printLog)(ctx, `maybeBumpForCeaAtaRent — no Solana RPC URL for ${targetChain}; skipping rent bump`);
|
|
240
|
+
return effectiveGasLimit;
|
|
241
|
+
}
|
|
242
|
+
try {
|
|
243
|
+
const ceaPda = deriveSvmCeaPda(ueaAddress);
|
|
244
|
+
const splMint = new web3_js_1.PublicKey(splMintBase58);
|
|
245
|
+
const ceaAta = deriveAtaPubkey(ceaPda, splMint);
|
|
246
|
+
const conn = new web3_js_1.Connection(rpcUrl, 'confirmed');
|
|
247
|
+
const info = await withSvmRentRpcTimeout(conn.getAccountInfo(ceaAta), `getAccountInfo(${ceaAta.toBase58()})`);
|
|
248
|
+
const ataExists = info !== null && info.data.length > 0;
|
|
249
|
+
if (!ataExists) {
|
|
250
|
+
const bumped = effectiveGasLimit + exports.CEA_ATA_RENT_LAMPORTS_BUMP;
|
|
251
|
+
(0, context_1.printLog)(ctx, `maybeBumpForCeaAtaRent — CEA ATA ${ceaAta.toBase58()} not deployed on ${targetChain}; ` +
|
|
252
|
+
`bumping effectiveGasLimit ${effectiveGasLimit} → ${bumped} ` +
|
|
253
|
+
`(+${exports.CEA_ATA_RENT_LAMPORTS_BUMP} lamports for ATA rent + exec rent + compute buffer)`);
|
|
254
|
+
return bumped;
|
|
240
255
|
}
|
|
241
|
-
|
|
256
|
+
(0, context_1.printLog)(ctx, `maybeBumpForCeaAtaRent — CEA ATA ${ceaAta.toBase58()} already deployed on ${targetChain}; no rent bump`);
|
|
257
|
+
return effectiveGasLimit;
|
|
258
|
+
}
|
|
259
|
+
catch (err) {
|
|
260
|
+
(0, context_1.printLog)(ctx, `maybeBumpForCeaAtaRent — RPC error querying CEA ATA on ${targetChain}: ` +
|
|
261
|
+
`${err instanceof Error ? err.message : String(err)}; proceeding without bump`);
|
|
262
|
+
return effectiveGasLimit;
|
|
263
|
+
}
|
|
242
264
|
}
|
|
243
265
|
//# sourceMappingURL=svm-rent.js.map
|
|
@@ -50,11 +50,10 @@ function transformToUniversalTxReceipt(receipt, originalTxResponse) {
|
|
|
50
50
|
// Progress Event Reconstruction
|
|
51
51
|
// ============================================================================
|
|
52
52
|
function reconstructProgressEvents(universalTxResponse, universalTxData) {
|
|
53
|
-
var _a, _b, _c;
|
|
54
53
|
const route = universalTxResponse.route;
|
|
55
|
-
const pcTx =
|
|
56
|
-
const isOutboundFailed =
|
|
57
|
-
const isPcFailed =
|
|
54
|
+
const pcTx = universalTxData?.pcTx?.[0];
|
|
55
|
+
const isOutboundFailed = universalTxData?.universalStatus === types_1.UniversalTxStatus.OUTBOUND_FAILED;
|
|
56
|
+
const isPcFailed = pcTx?.status === 'FAILED';
|
|
58
57
|
// R1 fallback keeps the inclusive view (any terminal failure → 199-02).
|
|
59
58
|
// R2 and R3 reconstructors narrow to Push-chain-only failures (see call
|
|
60
59
|
// sites below) — an outbound-leg revert is re-detected during wait() by
|
|
@@ -62,7 +61,7 @@ function reconstructProgressEvents(universalTxResponse, universalTxData) {
|
|
|
62
61
|
// scoped phase ('outbound' + source-chain). Emitting in both places
|
|
63
62
|
// would double-fire the terminal with a misleading 'push' title on top.
|
|
64
63
|
const isFailed = isPcFailed || isOutboundFailed;
|
|
65
|
-
const pcErrorMsg =
|
|
64
|
+
const pcErrorMsg = pcTx?.errorMsg
|
|
66
65
|
? (0, formatters_1.normalizePcInsufficientFundsError)(pcTx.errorMsg)
|
|
67
66
|
: 'Unknown error';
|
|
68
67
|
const errorMsg = isOutboundFailed
|
|
@@ -82,7 +81,7 @@ function reconstructProgressEvents(universalTxResponse, universalTxData) {
|
|
|
82
81
|
// carries one UniversalTx with multiple outboundTx entries; wrap the
|
|
83
82
|
// per-leg R2/R3 backbones with the SEND-TX-001 / 002-xx / 999-xx markers
|
|
84
83
|
// so replay parity matches live cascade emission.
|
|
85
|
-
if ((
|
|
84
|
+
if ((universalTxData?.outboundTx?.length ?? 0) > 1) {
|
|
86
85
|
return reconstructMultichain(universalTxResponse, universalTxData, isFailed, errorMsg);
|
|
87
86
|
}
|
|
88
87
|
if (route === route_detector_1.TransactionRoute.UOA_TO_CEA) {
|
|
@@ -132,10 +131,9 @@ function reconstructProgressEvents(universalTxResponse, universalTxData) {
|
|
|
132
131
|
return events;
|
|
133
132
|
}
|
|
134
133
|
function reconstructR2(universalTxResponse, universalTxData, isFailed, errorMsg) {
|
|
135
|
-
var _a, _b, _c, _d, _e, _f, _g;
|
|
136
134
|
const events = [];
|
|
137
|
-
const targetChain = (
|
|
138
|
-
const targetAddress =
|
|
135
|
+
const targetChain = (universalTxResponse.chain ?? 'external');
|
|
136
|
+
const targetAddress = universalTxData?.outboundTx?.[0]?.recipient ?? universalTxResponse.to;
|
|
139
137
|
events.push(progress_hook_1.default[progress_hook_types_1.PROGRESS_HOOK.SEND_TX_201](targetChain, targetAddress));
|
|
140
138
|
events.push(progress_hook_1.default[progress_hook_types_1.PROGRESS_HOOK.SEND_TX_202_01](targetChain));
|
|
141
139
|
// Reconstruction: gas split unavailable from historical data — pass zeroes
|
|
@@ -151,7 +149,7 @@ function reconstructR2(universalTxResponse, universalTxData, isFailed, errorMsg)
|
|
|
151
149
|
// had a non-zero burn amount (proxy for "user supplied funds.amount > 0").
|
|
152
150
|
// Values are zero-placeholders matching the existing 202-02 pattern.
|
|
153
151
|
const ueaFrom = universalTxResponse.from;
|
|
154
|
-
const burnAmount = BigInt(
|
|
152
|
+
const burnAmount = BigInt(universalTxData?.outboundTx?.[0]?.amount ?? '0');
|
|
155
153
|
if (burnAmount > BigInt(0)) {
|
|
156
154
|
events.push(progress_hook_1.default[progress_hook_types_1.PROGRESS_HOOK.SEND_TX_203_03](BigInt(0), BigInt(0), true, ueaFrom, 'R2_EVM', { kind: 'PRC20' }));
|
|
157
155
|
}
|
|
@@ -166,10 +164,9 @@ function reconstructR2(universalTxResponse, universalTxData, isFailed, errorMsg)
|
|
|
166
164
|
return events;
|
|
167
165
|
}
|
|
168
166
|
function reconstructR3(universalTxResponse, universalTxData, isFailed, errorMsg) {
|
|
169
|
-
var _a, _b, _c, _d;
|
|
170
167
|
const events = [];
|
|
171
|
-
const sourceChain = (
|
|
172
|
-
const ceaAddress =
|
|
168
|
+
const sourceChain = (universalTxResponse.chain ?? 'source');
|
|
169
|
+
const ceaAddress = universalTxData?.outboundTx?.[0]?.recipient ?? universalTxResponse.to;
|
|
173
170
|
events.push(progress_hook_1.default[progress_hook_types_1.PROGRESS_HOOK.SEND_TX_301](sourceChain, ceaAddress));
|
|
174
171
|
events.push(progress_hook_1.default[progress_hook_types_1.PROGRESS_HOOK.SEND_TX_302_01](sourceChain));
|
|
175
172
|
events.push(progress_hook_1.default[progress_hook_types_1.PROGRESS_HOOK.SEND_TX_302_02](sourceChain, BigInt(0), BigInt(0)));
|
|
@@ -205,7 +202,7 @@ function decodeUeaMulticall(data) {
|
|
|
205
202
|
const [tuples] = (0, viem_1.decodeAbiParameters)([payload_builders_1.MULTICALL_TUPLE_TYPE], body);
|
|
206
203
|
return tuples;
|
|
207
204
|
}
|
|
208
|
-
catch
|
|
205
|
+
catch {
|
|
209
206
|
return null;
|
|
210
207
|
}
|
|
211
208
|
}
|
|
@@ -260,14 +257,13 @@ function decodeR3MergedInnerCount(outboundPayload) {
|
|
|
260
257
|
if (pushCalls)
|
|
261
258
|
return pushCalls.length;
|
|
262
259
|
}
|
|
263
|
-
catch
|
|
260
|
+
catch {
|
|
264
261
|
// fall through to next outer call
|
|
265
262
|
}
|
|
266
263
|
}
|
|
267
264
|
return 0;
|
|
268
265
|
}
|
|
269
266
|
function reconstructMultichain(universalTxResponse, universalTxData, isFailed, errorMsg) {
|
|
270
|
-
var _a, _b, _c, _d, _e;
|
|
271
267
|
const events = [];
|
|
272
268
|
const outbounds = universalTxData.outboundTx;
|
|
273
269
|
// Merged-R1 recovery: each R3 outbound's payload embeds the
|
|
@@ -310,7 +306,6 @@ function reconstructMultichain(universalTxResponse, universalTxData, isFailed, e
|
|
|
310
306
|
let failedAt = null;
|
|
311
307
|
let failureMsg = errorMsg;
|
|
312
308
|
outbounds.forEach((ob, i) => {
|
|
313
|
-
var _a, _b;
|
|
314
309
|
const hopNum = i + 1;
|
|
315
310
|
const fromChain = i === 0 ? sourceChain : outbounds[i - 1].destinationChain;
|
|
316
311
|
const toChain = ob.destinationChain;
|
|
@@ -318,12 +313,19 @@ function reconstructMultichain(universalTxResponse, universalTxData, isFailed, e
|
|
|
318
313
|
// Build a single-leg view so the per-leg reconstructors (R2/R3) emit
|
|
319
314
|
// their usual backbone. We narrow `outboundTx` to this leg so any field
|
|
320
315
|
// reads (e.g. `outboundTx[0].recipient`) resolve to this leg's data.
|
|
321
|
-
const legResponse =
|
|
322
|
-
|
|
316
|
+
const legResponse = {
|
|
317
|
+
...universalTxResponse,
|
|
318
|
+
chain: toChain,
|
|
319
|
+
chainNamespace: toChain,
|
|
320
|
+
};
|
|
321
|
+
const legData = {
|
|
322
|
+
...universalTxData,
|
|
323
|
+
outboundTx: [ob],
|
|
324
|
+
};
|
|
323
325
|
const payload = (ob.payload || '').toLowerCase();
|
|
324
326
|
const isR3Leg = payload.includes(SEND_UNIVERSAL_TX_TO_UEA_SELECTOR);
|
|
325
327
|
const legFailed = ob.outboundStatus === types_2.OutboundStatus.REVERTED;
|
|
326
|
-
const legError = ob.abortReason ||
|
|
328
|
+
const legError = ob.abortReason || ob.observedTx?.errorMsg || 'leg execution failed';
|
|
327
329
|
if (isR3Leg) {
|
|
328
330
|
events.push(...reconstructR3(legResponse, legData, legFailed, legError));
|
|
329
331
|
}
|
|
@@ -332,7 +334,7 @@ function reconstructMultichain(universalTxResponse, universalTxData, isFailed, e
|
|
|
332
334
|
}
|
|
333
335
|
if (!legFailed) {
|
|
334
336
|
if (hopNum < hopCount) {
|
|
335
|
-
const txHash =
|
|
337
|
+
const txHash = ob.observedTx?.txHash || legResponse.hash;
|
|
336
338
|
events.push(isR3Leg
|
|
337
339
|
? progress_hook_1.default[progress_hook_types_1.PROGRESS_HOOK.SEND_TX_399_99](toChain, txHash)
|
|
338
340
|
: progress_hook_1.default[progress_hook_types_1.PROGRESS_HOOK.SEND_TX_299_99](toChain, txHash));
|
|
@@ -344,9 +346,10 @@ function reconstructMultichain(universalTxResponse, universalTxData, isFailed, e
|
|
|
344
346
|
failureMsg = legError;
|
|
345
347
|
}
|
|
346
348
|
});
|
|
347
|
-
const finalObservedTxHash =
|
|
349
|
+
const finalObservedTxHash = [...outbounds].reverse().find((ob) => ob.observedTx?.txHash)?.observedTx
|
|
350
|
+
?.txHash ?? universalTxResponse.hash;
|
|
348
351
|
const failedObservedTxHash = failedAt !== null
|
|
349
|
-
?
|
|
352
|
+
? outbounds[failedAt - 1]?.observedTx?.txHash
|
|
350
353
|
: undefined;
|
|
351
354
|
if (failedAt !== null) {
|
|
352
355
|
events.push(progress_hook_1.default[progress_hook_types_1.PROGRESS_HOOK.SEND_TX_999_02](failedAt, hopCount, failureMsg, failedObservedTxHash, universalTxResponse.hash));
|