Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion services/ymax-planner/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@
"@agoric/internal": "workspace:*",
"@agoric/orchestration": "workspace:*",
"@agoric/portfolio-api": "workspace:^",
"@axelarjs/api": "^0.4.4",
"@cosmjs/crypto": "^0.36.0",
"@cosmjs/encoding": "^0.36.0",
"@cosmjs/proto-signing": "^0.36.0",
Expand Down
133 changes: 0 additions & 133 deletions services/ymax-planner/src/axelarscan-utils.ts

This file was deleted.

95 changes: 43 additions & 52 deletions services/ymax-planner/src/pending-tx-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,7 @@ import type {
UsdcAddresses,
} from './support.ts';
import { lookBackCctp, watchCctpTransfer } from './watchers/cctp-watcher.ts';
import {
lookBackGmp,
WATCH_GMP_ABORTED,
watchGmp,
} from './watchers/gmp-watcher.ts';
import { lookBackGmp, watchGmp } from './watchers/gmp-watcher.ts';
import {
watchSmartWalletTx,
lookBackSmartWalletTx,
Expand All @@ -42,7 +38,8 @@ import type { YdsNotifier } from './yds-notifier.ts';
export type EvmChain = keyof typeof AxelarChain;

export type WatcherResult = {
found: boolean;
settled: boolean;
success?: boolean;
txHash?: string;
};

Expand Down Expand Up @@ -152,7 +149,7 @@ const cctpMonitor: PendingTxMonitor<CctpTx, EvmContext> = {
txId,
});
void liveResultP.then(result => {
if (result.found) {
if (result.settled) {
log(`${logPrefix} Live mode completed`);
abortController.abort();
}
Expand All @@ -173,7 +170,7 @@ const cctpMonitor: PendingTxMonitor<CctpTx, EvmContext> = {
txId,
});

if (transferResult.found) {
if (transferResult.settled) {
// Found in lookback, cancel live mode
const reason = `${logPrefix} Lookback found transaction`;
log(reason);
Expand All @@ -191,11 +188,13 @@ const cctpMonitor: PendingTxMonitor<CctpTx, EvmContext> = {
return;
}

await resolvePendingTx({
signingSmartWalletKit: ctx.signingSmartWalletKit,
txId,
status: transferResult?.found ? TxStatus.SUCCESS : TxStatus.FAILED,
});
transferResult.settled &&
(await resolvePendingTx({
signingSmartWalletKit: ctx.signingSmartWalletKit,
txId,
status:
transferResult.success !== false ? TxStatus.SUCCESS : TxStatus.FAILED,
}));

if (transferResult?.txHash) {
await ctx.ydsNotifier?.notifySettlement(txId, transferResult.txHash);
Expand All @@ -209,7 +208,7 @@ const gmpMonitor: PendingTxMonitor<GmpTx, EvmContext> = {
watch: async (ctx, tx, log, opts) => {
await null;

const { txId, destinationAddress } = tx;
const { txId, destinationAddress, sourceAddress } = tx;
const logPrefix = `[${txId}]`;

if (opts.signal?.aborted) {
Expand All @@ -219,6 +218,8 @@ const gmpMonitor: PendingTxMonitor<GmpTx, EvmContext> = {

// Parse destinationAddress format: 'eip155:42161:0x126cf3AC9ea12794Ff50f56727C7C66E26D9C092'
assert(destinationAddress, `${logPrefix} Missing destinationAddress`);
assert(sourceAddress, `${logPrefix} Missing sourceAddress`);

const { namespace, reference, accountAddress } =
parseAccountId(destinationAddress);
const caipId: CaipChainId = `${namespace}:${reference}`;
Expand All @@ -227,10 +228,14 @@ const gmpMonitor: PendingTxMonitor<GmpTx, EvmContext> = {

const provider = ctx.evmProviders[caipId] as WebSocketProvider;

// Extract the address portion from sourceAddress (format: 'cosmos:agoric-3:agoric1...')
const lcaAddress = parseAccountId(sourceAddress).accountAddress;

const watchArgs = {
provider,
contractAddress: accountAddress as `0x${string}`,
txId,
expectedSourceAddress: lcaAddress,
log: (msg, ...args) => log(`${logPrefix} ${msg}`, ...args),
};

Expand All @@ -243,8 +248,6 @@ const gmpMonitor: PendingTxMonitor<GmpTx, EvmContext> = {
signal: opts.signal,
kvStore: ctx.kvStore,
makeAbortController: ctx.makeAbortController,
axelarApiUrl: ctx.axelarApiUrl,
fetch: ctx.fetch,
});
} else {
// Lookback mode with concurrent live watching
Expand All @@ -260,31 +263,18 @@ const gmpMonitor: PendingTxMonitor<GmpTx, EvmContext> = {
signal: abortController.signal,
kvStore: ctx.kvStore,
makeAbortController: ctx.makeAbortController,
axelarApiUrl: ctx.axelarApiUrl,
fetch: ctx.fetch,
});

// Attach handler to abort lookback if live mode completes first with
// a definitive result. This handler does NOT resolve the transaction -
// resolution happens once at the end to prevent duplicate resolutions.
void liveResultP
.then(result => {
// Abort lookback only if live mode has a definitive answer:
// - Transaction found successfully (result.found === true)
// - Transaction found but failed (result.rejectionReason present)
// If neither (just timed out), let lookback continue - it might find it.
if (result.found || result.rejectionReason) {
const reason = `${logPrefix} Live mode completed`;
log(reason);
abortController.abort(reason);
}
})
.catch(error => {
// If lookback aborted live mode, no action needed
if (error !== WATCH_GMP_ABORTED) {
throw error;
}
});
void liveResultP.then(result => {
if (result.settled) {
const reason = `${logPrefix} Live mode completed`;
log(reason);
abortController.abort(reason);
}
Comment on lines +272 to +276
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about handling tx not settled here?

});

await null;
// Wait for at least one block to ensure overlap between lookback and live mode
Expand All @@ -302,7 +292,7 @@ const gmpMonitor: PendingTxMonitor<GmpTx, EvmContext> = {
});

// Determine which result to use based on what completed successfully
if (lookBackResult.found) {
if (lookBackResult.settled) {
// Found in lookback, cancel live mode
transferResult = lookBackResult;
const reason = `${logPrefix} Lookback found transaction`;
Expand All @@ -321,14 +311,13 @@ const gmpMonitor: PendingTxMonitor<GmpTx, EvmContext> = {
return;
}

await resolvePendingTx({
signingSmartWalletKit: ctx.signingSmartWalletKit,
txId,
status: transferResult?.found ? TxStatus.SUCCESS : TxStatus.FAILED,
...(transferResult?.rejectionReason
? { rejectionReason: transferResult.rejectionReason }
: {}),
});
transferResult.settled &&
(await resolvePendingTx({
signingSmartWalletKit: ctx.signingSmartWalletKit,
txId,
status:
transferResult.success !== false ? TxStatus.SUCCESS : TxStatus.FAILED,
}));

if (transferResult?.txHash) {
await ctx.ydsNotifier?.notifySettlement(txId, transferResult.txHash);
Expand Down Expand Up @@ -396,7 +385,7 @@ const makeAccountMonitor: PendingTxMonitor<MakeAccountTx, EvmContext> = {
txId,
});
void liveResultP.then(result => {
if (result.found) {
if (result.settled) {
log(`${logPrefix} Live mode completed`);
abortController.abort();
}
Expand All @@ -416,7 +405,7 @@ const makeAccountMonitor: PendingTxMonitor<MakeAccountTx, EvmContext> = {
signal: abortController.signal,
});

if (walletResult.found) {
if (walletResult.settled) {
log(`${logPrefix} Lookback found wallet creation`);
abortController.abort();
} else {
Expand All @@ -431,11 +420,13 @@ const makeAccountMonitor: PendingTxMonitor<MakeAccountTx, EvmContext> = {
return;
}

await resolvePendingTx({
signingSmartWalletKit: ctx.signingSmartWalletKit,
txId,
status: walletResult?.found ? TxStatus.SUCCESS : TxStatus.FAILED,
});
walletResult.settled &&
(await resolvePendingTx({
signingSmartWalletKit: ctx.signingSmartWalletKit,
txId,
status:
walletResult.success !== false ? TxStatus.SUCCESS : TxStatus.FAILED,
}));

if (walletResult?.txHash) {
await ctx.ydsNotifier?.notifySettlement(txId, walletResult.txHash);
Expand Down
Loading
Loading