From fb8c53b888e8adaa009c8be9ac282d3dfc8d6712 Mon Sep 17 00:00:00 2001 From: Dan Connolly Date: Wed, 20 Nov 2024 18:39:23 -0600 Subject: [PATCH] refactor(fast-usdc): sender type, simulate.advance --- packages/fast-usdc/src/exos/settler.js | 13 +++--- packages/fast-usdc/test/exos/settler.test.ts | 42 +++++++++++++------- 2 files changed, 34 insertions(+), 21 deletions(-) diff --git a/packages/fast-usdc/src/exos/settler.js b/packages/fast-usdc/src/exos/settler.js index 425f6e41bed..a81189837fb 100644 --- a/packages/fast-usdc/src/exos/settler.js +++ b/packages/fast-usdc/src/exos/settler.js @@ -72,10 +72,15 @@ export const prepareSettler = ( // only interested in packets from the issuing chain return; } + // TODO: why is it safe to cast this without a runtime check? const tx = /** @type {FungibleTokenPacketData} */ ( JSON.parse(atob(event.packet.data)) ); + + // given the sourceChannel check, we can be certain of this cast + const sender = /** @type {NobleAddress} */ (tx.sender); + if (tx.denom !== this.state.remoteDenom) { // only interested in uusdc return; @@ -94,13 +99,7 @@ export const prepareSettler = ( const amountInt = BigInt(tx.amount); // TODO: what if this throws? - // TODO discern between SETTLED and OBSERVED; each has different fees/destinations - const hasPendingSettlement = statusManager.hasPendingSettlement( - // given the sourceChannel check, we can be certain of this cast - /** @type {NobleAddress} */ (tx.sender), - amountInt, - ); - if (!hasPendingSettlement) { + if (!statusManager.hasPendingSettlement(sender, amountInt)) { // TODO FAILURE PATH -> put money in recovery account or .transfer to receiver // TODO should we have an ORPHANED TxStatus for this? throw makeError( diff --git a/packages/fast-usdc/test/exos/settler.test.ts b/packages/fast-usdc/test/exos/settler.test.ts index 17c99ee7090..c237496ae34 100644 --- a/packages/fast-usdc/test/exos/settler.test.ts +++ b/packages/fast-usdc/test/exos/settler.test.ts @@ -80,17 +80,31 @@ const makeTestContext = async t => { remoteDenom: 'uusdc', }); - const simulateAdvance = (evidence?: CctpTxEvidence) => { - const cctpTxEvidence: CctpTxEvidence = { - ...MockCctpTxEvidences.AGORIC_PLUS_OSMO(), - ...evidence, - }; - t.log('Mock CCTP Evidence:', cctpTxEvidence); - t.log('Pretend we initiated advance, mark as `ADVANCED`'); - statusManager.advance(cctpTxEvidence); - - return cctpTxEvidence; - }; + const simulate = harden({ + advance: (evidence?: CctpTxEvidence) => { + const cctpTxEvidence: CctpTxEvidence = { + ...MockCctpTxEvidences.AGORIC_PLUS_OSMO(), + ...evidence, + }; + t.log('Mock CCTP Evidence:', cctpTxEvidence); + t.log('Pretend we initiated advance, mark as `ADVANCED`'); + statusManager.advance(cctpTxEvidence); + + return cctpTxEvidence; + }, + + observe: (evidence?: CctpTxEvidence) => { + const cctpTxEvidence: CctpTxEvidence = { + ...MockCctpTxEvidences.AGORIC_PLUS_OSMO(), + ...evidence, + }; + t.log('Mock CCTP Evidence:', cctpTxEvidence); + t.log('Pretend we `OBSERVED`'); + statusManager.observe(cctpTxEvidence); + + return cctpTxEvidence; + }, + }); const repayer = zone.exo('Repayer Mock', undefined, { repay(fromSeat: ZCFSeat, amounts: AmountKeywordRecord) { @@ -103,7 +117,7 @@ const makeTestContext = async t => { makeSettler, statusManager, defaultSettlerParams, - simulateAdvance, + simulate, repayer, peekCalls: () => harden([...callLog]), accounts: mockAccounts, @@ -121,7 +135,7 @@ test('happy path: disburse to LPs; StatusManager removes tx', async t => { statusManager, defaultSettlerParams, repayer, - simulateAdvance, + simulate, accounts, peekCalls, } = t.context; @@ -134,7 +148,7 @@ test('happy path: disburse to LPs; StatusManager removes tx', async t => { ...defaultSettlerParams, }); - const cctpTxEvidence = simulateAdvance(); + const cctpTxEvidence = simulate.advance(); t.deepEqual( statusManager.lookupPending( cctpTxEvidence.tx.forwardingAddress,