Skip to content

Commit 444aedd

Browse files
committed
feat: StatusManager tracks seenTxs
- use a composite key of `txHash+chainId` to track unique `EventFeed` submissions
1 parent 024fd1d commit 444aedd

File tree

2 files changed

+35
-2
lines changed

2 files changed

+35
-2
lines changed

packages/fast-usdc/src/exos/status-manager.js

+33-2
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ import { CctpTxEvidenceShape, PendingTxShape } from '../typeGuards.js';
66
import { TxStatus } from '../constants.js';
77

88
/**
9-
* @import {MapStore} from '@agoric/store';
9+
* @import {MapStore, SetStore} from '@agoric/store';
1010
* @import {Zone} from '@agoric/zone';
11-
* @import {CctpTxEvidence, NobleAddress, PendingTxKey, PendingTx} from '../types.js';
11+
* @import {CctpTxEvidence, NobleAddress, SeenTxKey, PendingTxKey, PendingTx} from '../types.js';
1212
*/
1313

1414
/**
@@ -29,6 +29,16 @@ const getPendingTxKey = evidence => {
2929
return toPendingTxKey(forwardingAddress, amount);
3030
};
3131

32+
/**
33+
* Get the key for the seenTxs SetStore
34+
* @param {CctpTxEvidence} evidence
35+
* @returns {SeenTxKey}
36+
*/
37+
const getSeenKey = evidence => {
38+
const { txHash, chainId } = evidence;
39+
return `${txHash}+${chainId}`;
40+
};
41+
3242
/**
3343
* The `StatusManager` keeps track of Pending and Seen Transactions
3444
* via {@link TxStatus} states, aiding in coordination between the `Advancer`
@@ -45,6 +55,25 @@ export const prepareStatusManager = zone => {
4555
valueShape: M.arrayOf(PendingTxShape),
4656
});
4757

58+
/** @type {SetStore<SeenTxKey>} */
59+
const seenTxs = zone.setStore('SeenTxs', {
60+
keyShape: M.string(),
61+
});
62+
63+
/**
64+
* Ensures that `txHash+chainId` has not been processed
65+
* and adds `txHash+chainId` to `seenTxs` set.
66+
*
67+
* @param {CctpTxEvidence} evidence
68+
*/
69+
const assertNotSeen = evidence => {
70+
const seenKey = getSeenKey(evidence);
71+
if (seenTxs.has(seenKey)) {
72+
throw makeError(`Transaction already seen: ${q(seenKey)}`);
73+
}
74+
seenTxs.add(seenKey);
75+
};
76+
4877
return zone.exo(
4978
'Fast USDC Status Manager',
5079
M.interface('StatusManagerI', {
@@ -60,6 +89,7 @@ export const prepareStatusManager = zone => {
6089
* @param {CctpTxEvidence} evidence
6190
*/
6291
advance(evidence) {
92+
assertNotSeen(evidence);
6393
const key = getPendingTxKey(evidence);
6494
const entry = { ...evidence, status: TxStatus.Advanced };
6595

@@ -76,6 +106,7 @@ export const prepareStatusManager = zone => {
76106
* @param {CctpTxEvidence} evidence
77107
*/
78108
observe(evidence) {
109+
assertNotSeen(evidence);
79110
const key = getPendingTxKey(evidence);
80111
const entry = { ...evidence, status: TxStatus.Observed };
81112

packages/fast-usdc/src/types.ts

+2
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,6 @@ export interface PendingTx extends CctpTxEvidence {
3232
/** composite of NobleAddress and transaction amount value */
3333
export type PendingTxKey = `"["${NobleAddress}",${bigint}]"`;
3434

35+
export type SeenTxKey = `${EvmHash}+${number}`;
36+
3537
export type * from './constants.js';

0 commit comments

Comments
 (0)