From 3ea2a974fcbd8e3c4916d634acf895bc812b0d93 Mon Sep 17 00:00:00 2001 From: Cody Butz Date: Fri, 13 Feb 2026 17:53:56 -0500 Subject: [PATCH 1/2] For transactions, allow either a UTxO or an OutRef be passed. The transaction fn will resolve it to an UTxO. --- src/contracts/cdp/transactions.ts | 376 ++++++++---------- src/contracts/collector/transactions.ts | 18 +- src/contracts/gov/transactions.ts | 139 +++---- src/contracts/interest-oracle/transactions.ts | 12 +- src/contracts/leverage/transactions.ts | 43 +- src/contracts/lrp/transactions.ts | 38 +- src/contracts/price-oracle/transactions.ts | 11 +- src/contracts/stability-pool/transactions.ts | 14 +- src/contracts/staking/helpers.ts | 77 ++-- src/contracts/staking/transactions.ts | 147 ++++--- src/contracts/treasury/transactions.ts | 16 +- src/utils/lucid-utils.ts | 33 ++ tests/gov.test.ts | 114 +++++- tests/staking.test.ts | 29 +- 14 files changed, 596 insertions(+), 471 deletions(-) diff --git a/src/contracts/cdp/transactions.ts b/src/contracts/cdp/transactions.ts index cff8485..d7785f0 100644 --- a/src/contracts/cdp/transactions.ts +++ b/src/contracts/cdp/transactions.ts @@ -17,6 +17,8 @@ import { addrDetails, createScriptAddress, getInlineDatumOrThrow, + resolveUtxo, + UTxOOrOutRef, } from '../../utils/lucid-utils'; import { matchSingle } from '../../utils/utils'; import { @@ -61,11 +63,11 @@ export async function openCdp( collateralAmount: bigint, mintedAmount: bigint, sysParams: SystemParams, - cdpCreatorOref: OutRef, - iassetOref: OutRef, - priceOracleOref: OutRef, - interestOracleOref: OutRef, - collectorOref: OutRef, + cdpCreator: UTxOOrOutRef, + iasset: UTxOOrOutRef, + priceOracle: UTxOOrOutRef, + interestOracle: UTxOOrOutRef, + collector: UTxOOrOutRef, lucid: LucidEvolution, currentSlot: number, ): Promise { @@ -99,33 +101,37 @@ export async function openCdp( (_) => new Error('Expected a single iasset token policy Ref Script UTXO'), ); - const iassetUtxo = matchSingle( - await lucid.utxosByOutRef([iassetOref]), - (_) => new Error('Expected a single iasset UTXO'), + const iassetUtxo = await resolveUtxo( + iasset, + lucid, + 'Expected a single iasset UTXO', ); const iassetDatum = parseIAssetDatumOrThrow( getInlineDatumOrThrow(iassetUtxo), ); - const priceOracleUtxo = matchSingle( - await lucid.utxosByOutRef([priceOracleOref]), - (_) => new Error('Expected a single price oracle UTXO'), + const priceOracleUtxo = await resolveUtxo( + priceOracle, + lucid, + 'Expected a single price oracle UTXO', ); const priceOracleDatum = parsePriceOracleDatum( getInlineDatumOrThrow(priceOracleUtxo), ); - const interestOracleUtxo = matchSingle( - await lucid.utxosByOutRef([interestOracleOref]), - (_) => new Error('Expected a single interest oracle UTXO'), + const interestOracleUtxo = await resolveUtxo( + interestOracle, + lucid, + 'Expected a single interest oracle UTXO', ); const interestOracleDatum = parseInterestOracleDatum( getInlineDatumOrThrow(interestOracleUtxo), ); - const cdpCreatorUtxo = matchSingle( - await lucid.utxosByOutRef([cdpCreatorOref]), - (_) => new Error('Expected a single CDP creator UTXO'), + const cdpCreatorUtxo = await resolveUtxo( + cdpCreator, + lucid, + 'Expected a single CDP creator UTXO', ); match(iassetDatum.price) @@ -212,7 +218,7 @@ export async function openCdp( ); if (debtMintingFee > 0) { - await collectorFeeTx(debtMintingFee, lucid, sysParams, tx, collectorOref); + await collectorFeeTx(debtMintingFee, lucid, sysParams, tx, collector); } return tx; @@ -221,13 +227,13 @@ export async function openCdp( async function adjustCdp( collateralAmount: bigint, mintAmount: bigint, - cdpOref: OutRef, - iassetOref: OutRef, - priceOracleOref: OutRef, - interestOracleOref: OutRef, - collectorOref: OutRef, - govOref: OutRef, - treasuryOref: OutRef, + cdp: UTxOOrOutRef, + iasset: UTxOOrOutRef, + priceOracle: UTxOOrOutRef, + interestOracle: UTxOOrOutRef, + collector: UTxOOrOutRef, + gov: UTxOOrOutRef, + treasury: UTxOOrOutRef, sysParams: SystemParams, lucid: LucidEvolution, currentSlot: number, @@ -242,37 +248,34 @@ async function adjustCdp( (_) => new Error('Expected a single cdp Ref Script UTXO'), ); - const cdpUtxo = matchSingle( - await lucid.utxosByOutRef([cdpOref]), - (_) => new Error('Expected a single cdp UTXO'), - ); + const cdpUtxo = await resolveUtxo(cdp, lucid, 'Expected a single cdp UTXO'); const cdpDatum = parseCdpDatumOrThrow(getInlineDatumOrThrow(cdpUtxo)); - const iassetUtxo = matchSingle( - await lucid.utxosByOutRef([iassetOref]), - (_) => new Error('Expected a single iasset UTXO'), + const iassetUtxo = await resolveUtxo( + iasset, + lucid, + 'Expected a single iasset UTXO', ); const iassetDatum = parseIAssetDatumOrThrow( getInlineDatumOrThrow(iassetUtxo), ); - const govUtxo = matchSingle( - await lucid.utxosByOutRef([govOref]), - (_) => new Error('Expected a single gov UTXO'), - ); + const govUtxo = await resolveUtxo(gov, lucid, 'Expected a single gov UTXO'); const govDatum = parseGovDatumOrThrow(getInlineDatumOrThrow(govUtxo)); - const priceOracleUtxo = matchSingle( - await lucid.utxosByOutRef([priceOracleOref]), - (_) => new Error('Expected a single price oracle UTXO'), + const priceOracleUtxo = await resolveUtxo( + priceOracle, + lucid, + 'Expected a single price oracle UTXO', ); const priceOracleDatum = parsePriceOracleDatum( getInlineDatumOrThrow(priceOracleUtxo), ); - const interestOracleUtxo = matchSingle( - await lucid.utxosByOutRef([interestOracleOref]), - (_) => new Error('Expected a single interest oracle UTXO'), + const interestOracleUtxo = await resolveUtxo( + interestOracle, + lucid, + 'Expected a single interest oracle UTXO', ); const interestOracleDatum = parseInterestOracleDatum( getInlineDatumOrThrow(interestOracleUtxo), @@ -388,13 +391,7 @@ async function adjustCdp( const interestTreasuryAdaAmt = interestAdaAmt - interestCollectorAdaAmt; if (interestTreasuryAdaAmt > 0) { - await treasuryFeeTx( - interestTreasuryAdaAmt, - lucid, - sysParams, - tx, - treasuryOref, - ); + await treasuryFeeTx(interestTreasuryAdaAmt, lucid, sysParams, tx, treasury); } let collectorFee = interestCollectorAdaAmt; @@ -416,7 +413,7 @@ async function adjustCdp( } if (collectorFee > 0n) { - await collectorFeeTx(collectorFee, lucid, sysParams, tx, collectorOref); + await collectorFeeTx(collectorFee, lucid, sysParams, tx, collector); } return tx; @@ -424,13 +421,13 @@ async function adjustCdp( export async function depositCdp( amount: bigint, - cdpOref: OutRef, - iassetOref: OutRef, - priceOracleOref: OutRef, - interestOracleOref: OutRef, - collectorOref: OutRef, - govOref: OutRef, - treasuryOref: OutRef, + cdp: UTxOOrOutRef, + iasset: UTxOOrOutRef, + priceOracle: UTxOOrOutRef, + interestOracle: UTxOOrOutRef, + collector: UTxOOrOutRef, + gov: UTxOOrOutRef, + treasury: UTxOOrOutRef, params: SystemParams, lucid: LucidEvolution, currentSlot: number, @@ -438,13 +435,13 @@ export async function depositCdp( return adjustCdp( amount, 0n, - cdpOref, - iassetOref, - priceOracleOref, - interestOracleOref, - collectorOref, - govOref, - treasuryOref, + cdp, + iasset, + priceOracle, + interestOracle, + collector, + gov, + treasury, params, lucid, currentSlot, @@ -453,13 +450,13 @@ export async function depositCdp( export async function withdrawCdp( amount: bigint, - cdpOref: OutRef, - iassetOref: OutRef, - priceOracleOref: OutRef, - interestOracleOref: OutRef, - collectorOref: OutRef, - govOref: OutRef, - treasuryOref: OutRef, + cdp: UTxOOrOutRef, + iasset: UTxOOrOutRef, + priceOracle: UTxOOrOutRef, + interestOracle: UTxOOrOutRef, + collector: UTxOOrOutRef, + gov: UTxOOrOutRef, + treasury: UTxOOrOutRef, params: SystemParams, lucid: LucidEvolution, currentSlot: number, @@ -467,13 +464,13 @@ export async function withdrawCdp( return adjustCdp( -amount, 0n, - cdpOref, - iassetOref, - priceOracleOref, - interestOracleOref, - collectorOref, - govOref, - treasuryOref, + cdp, + iasset, + priceOracle, + interestOracle, + collector, + gov, + treasury, params, lucid, currentSlot, @@ -482,13 +479,13 @@ export async function withdrawCdp( export async function mintCdp( amount: bigint, - cdpOref: OutRef, - iassetOref: OutRef, - priceOracleOref: OutRef, - interestOracleOref: OutRef, - collectorOref: OutRef, - govOref: OutRef, - treasuryOref: OutRef, + cdp: UTxOOrOutRef, + iasset: UTxOOrOutRef, + priceOracle: UTxOOrOutRef, + interestOracle: UTxOOrOutRef, + collector: UTxOOrOutRef, + gov: UTxOOrOutRef, + treasury: UTxOOrOutRef, params: SystemParams, lucid: LucidEvolution, currentSlot: number, @@ -496,13 +493,13 @@ export async function mintCdp( return adjustCdp( 0n, amount, - cdpOref, - iassetOref, - priceOracleOref, - interestOracleOref, - collectorOref, - govOref, - treasuryOref, + cdp, + iasset, + priceOracle, + interestOracle, + collector, + gov, + treasury, params, lucid, currentSlot, @@ -511,13 +508,13 @@ export async function mintCdp( export async function burnCdp( amount: bigint, - cdpOref: OutRef, - iassetOref: OutRef, - priceOracleOref: OutRef, - interestOracleOref: OutRef, - collectorOref: OutRef, - govOref: OutRef, - treasuryOref: OutRef, + cdp: UTxOOrOutRef, + iasset: UTxOOrOutRef, + priceOracle: UTxOOrOutRef, + interestOracle: UTxOOrOutRef, + collector: UTxOOrOutRef, + gov: UTxOOrOutRef, + treasury: UTxOOrOutRef, params: SystemParams, lucid: LucidEvolution, currentSlot: number, @@ -525,13 +522,13 @@ export async function burnCdp( return adjustCdp( 0n, -amount, - cdpOref, - iassetOref, - priceOracleOref, - interestOracleOref, - collectorOref, - govOref, - treasuryOref, + cdp, + iasset, + priceOracle, + interestOracle, + collector, + gov, + treasury, params, lucid, currentSlot, @@ -539,13 +536,13 @@ export async function burnCdp( } export async function closeCdp( - cdpOref: OutRef, - iassetOref: OutRef, - priceOracleOref: OutRef, - interestOracleOref: OutRef, - collectorOref: OutRef, - govOref: OutRef, - treasuryOref: OutRef, + cdp: UTxOOrOutRef, + iasset: UTxOOrOutRef, + priceOracle: UTxOOrOutRef, + interestOracle: UTxOOrOutRef, + collector: UTxOOrOutRef, + gov: UTxOOrOutRef, + treasury: UTxOOrOutRef, sysParams: SystemParams, lucid: LucidEvolution, currentSlot: number, @@ -578,37 +575,34 @@ export async function closeCdp( (_) => new Error('Expected a single iasset token policy Ref Script UTXO'), ); - const cdpUtxo = matchSingle( - await lucid.utxosByOutRef([cdpOref]), - (_) => new Error('Expected a single cdp UTXO'), - ); + const cdpUtxo = await resolveUtxo(cdp, lucid, 'Expected a single cdp UTXO'); const cdpDatum = parseCdpDatumOrThrow(getInlineDatumOrThrow(cdpUtxo)); - const iassetUtxo = matchSingle( - await lucid.utxosByOutRef([iassetOref]), - (_) => new Error('Expected a single iasset UTXO'), + const iassetUtxo = await resolveUtxo( + iasset, + lucid, + 'Expected a single iasset UTXO', ); const iassetDatum = parseIAssetDatumOrThrow( getInlineDatumOrThrow(iassetUtxo), ); - const govUtxo = matchSingle( - await lucid.utxosByOutRef([govOref]), - (_) => new Error('Expected a single gov UTXO'), - ); + const govUtxo = await resolveUtxo(gov, lucid, 'Expected a single gov UTXO'); const govDatum = parseGovDatumOrThrow(getInlineDatumOrThrow(govUtxo)); - const priceOracleUtxo = matchSingle( - await lucid.utxosByOutRef([priceOracleOref]), - (_) => new Error('Expected a single price oracle UTXO'), + const priceOracleUtxo = await resolveUtxo( + priceOracle, + lucid, + 'Expected a single price oracle UTXO', ); const priceOracleDatum = parsePriceOracleDatum( getInlineDatumOrThrow(priceOracleUtxo), ); - const interestOracleUtxo = matchSingle( - await lucid.utxosByOutRef([interestOracleOref]), - (_) => new Error('Expected a single interest oracle UTXO'), + const interestOracleUtxo = await resolveUtxo( + interestOracle, + lucid, + 'Expected a single interest oracle UTXO', ); const interestOracleDatum = parseInterestOracleDatum( getInlineDatumOrThrow(interestOracleUtxo), @@ -683,13 +677,7 @@ export async function closeCdp( const interestTreasuryAdaAmt = interestAdaAmt - interestCollectorAdaAmt; if (interestTreasuryAdaAmt > 0) { - await treasuryFeeTx( - interestTreasuryAdaAmt, - lucid, - sysParams, - tx, - treasuryOref, - ); + await treasuryFeeTx(interestTreasuryAdaAmt, lucid, sysParams, tx, treasury); } const collectorFee = @@ -700,7 +688,7 @@ export async function closeCdp( ); if (collectorFee > 0n) { - await collectorFeeTx(collectorFee, lucid, sysParams, tx, collectorOref); + await collectorFeeTx(collectorFee, lucid, sysParams, tx, collector); } return tx; @@ -712,12 +700,12 @@ export async function redeemCdp( * The logic will automatically cap the amount to the max. */ attemptedRedemptionIAssetAmt: bigint, - cdpOref: OutRef, - iassetOref: OutRef, - priceOracleOref: OutRef, - interestOracleOref: OutRef, - collectorOref: OutRef, - treasuryOref: OutRef, + cdp: UTxOOrOutRef, + iasset: UTxOOrOutRef, + priceOracle: UTxOOrOutRef, + interestOracle: UTxOOrOutRef, + collector: UTxOOrOutRef, + treasury: UTxOOrOutRef, sysParams: SystemParams, lucid: LucidEvolution, currentSlot: number, @@ -741,31 +729,31 @@ export async function redeemCdp( (_) => new Error('Expected a single iasset token policy Ref Script UTXO'), ); - const cdpUtxo = matchSingle( - await lucid.utxosByOutRef([cdpOref]), - (_) => new Error('Expected a single cdp UTXO'), - ); + const cdpUtxo = await resolveUtxo(cdp, lucid, 'Expected a single cdp UTXO'); const cdpDatum = parseCdpDatumOrThrow(getInlineDatumOrThrow(cdpUtxo)); - const iassetUtxo = matchSingle( - await lucid.utxosByOutRef([iassetOref]), - (_) => new Error('Expected a single iasset UTXO'), + const iassetUtxo = await resolveUtxo( + iasset, + lucid, + 'Expected a single iasset UTXO', ); const iassetDatum = parseIAssetDatumOrThrow( getInlineDatumOrThrow(iassetUtxo), ); - const priceOracleUtxo = matchSingle( - await lucid.utxosByOutRef([priceOracleOref]), - (_) => new Error('Expected a single price oracle UTXO'), + const priceOracleUtxo = await resolveUtxo( + priceOracle, + lucid, + 'Expected a single price oracle UTXO', ); const priceOracleDatum = parsePriceOracleDatum( getInlineDatumOrThrow(priceOracleUtxo), ); - const interestOracleUtxo = matchSingle( - await lucid.utxosByOutRef([interestOracleOref]), - (_) => new Error('Expected a single interest oracle UTXO'), + const interestOracleUtxo = await resolveUtxo( + interestOracle, + lucid, + 'Expected a single interest oracle UTXO', ); const interestOracleDatum = parseInterestOracleDatum( getInlineDatumOrThrow(interestOracleUtxo), @@ -902,25 +890,19 @@ export async function redeemCdp( lucid, sysParams, tx, - collectorOref, + collector, ); - await treasuryFeeTx( - interestTreasuryAdaAmt, - lucid, - sysParams, - tx, - treasuryOref, - ); + await treasuryFeeTx(interestTreasuryAdaAmt, lucid, sysParams, tx, treasury); return tx; } export async function freezeCdp( - cdpOref: OutRef, - iassetOref: OutRef, - priceOracleOref: OutRef, - interestOracleOref: OutRef, + cdp: UTxOOrOutRef, + iasset: UTxOOrOutRef, + priceOracle: UTxOOrOutRef, + interestOracle: UTxOOrOutRef, sysParams: SystemParams, lucid: LucidEvolution, currentSlot: number, @@ -934,31 +916,31 @@ export async function freezeCdp( ]), (_) => new Error('Expected a single cdp Ref Script UTXO'), ); - const cdpUtxo = matchSingle( - await lucid.utxosByOutRef([cdpOref]), - (_) => new Error('Expected a single cdp UTXO'), - ); + const cdpUtxo = await resolveUtxo(cdp, lucid, 'Expected a single cdp UTXO'); const cdpDatum = parseCdpDatumOrThrow(getInlineDatumOrThrow(cdpUtxo)); - const iassetUtxo = matchSingle( - await lucid.utxosByOutRef([iassetOref]), - (_) => new Error('Expected a single iasset UTXO'), + const iassetUtxo = await resolveUtxo( + iasset, + lucid, + 'Expected a single iasset UTXO', ); const iassetDatum = parseIAssetDatumOrThrow( getInlineDatumOrThrow(iassetUtxo), ); - const priceOracleUtxo = matchSingle( - await lucid.utxosByOutRef([priceOracleOref]), - (_) => new Error('Expected a single price oracle UTXO'), + const priceOracleUtxo = await resolveUtxo( + priceOracle, + lucid, + 'Expected a single price oracle UTXO', ); const priceOracleDatum = parsePriceOracleDatum( getInlineDatumOrThrow(priceOracleUtxo), ); - const interestOracleUtxo = matchSingle( - await lucid.utxosByOutRef([interestOracleOref]), - (_) => new Error('Expected a single interest oracle UTXO'), + const interestOracleUtxo = await resolveUtxo( + interestOracle, + lucid, + 'Expected a single interest oracle UTXO', ); const interestOracleDatum = parseInterestOracleDatum( getInlineDatumOrThrow(interestOracleUtxo), @@ -1061,10 +1043,10 @@ export async function freezeCdp( } export async function liquidateCdp( - cdpOref: OutRef, - stabilityPoolOref: OutRef, - collectorOref: OutRef, - treasuryOref: OutRef, + cdp: UTxOOrOutRef, + stabilityPool: UTxOOrOutRef, + collector: UTxOOrOutRef, + treasury: UTxOOrOutRef, sysParams: SystemParams, lucid: LucidEvolution, ): Promise { @@ -1099,15 +1081,13 @@ export async function liquidateCdp( (_) => new Error('Expected a single cdp auth token policy Ref Script UTXO'), ); - const cdpUtxo = matchSingle( - await lucid.utxosByOutRef([cdpOref]), - (_) => new Error('Expected a single cdp UTXO'), - ); + const cdpUtxo = await resolveUtxo(cdp, lucid, 'Expected a single cdp UTXO'); const cdpDatum = parseCdpDatumOrThrow(getInlineDatumOrThrow(cdpUtxo)); - const spUtxo = matchSingle( - await lucid.utxosByOutRef([stabilityPoolOref]), - (_) => new Error('Expected a single stability pool UTXO'), + const spUtxo = await resolveUtxo( + stabilityPool, + lucid, + 'Expected a single stability pool UTXO', ); const spDatum = parseStabilityPoolDatum(getInlineDatumOrThrow(spUtxo)); @@ -1198,15 +1178,9 @@ export async function liquidateCdp( ); } - await collectorFeeTx( - lovelacesForCollector, - lucid, - sysParams, - tx, - collectorOref, - ); + await collectorFeeTx(lovelacesForCollector, lucid, sysParams, tx, collector); - await treasuryFeeTx(lovelacesForTreasury, lucid, sysParams, tx, treasuryOref); + await treasuryFeeTx(lovelacesForTreasury, lucid, sysParams, tx, treasury); return tx; } diff --git a/src/contracts/collector/transactions.ts b/src/contracts/collector/transactions.ts index d43603e..1e6c98b 100644 --- a/src/contracts/collector/transactions.ts +++ b/src/contracts/collector/transactions.ts @@ -1,15 +1,10 @@ -import { - Data, - LucidEvolution, - OutRef, - TxBuilder, - UTxO, -} from '@lucid-evolution/lucid'; +import { Data, LucidEvolution, TxBuilder, UTxO } from '@lucid-evolution/lucid'; import { fromSystemParamsScriptRef, SystemParams, } from '../../types/system-params'; import { matchSingle } from '../../utils/utils'; +import { resolveUtxo, UTxOOrOutRef } from '../../utils/lucid-utils'; import { serialiseCollectorRedeemer } from './types'; export async function collectorFeeTx( @@ -17,11 +12,12 @@ export async function collectorFeeTx( lucid: LucidEvolution, params: SystemParams, tx: TxBuilder, - collectorOref: OutRef, + collector: UTxOOrOutRef, ): Promise { - const collectorUtxo: UTxO = matchSingle( - await lucid.utxosByOutRef([collectorOref]), - (_) => new Error('Expected a single collector UTXO'), + const collectorUtxo: UTxO = await resolveUtxo( + collector, + lucid, + 'Expected a single collector UTXO', ); const collectorRefScriptUtxo = matchSingle( diff --git a/src/contracts/gov/transactions.ts b/src/contracts/gov/transactions.ts index 5fdb94b..2e5aaeb 100644 --- a/src/contracts/gov/transactions.ts +++ b/src/contracts/gov/transactions.ts @@ -1,4 +1,3 @@ -// import { OutRef } from '@lucid-evolution/lucid'; import { addAssets, Assets, @@ -22,6 +21,8 @@ import { matchSingle } from '../../utils/utils'; import { createScriptAddress, getInlineDatumOrThrow, + resolveUtxo, + UTxOOrOutRef, } from '../../utils/lucid-utils'; import { parsePollManagerOrThrow, @@ -101,7 +102,7 @@ export async function createProposal( sysParams: SystemParams, lucid: LucidEvolution, currentSlot: number, - govOref: OutRef, + gov: UTxOOrOutRef, /** * This has to be passed only in case of createAsset proposal */ @@ -130,10 +131,7 @@ export async function createProposal( (_) => new Error('Expected a single poll auth token policy ref Script UTXO'), ); - const govUtxo = matchSingle( - await lucid.utxosByOutRef([govOref]), - (_) => new Error('Expected a single Gov UTXO'), - ); + const govUtxo = await resolveUtxo(gov, lucid, 'Expected a single Gov UTXO'); const govDatum = parseGovDatumOrThrow(getInlineDatumOrThrow(govUtxo)); @@ -257,7 +255,7 @@ export async function createShardsChunks( * This gets automatically capped to total shards count. */ chunkSize: bigint, - pollManagerOref: OutRef, + pollManager: UTxOOrOutRef, sysParams: SystemParams, currentSlot: number, lucid: LucidEvolution, @@ -267,16 +265,19 @@ export async function createShardsChunks( const ownAddr = await lucid.wallet().address(); - const pollManagerUtxo = matchSingle( - await lucid.utxosByOutRef([pollManagerOref]), - (_) => new Error('Expected a single Poll manager UTXO'), + const pollManagerUtxo = await resolveUtxo( + pollManager, + lucid, + 'Expected a single Poll manager UTXO', ); - const pollManager = parsePollManagerOrThrow( + const pollManagerDatum = parsePollManagerOrThrow( getInlineDatumOrThrow(pollManagerUtxo), ); - if (pollManager.createdShardsCount >= pollManager.totalShardsCount) { + if ( + pollManagerDatum.createdShardsCount >= pollManagerDatum.totalShardsCount + ) { throw new Error('All shards already created.'); } @@ -302,7 +303,9 @@ export async function createShardsChunks( const shardsCount = BigInt( Math.min( Number(chunkSize), - Number(pollManager.totalShardsCount - pollManager.createdShardsCount), + Number( + pollManagerDatum.totalShardsCount - pollManagerDatum.createdShardsCount, + ), ), ); @@ -328,8 +331,9 @@ export async function createShardsChunks( value: serialisePollDatum({ PollManager: { content: { - ...pollManager, - createdShardsCount: pollManager.createdShardsCount + shardsCount, + ...pollManagerDatum, + createdShardsCount: + pollManagerDatum.createdShardsCount + shardsCount, }, }, }), @@ -346,9 +350,9 @@ export async function createShardsChunks( value: serialisePollDatum({ PollShard: { content: { - pollId: pollManager.pollId, + pollId: pollManagerDatum.pollId, status: { yesVotes: 0n, noVotes: 0n }, - votingEndTime: pollManager.votingEndTime, + votingEndTime: pollManagerDatum.votingEndTime, managerAddress: addressFromBech32(pollManagerUtxo.address), }, }, @@ -399,8 +403,8 @@ function voteHelper( export async function vote( voteOption: VoteOption, - pollShardOref: OutRef, - stakingPositionOref: OutRef, + pollShard: UTxOOrOutRef, + stakingPosition: UTxOOrOutRef, sysParams: SystemParams, lucid: LucidEvolution, currentSlot: number, @@ -425,17 +429,19 @@ export async function vote( (_) => new Error('Expected a single staking ref Script UTXO'), ); - const pollShardUtxo = matchSingle( - await lucid.utxosByOutRef([pollShardOref]), - (_) => new Error('Expected a single Poll shard UTXO'), + const pollShardUtxo = await resolveUtxo( + pollShard, + lucid, + 'Expected a single Poll shard UTXO', ); const pollShardDatum = parsePollShardOrThrow( getInlineDatumOrThrow(pollShardUtxo), ); - const stakingPosUtxo = matchSingle( - await lucid.utxosByOutRef([stakingPositionOref]), - (_) => new Error('Expected a single staking position UTXO'), + const stakingPosUtxo = await resolveUtxo( + stakingPosition, + lucid, + 'Expected a single staking position UTXO', ); const stakingPosDatum = parseStakingPositionOrThrow( getInlineDatumOrThrow(stakingPosUtxo), @@ -509,7 +515,7 @@ export async function vote( } export async function mergeShards( - pollManagerOref: OutRef, + pollManager: UTxOOrOutRef, shardsOutRefs: OutRef[], sysParams: SystemParams, lucid: LucidEvolution, @@ -547,9 +553,10 @@ export async function mergeShards( new Error('Expected a single poll auth token policy ref Script UTXO'), ); - const pollManagerUtxo = matchSingle( - await lucid.utxosByOutRef([pollManagerOref]), - (_) => new Error('Expected a single Poll manager UTXO'), + const pollManagerUtxo = await resolveUtxo( + pollManager, + lucid, + 'Expected a single Poll manager UTXO', ); const pollManagerDatum = parsePollManagerOrThrow( @@ -628,8 +635,8 @@ export async function mergeShards( } export async function endProposal( - pollManagerOref: OutRef, - govOref: OutRef, + pollManager: UTxOOrOutRef, + gov: UTxOOrOutRef, sysParams: SystemParams, lucid: LucidEvolution, currentSlot: number, @@ -674,18 +681,16 @@ export async function endProposal( new Error('Expected a single upgrade auth token policy ref Script UTXO'), ); - const pollManagerUtxo = matchSingle( - await lucid.utxosByOutRef([pollManagerOref]), - (_) => new Error('Expected a single Poll manager UTXO'), + const pollManagerUtxo = await resolveUtxo( + pollManager, + lucid, + 'Expected a single Poll manager UTXO', ); - const pollManager = parsePollManagerOrThrow( + const pollManagerDatum = parsePollManagerOrThrow( getInlineDatumOrThrow(pollManagerUtxo), ); - const govUtxo = matchSingle( - await lucid.utxosByOutRef([govOref]), - (_) => new Error('Expected a single Gov UTXO'), - ); + const govUtxo = await resolveUtxo(gov, lucid, 'Expected a single Gov UTXO'); const govDatum = parseGovDatumOrThrow(getInlineDatumOrThrow(govUtxo)); const pollNft = fromSystemParamsAsset(sysParams.govParams.pollToken); @@ -693,14 +698,14 @@ export async function endProposal( sysParams.pollManagerParams.indyAsset, ); - const proposalExpired = currentTime > pollManager.expirationTime; + const proposalExpired = currentTime > pollManagerDatum.expirationTime; const proposalPassed = !proposalExpired && pollPassQuorum( sysParams.pollManagerParams.initialIndyDistribution, - pollManager.status, + pollManagerDatum.status, currentTime, - pollManager.minimumQuorum, + pollManagerDatum.minimumQuorum, govDatum.treasuryIndyWithdrawnAmt, ); @@ -750,12 +755,12 @@ export async function endProposal( { kind: 'inline', value: serialiseExecuteDatum({ - id: pollManager.pollId, - content: pollManager.content, + id: pollManagerDatum.pollId, + content: pollManagerDatum.content, passedTime: currentTime, - votingEndTime: pollManager.votingEndTime, - protocolVersion: pollManager.protocolVersion, - treasuryWithdrawal: pollManager.treasuryWithdrawal, + votingEndTime: pollManagerDatum.votingEndTime, + protocolVersion: pollManagerDatum.protocolVersion, + treasuryWithdrawal: pollManagerDatum.treasuryWithdrawal, }), }, upgradeTokenVal, @@ -776,11 +781,11 @@ export async function endProposal( } export async function executeProposal( - executeOref: OutRef, - govOref: OutRef, - treasuryWithdrawalOref: OutRef | null, + execute: UTxOOrOutRef, + gov: UTxOOrOutRef, + treasuryWithdrawal: UTxOOrOutRef | null, allIAssetOrefs: OutRef[] | null, - modifyIAssetOref: OutRef | null, + modifyIAsset: UTxOOrOutRef | null, sysParams: SystemParams, lucid: LucidEvolution, currentSlot: number, @@ -790,10 +795,7 @@ export async function executeProposal( const ownAddr = await lucid.wallet().address(); - const govUtxo = matchSingle( - await lucid.utxosByOutRef([govOref]), - (_) => new Error('Expected a single gov UTXO'), - ); + const govUtxo = await resolveUtxo(gov, lucid, 'Expected a single gov UTXO'); const govDatum = parseGovDatumOrThrow(getInlineDatumOrThrow(govUtxo)); @@ -822,9 +824,10 @@ export async function executeProposal( new Error('Expected a single upgrade auth token policy ref Script UTXO'), ); - const executeUtxo = matchSingle( - await lucid.utxosByOutRef([executeOref]), - (_) => new Error('Expected a single execute UTXO'), + const executeUtxo = await resolveUtxo( + execute, + lucid, + 'Expected a single execute UTXO', ); const executeDatum = parseExecuteDatumOrThrow( @@ -849,13 +852,13 @@ export async function executeProposal( O.fromNullable(executeDatum.treasuryWithdrawal), O.match( () => { - if (treasuryWithdrawalOref) { + if (treasuryWithdrawal) { throw new Error('Cannot provide withdrawal oref when no withdrawal.'); } return Promise.resolve(); }, async (withdrawal) => { - if (!treasuryWithdrawalOref) { + if (!treasuryWithdrawal) { throw new Error('Have to provide withdrawal oref when withdrawal.'); } @@ -868,9 +871,10 @@ export async function executeProposal( (_) => new Error('Expected a single Treasury Ref Script UTXO'), ); - const treasuryWithdrawalUtxo = matchSingle( - await lucid.utxosByOutRef([treasuryWithdrawalOref]), - (_) => new Error('Expected a single withdrawal UTXO'), + const treasuryWithdrawalUtxo = await resolveUtxo( + treasuryWithdrawal, + lucid, + 'Expected a single withdrawal UTXO', ); const withdrawalVal = createValueFromWithdrawal(withdrawal); @@ -1062,13 +1066,14 @@ export async function executeProposal( (_) => new Error('Expected a single CDP Ref Script UTXO'), ); - if (!modifyIAssetOref) { + if (!modifyIAsset) { throw new Error('Have to provide iasset oref when modify asset.'); } - const iassetUtxo = matchSingle( - await lucid.utxosByOutRef([modifyIAssetOref]), - (_) => new Error('Expected a single iasset UTXO'), + const iassetUtxo = await resolveUtxo( + modifyIAsset, + lucid, + 'Expected a single iasset UTXO', ); const iassetDatum = parseIAssetDatumOrThrow( diff --git a/src/contracts/interest-oracle/transactions.ts b/src/contracts/interest-oracle/transactions.ts index 2358b97..cdde7a6 100644 --- a/src/contracts/interest-oracle/transactions.ts +++ b/src/contracts/interest-oracle/transactions.ts @@ -1,12 +1,12 @@ import { fromText, LucidEvolution, - OutRef, toUnit, TxBuilder, UTxO, validatorToAddress, } from '@lucid-evolution/lucid'; +import { UTxOOrOutRef } from '../../utils/lucid-utils'; import { AssetClass } from '../../types/generic'; import { InterestOracleParams, @@ -29,19 +29,19 @@ export async function startInterestOracle( lucid: LucidEvolution, interestTokenName?: string, withScriptRef: boolean = false, - refOutRef?: OutRef, + refUtxo?: UTxOOrOutRef, ): Promise<[TxBuilder, AssetClass]> { const network = lucid.config().network!; const tokenName = interestTokenName ?? 'INTEREST_ORACLE'; - if (!refOutRef) { - refOutRef = (await lucid.wallet().getUtxos())[0]; + if (!refUtxo) { + refUtxo = (await lucid.wallet().getUtxos())[0]; } const [tx, policyId] = await oneShotMintTx(lucid, { referenceOutRef: { - txHash: refOutRef.txHash, - outputIdx: BigInt(refOutRef.outputIndex), + txHash: refUtxo.txHash, + outputIdx: BigInt(refUtxo.outputIndex), }, mintAmounts: [ { diff --git a/src/contracts/leverage/transactions.ts b/src/contracts/leverage/transactions.ts index b1744bb..46cd12c 100644 --- a/src/contracts/leverage/transactions.ts +++ b/src/contracts/leverage/transactions.ts @@ -1,7 +1,6 @@ import { LucidEvolution, TxBuilder, - OutRef, UTxO, addAssets, slotToUnixTime, @@ -11,6 +10,8 @@ import { addrDetails, createScriptAddress, getInlineDatumOrThrow, + resolveUtxo, + UTxOOrOutRef, } from '../../utils/lucid-utils'; import { parsePriceOracleDatum } from '../price-oracle/types'; import { ocdMul } from '../../types/on-chain-decimal'; @@ -43,11 +44,11 @@ import { export async function leverageCdpWithLrp( leverage: number, baseCollateral: bigint, - priceOracleOutRef: OutRef, - iassetOutRef: OutRef, - cdpCreatorOref: OutRef, - interestOracleOref: OutRef, - collectorOref: OutRef, + priceOracle: UTxOOrOutRef, + iasset: UTxOOrOutRef, + cdpCreator: UTxOOrOutRef, + interestOracle: UTxOOrOutRef, + collector: UTxOOrOutRef, sysParams: SystemParams, lucid: LucidEvolution, allLrps: [UTxO, LRPDatum][], @@ -90,30 +91,34 @@ export async function leverageCdpWithLrp( (_) => new Error('Expected a single iasset token policy Ref Script UTXO'), ); - const cdpCreatorUtxo = matchSingle( - await lucid.utxosByOutRef([cdpCreatorOref]), - (_) => new Error('Expected a single CDP creator UTXO'), + const cdpCreatorUtxo = await resolveUtxo( + cdpCreator, + lucid, + 'Expected a single CDP creator UTXO', ); - const interestOracleUtxo = matchSingle( - await lucid.utxosByOutRef([interestOracleOref]), - (_) => new Error('Expected a single interest oracle UTXO'), + const interestOracleUtxo = await resolveUtxo( + interestOracle, + lucid, + 'Expected a single interest oracle UTXO', ); const interestOracleDatum = parseInterestOracleDatum( getInlineDatumOrThrow(interestOracleUtxo), ); - const priceOracleUtxo = matchSingle( - await lucid.utxosByOutRef([priceOracleOutRef]), - (_) => new Error('Expected a single price oracle UTXO'), + const priceOracleUtxo = await resolveUtxo( + priceOracle, + lucid, + 'Expected a single price oracle UTXO', ); const priceOracleDatum = parsePriceOracleDatum( getInlineDatumOrThrow(priceOracleUtxo), ); - const iassetUtxo = matchSingle( - await lucid.utxosByOutRef([iassetOutRef]), - (_) => new Error('Expected a single IAsset UTXO'), + const iassetUtxo = await resolveUtxo( + iasset, + lucid, + 'Expected a single IAsset UTXO', ); const iassetDatum = parseIAssetDatumOrThrow( getInlineDatumOrThrow(iassetUtxo), @@ -267,7 +272,7 @@ export async function leverageCdpWithLrp( ); if (debtMintingFee > 0) { - await collectorFeeTx(debtMintingFee, lucid, sysParams, tx, collectorOref); + await collectorFeeTx(debtMintingFee, lucid, sysParams, tx, collector); } return tx; diff --git a/src/contracts/lrp/transactions.ts b/src/contracts/lrp/transactions.ts index 9bd7f2b..95c668b 100644 --- a/src/contracts/lrp/transactions.ts +++ b/src/contracts/lrp/transactions.ts @@ -11,6 +11,8 @@ import { addrDetails, createScriptAddress, getInlineDatumOrThrow, + resolveUtxo, + UTxOOrOutRef, } from '../../utils/lucid-utils'; import { unzip, zip } from 'fp-ts/lib/Array'; import { @@ -69,7 +71,7 @@ export async function openLrp( } export async function cancelLrp( - lrpOutRef: OutRef, + lrp: UTxOOrOutRef, sysParams: SystemParams, lucid: LucidEvolution, ): Promise { @@ -80,10 +82,7 @@ export async function cancelLrp( (_) => new Error('Expected a single LRP Ref Script UTXO'), ); - const lrpUtxo = matchSingle( - await lucid.utxosByOutRef([lrpOutRef]), - (_) => new Error('Expected a single LRP UTXO.'), - ); + const lrpUtxo = await resolveUtxo(lrp, lucid, 'Expected a single LRP UTXO.'); const lrpDatum = parseLrpDatumOrThrow(getInlineDatumOrThrow(lrpUtxo)); @@ -97,8 +96,8 @@ export async function cancelLrp( export async function redeemLrp( /** The tuple represents the LRP outref and the amount of iAssets to redeem against it. */ redemptionLrpsData: [OutRef, bigint][], - priceOracleOutRef: OutRef, - iassetOutRef: OutRef, + priceOracle: UTxOOrOutRef, + iasset: UTxOOrOutRef, lucid: LucidEvolution, sysParams: SystemParams, ): Promise { @@ -111,14 +110,16 @@ export async function redeemLrp( (_) => new Error('Expected a single LRP Ref Script UTXO'), ); - const priceOracleUtxo = matchSingle( - await lucid.utxosByOutRef([priceOracleOutRef]), - (_) => new Error('Expected a single price oracle UTXO'), + const priceOracleUtxo = await resolveUtxo( + priceOracle, + lucid, + 'Expected a single price oracle UTXO', ); - const iassetUtxo = matchSingle( - await lucid.utxosByOutRef([iassetOutRef]), - (_) => new Error('Expected a single IAsset UTXO'), + const iassetUtxo = await resolveUtxo( + iasset, + lucid, + 'Expected a single IAsset UTXO', ); const iassetDatum = parseIAssetDatumOrThrow( @@ -167,7 +168,7 @@ export async function redeemLrp( */ export async function adjustLrp( lucid: LucidEvolution, - lrpOutRef: OutRef, + lrp: UTxOOrOutRef, /** * A positive amount increases the lovelaces in the LRP, * and a negative amount takes lovelaces from the LRP. @@ -183,10 +184,7 @@ export async function adjustLrp( (_) => new Error('Expected a single LRP Ref Script UTXO'), ); - const lrpUtxo = matchSingle( - await lucid.utxosByOutRef([lrpOutRef]), - (_) => new Error('Expected a single LRP UTXO.'), - ); + const lrpUtxo = await resolveUtxo(lrp, lucid, 'Expected a single LRP UTXO.'); const lrpDatum = parseLrpDatumOrThrow(getInlineDatumOrThrow(lrpUtxo)); @@ -245,8 +243,8 @@ export async function adjustLrp( */ export async function claimLrp( lucid: LucidEvolution, - lrpOutRef: OutRef, + lrp: UTxOOrOutRef, sysParams: SystemParams, ): Promise { - return adjustLrp(lucid, lrpOutRef, 0n, undefined, sysParams); + return adjustLrp(lucid, lrp, 0n, undefined, sysParams); } diff --git a/src/contracts/price-oracle/transactions.ts b/src/contracts/price-oracle/transactions.ts index f6aa6b6..94b43d8 100644 --- a/src/contracts/price-oracle/transactions.ts +++ b/src/contracts/price-oracle/transactions.ts @@ -19,8 +19,8 @@ import { mkPriceOracleValidator } from './scripts'; import { oneShotMintTx } from '../one-shot/transactions'; import { mkAssetsOf, mkLovelacesOf } from '../../utils/value-helpers'; import { OnChainDecimal } from '../../types/on-chain-decimal'; -import { matchSingle } from '../../utils/utils'; import { ONE_SECOND } from '../../utils/time-helpers'; +import { resolveUtxo, UTxOOrOutRef } from '../../utils/lucid-utils'; export async function startPriceOracleTx( lucid: LucidEvolution, @@ -70,7 +70,7 @@ export async function startPriceOracleTx( export async function feedPriceOracleTx( lucid: LucidEvolution, - oracleOref: OutRef, + oracle: UTxOOrOutRef, newPrice: OnChainDecimal, oracleParams: PriceOracleParams, currentSlot: number, @@ -78,9 +78,10 @@ export async function feedPriceOracleTx( const network = lucid.config().network!; const currentTime = BigInt(slotToUnixTime(network, currentSlot)); - const priceOracleUtxo = matchSingle( - await lucid.utxosByOutRef([oracleOref]), - (_) => new Error('Expected a single price oracle UTXO'), + const priceOracleUtxo = await resolveUtxo( + oracle, + lucid, + 'Expected a single price oracle UTXO', ); const oracleValidator = mkPriceOracleValidator(oracleParams); diff --git a/src/contracts/stability-pool/transactions.ts b/src/contracts/stability-pool/transactions.ts index c0c528d..d945510 100644 --- a/src/contracts/stability-pool/transactions.ts +++ b/src/contracts/stability-pool/transactions.ts @@ -8,7 +8,6 @@ import { UTxO, credentialToAddress, fromHex, - OutRef, toHex, } from '@lucid-evolution/lucid'; import { ActionReturnDatum } from './types'; @@ -17,6 +16,7 @@ import { addrDetails, getInlineDatumOrThrow, scriptRef, + UTxOOrOutRef, } from '../../utils/lucid-utils'; import { mkStabilityPoolValidatorFromSP } from './scripts'; import { @@ -236,7 +236,7 @@ export async function processSpRequest( newSnapshotUtxo: UTxO | undefined, params: SystemParams, lucid: LucidEvolution, - collectorOref: OutRef, + collector: UTxOOrOutRef, ): Promise { const redeemer: StabilityPoolRedeemer = { ProcessRequest: { @@ -463,13 +463,7 @@ export async function processSpRequest( ); if (rewardLovelacesFee > 0n) { - await collectorFeeTx( - rewardLovelacesFee, - lucid, - params, - tx, - collectorOref, - ); + await collectorFeeTx(rewardLovelacesFee, lucid, params, tx, collector); } tx.readFrom([govUtxo, iAssetUtxo, ...refInputs]); tx.pay.ToContract( @@ -603,7 +597,7 @@ export async function processSpRequest( params.scriptReferences.authTokenPolicies.accountTokenRef, lucid, ); - await collectorFeeTx(rewardLovelacesFee, lucid, params, tx, collectorOref); + await collectorFeeTx(rewardLovelacesFee, lucid, params, tx, collector); tx.readFrom([govUtxo, iAssetUtxo, accountTokenRef, ...refInputs]); tx.mintAssets( { diff --git a/src/contracts/staking/helpers.ts b/src/contracts/staking/helpers.ts index a4e737c..ed08fdf 100644 --- a/src/contracts/staking/helpers.ts +++ b/src/contracts/staking/helpers.ts @@ -1,9 +1,4 @@ -import { - fromText, - OutRef, - UTxO, - validatorToScriptHash, -} from '@lucid-evolution/lucid'; +import { fromText, UTxO, validatorToScriptHash } from '@lucid-evolution/lucid'; import { LucidEvolution } from '@lucid-evolution/lucid'; import { SystemParams } from '../../types/system-params'; import { @@ -13,7 +8,11 @@ import { StakingPosition, StakingPosLockedAmt, } from './types-new'; -import { createScriptAddress } from '../../utils/lucid-utils'; +import { + createScriptAddress, + resolveUtxo, + UTxOOrOutRef, +} from '../../utils/lucid-utils'; import { mkStakingValidatorFromSP } from './scripts'; import { OCD_DECIMAL_UNIT } from '../../types/on-chain-decimal'; @@ -37,28 +36,20 @@ export function updateStakingLockedAmount( ); } -export function findStakingManagerByOutRef( - stakingManagerRef: OutRef, +export async function findStakingManagerByOutRef( + stakingManager: UTxOOrOutRef, lucid: LucidEvolution, ): Promise { - return lucid - .utxosByOutRef([stakingManagerRef]) - .then((utxos) => - utxos - .map((utxo) => { - if (!utxo.datum) return undefined; - const datum = parseStakingManagerDatum(utxo.datum); - return { utxo, datum }; - }) - .find((utxo) => utxo !== undefined), - ) - .then((result) => { - if (!result) - throw new Error( - 'Unable to locate Staking Manager by output reference.', - ); - return result; - }); + const utxo = await resolveUtxo( + stakingManager, + lucid, + 'Unable to locate Staking Manager by output reference.', + ); + if (!utxo.datum) { + throw new Error('Staking Manager UTxO has no datum.'); + } + const datum = parseStakingManagerDatum(utxo.datum); + return { utxo, datum }; } export function findStakingManager( @@ -92,28 +83,20 @@ export function findStakingManager( }); } -export function findStakingPositionByOutRef( - stakingPositionRef: OutRef, +export async function findStakingPositionByOutRef( + stakingPosition: UTxOOrOutRef, lucid: LucidEvolution, ): Promise { - return lucid - .utxosByOutRef([stakingPositionRef]) - .then((utxos) => - utxos - .map((utxo) => { - if (!utxo.datum) return undefined; - const datum = parseStakingPositionOrThrow(utxo.datum); - return { utxo, datum }; - }) - .find((utxo) => utxo !== undefined), - ) - .then((result) => { - if (!result) - throw new Error( - 'Unable to locate Staking Position by output reference.', - ); - return result; - }); + const utxo = await resolveUtxo( + stakingPosition, + lucid, + 'Unable to locate Staking Position by output reference.', + ); + if (!utxo.datum) { + throw new Error('Staking Position UTxO has no datum.'); + } + const datum = parseStakingPositionOrThrow(utxo.datum); + return { utxo, datum }; } export const rewardSnapshotPrecision = OCD_DECIMAL_UNIT * OCD_DECIMAL_UNIT; diff --git a/src/contracts/staking/transactions.ts b/src/contracts/staking/transactions.ts index beaa2eb..8b6f6b8 100644 --- a/src/contracts/staking/transactions.ts +++ b/src/contracts/staking/transactions.ts @@ -13,17 +13,20 @@ import { fromSystemParamsScriptRef, SystemParams, } from '../../types/system-params'; -import { addrDetails, getInlineDatumOrThrow } from '../../utils/lucid-utils'; +import { + addrDetails, + getInlineDatumOrThrow, + resolveUtxo, + UTxOOrOutRef, +} from '../../utils/lucid-utils'; import { distributeReward, - findStakingManager, - findStakingManagerByOutRef, - findStakingPositionByOutRef, rewardSnapshotPrecision, updateStakingLockedAmount, } from './helpers'; import { parseStakingManagerDatum, + parseStakingPositionOrThrow, serialiseStakingDatum, StakingManager, StakingPosition, @@ -38,13 +41,18 @@ export async function openStakingPosition( amount: bigint, params: SystemParams, lucid: LucidEvolution, - stakingManagerRef?: OutRef, + stakingManager: UTxOOrOutRef, ): Promise { const [pkh, _] = await addrDetails(lucid); - const stakingManagerOut = stakingManagerRef - ? await findStakingManagerByOutRef(stakingManagerRef, lucid) - : await findStakingManager(params, lucid); + const stakingManagerUtxo = await resolveUtxo( + stakingManager, + lucid, + 'Expected a single staking manager UTXO', + ); + const stakingManagerDatum = parseStakingManagerDatum( + getInlineDatumOrThrow(stakingManagerUtxo), + ); const stakingRefScriptUtxo = matchSingle( await lucid.utxosByOutRef([ @@ -62,9 +70,9 @@ export async function openStakingPosition( ); const newStakingManagerDatum: StakingManager = { - totalStake: stakingManagerOut.datum.totalStake + amount, + totalStake: stakingManagerDatum.totalStake + amount, managerSnapshot: { - snapshotAda: stakingManagerOut.datum.managerSnapshot.snapshotAda, + snapshotAda: stakingManagerDatum.managerSnapshot.snapshotAda, }, }; @@ -72,7 +80,7 @@ export async function openStakingPosition( owner: fromHex(pkh.hash), lockedAmount: new Map([]), positionSnapshot: { - snapshotAda: stakingManagerOut.datum.managerSnapshot.snapshotAda, + snapshotAda: stakingManagerDatum.managerSnapshot.snapshotAda, }, }; @@ -85,19 +93,19 @@ export async function openStakingPosition( return lucid .newTx() .collectFrom( - [stakingManagerOut.utxo], + [stakingManagerUtxo], serialiseStakingRedeemer({ CreateStakingPosition: { creatorPkh: pkh.hash }, }), ) .readFrom([stakingRefScriptUtxo]) .pay.ToContract( - stakingManagerOut.utxo.address, + stakingManagerUtxo.address, { kind: 'inline', value: serialiseStakingDatum(newStakingManagerDatum), }, - stakingManagerOut.utxo.assets, + stakingManagerUtxo.assets, ) .readFrom([stakingTokenPolicyRefScriptUtxo]) .mintAssets( @@ -107,7 +115,7 @@ export async function openStakingPosition( Data.void(), ) .pay.ToContract( - stakingManagerOut.utxo.address, + stakingManagerUtxo.address, { kind: 'inline', value: serialiseStakingDatum(stakingPositionDatum), @@ -121,23 +129,33 @@ export async function openStakingPosition( } export async function adjustStakingPosition( - stakingPositionRef: OutRef, + stakingPosition: UTxOOrOutRef, amount: bigint, params: SystemParams, lucid: LucidEvolution, currentSlot: number, - stakingManagerRef?: OutRef, + stakingManager: UTxOOrOutRef, ): Promise { const network = lucid.config().network!; const currentTime = slotToUnixTime(network, currentSlot) - 120 * ONE_SECOND; - const stakingPositionOut = await findStakingPositionByOutRef( - stakingPositionRef, + const stakingPositionUtxo = await resolveUtxo( + stakingPosition, lucid, + 'Expected a single staking position UTXO', + ); + const stakingPositionDatum = parseStakingPositionOrThrow( + getInlineDatumOrThrow(stakingPositionUtxo), + ); + + const stakingManagerUtxo = await resolveUtxo( + stakingManager, + lucid, + 'Expected a single staking manager UTXO', + ); + const stakingManagerDatum = parseStakingManagerDatum( + getInlineDatumOrThrow(stakingManagerUtxo), ); - const stakingManagerOut = stakingManagerRef - ? await findStakingManagerByOutRef(stakingManagerRef, lucid) - : await findStakingManager(params, lucid); const stakingRefScriptUtxo = matchSingle( await lucid.utxosByOutRef([ @@ -150,16 +168,15 @@ export async function adjustStakingPosition( params.stakingParams.indyToken[0].unCurrencySymbol + fromText(params.stakingParams.indyToken[1].unTokenName); - const existingIndyAmount = stakingPositionOut.utxo.assets[indyToken] ?? 0n; - const currentSnapshotAda = - stakingManagerOut.datum.managerSnapshot.snapshotAda; - const oldSnapshotAda = stakingPositionOut.datum.positionSnapshot.snapshotAda; + const existingIndyAmount = stakingPositionUtxo.assets[indyToken] ?? 0n; + const currentSnapshotAda = stakingManagerDatum.managerSnapshot.snapshotAda; + const oldSnapshotAda = stakingPositionDatum.positionSnapshot.snapshotAda; const adaReward = ((currentSnapshotAda - oldSnapshotAda) * existingIndyAmount) / rewardSnapshotPrecision; const newLockedAmount = updateStakingLockedAmount( - stakingPositionOut.datum.lockedAmount, + stakingPositionDatum.lockedAmount, BigInt(currentTime), ); @@ -168,38 +185,38 @@ export async function adjustStakingPosition( .validFrom(currentTime) .readFrom([stakingRefScriptUtxo]) .collectFrom( - [stakingPositionOut.utxo], + [stakingPositionUtxo], serialiseStakingRedeemer({ AdjustStakedAmount: { adjustAmount: amount }, }), ) .collectFrom( - [stakingManagerOut.utxo], + [stakingManagerUtxo], serialiseStakingRedeemer('UpdateTotalStake'), ) .pay.ToContract( - stakingManagerOut.utxo.address, + stakingManagerUtxo.address, { kind: 'inline', value: serialiseStakingDatum({ - ...stakingManagerOut.datum, - totalStake: stakingManagerOut.datum.totalStake + amount, + ...stakingManagerDatum, + totalStake: stakingManagerDatum.totalStake + amount, }), }, - addAssets(stakingManagerOut.utxo.assets, mkLovelacesOf(-adaReward)), + addAssets(stakingManagerUtxo.assets, mkLovelacesOf(-adaReward)), ) .pay.ToContract( - stakingPositionOut.utxo.address, + stakingPositionUtxo.address, { kind: 'inline', value: serialiseStakingDatum({ - ...stakingPositionOut.datum, + ...stakingPositionDatum, lockedAmount: newLockedAmount, - positionSnapshot: stakingManagerOut.datum.managerSnapshot, + positionSnapshot: stakingManagerDatum.managerSnapshot, }), }, addAssets( - stakingPositionOut.utxo.assets, + stakingPositionUtxo.assets, mkAssetsOf( { currencySymbol: params.stakingParams.indyToken[0].unCurrencySymbol, @@ -209,26 +226,36 @@ export async function adjustStakingPosition( ), ), ) - .addSignerKey(toHex(stakingPositionOut.datum.owner)); + .addSignerKey(toHex(stakingPositionDatum.owner)); } export async function closeStakingPosition( - stakingPositionRef: OutRef, + stakingPosition: UTxOOrOutRef, params: SystemParams, lucid: LucidEvolution, currentSlot: number, - stakingManagerRef?: OutRef, + stakingManager: UTxOOrOutRef, ): Promise { const network = lucid.config().network!; const currentTime = slotToUnixTime(network, currentSlot) - ONE_SECOND; - const stakingPositionOut = await findStakingPositionByOutRef( - stakingPositionRef, + const stakingPositionUtxo = await resolveUtxo( + stakingPosition, lucid, + 'Expected a single staking position UTXO', + ); + const stakingPositionDatum = parseStakingPositionOrThrow( + getInlineDatumOrThrow(stakingPositionUtxo), + ); + + const stakingManagerUtxo = await resolveUtxo( + stakingManager, + lucid, + 'Expected a single staking manager UTXO', + ); + const stakingManagerDatum = parseStakingManagerDatum( + getInlineDatumOrThrow(stakingManagerUtxo), ); - const stakingManagerOut = stakingManagerRef - ? await findStakingManagerByOutRef(stakingManagerRef, lucid) - : await findStakingManager(params, lucid); const stakingRefScriptUtxo = matchSingle( await lucid.utxosByOutRef([ @@ -252,10 +279,9 @@ export async function closeStakingPosition( params.stakingParams.indyToken[0].unCurrencySymbol + fromText(params.stakingParams.indyToken[1].unTokenName); - const existingIndyAmount = stakingPositionOut.utxo.assets[indyToken] ?? 0n; - const currentSnapshotAda = - stakingManagerOut.datum.managerSnapshot.snapshotAda; - const oldSnapshotAda = stakingPositionOut.datum.positionSnapshot.snapshotAda; + const existingIndyAmount = stakingPositionUtxo.assets[indyToken] ?? 0n; + const currentSnapshotAda = stakingManagerDatum.managerSnapshot.snapshotAda; + const oldSnapshotAda = stakingPositionDatum.positionSnapshot.snapshotAda; const adaReward = ((currentSnapshotAda - oldSnapshotAda) * existingIndyAmount) / (1000000n * 1000000n); @@ -264,21 +290,21 @@ export async function closeStakingPosition( .newTx() .validFrom(currentTime) .readFrom([stakingRefScriptUtxo, stakingTokenPolicyRefScriptUtxo]) - .collectFrom([stakingPositionOut.utxo], serialiseStakingRedeemer('Unstake')) + .collectFrom([stakingPositionUtxo], serialiseStakingRedeemer('Unstake')) .collectFrom( - [stakingManagerOut.utxo], + [stakingManagerUtxo], serialiseStakingRedeemer('UpdateTotalStake'), ) .pay.ToContract( - stakingManagerOut.utxo.address, + stakingManagerUtxo.address, { kind: 'inline', value: serialiseStakingDatum({ - ...stakingManagerOut.datum, - totalStake: stakingManagerOut.datum.totalStake - existingIndyAmount, + ...stakingManagerDatum, + totalStake: stakingManagerDatum.totalStake - existingIndyAmount, }), }, - addAssets(stakingManagerOut.utxo.assets, mkLovelacesOf(-adaReward)), + addAssets(stakingManagerUtxo.assets, mkLovelacesOf(-adaReward)), ) .mintAssets( { @@ -286,21 +312,26 @@ export async function closeStakingPosition( }, Data.void(), ) - .addSignerKey(toHex(stakingPositionOut.datum.owner)); + .addSignerKey(toHex(stakingPositionDatum.owner)); } const MIN_UTXO_AMOUNT = 2_000_000n; export async function distributeAda( - stakingManagerRef: OutRef, + stakingManager: UTxOOrOutRef, collectorRefs: OutRef[], params: SystemParams, lucid: LucidEvolution, ): Promise { - const [stakingManagerUtxo] = await lucid.utxosByOutRef([stakingManagerRef]); + const stakingManagerUtxo = await resolveUtxo( + stakingManager, + lucid, + 'Expected a single staking manager UTXO', + ); const stakingManagerDatum = parseStakingManagerDatum( getInlineDatumOrThrow(stakingManagerUtxo), ); + const collectorUtxos = (await lucid.utxosByOutRef(collectorRefs)) .filter((utxo) => utxo.datum && utxo.datum === Data.void()) .filter((utxo) => utxo.assets.lovelace > MIN_UTXO_AMOUNT); diff --git a/src/contracts/treasury/transactions.ts b/src/contracts/treasury/transactions.ts index 75c1ce7..9ff0db9 100644 --- a/src/contracts/treasury/transactions.ts +++ b/src/contracts/treasury/transactions.ts @@ -2,7 +2,6 @@ import { addAssets, Data, LucidEvolution, - OutRef, TxBuilder, } from '@lucid-evolution/lucid'; import { @@ -13,20 +12,25 @@ import { import { matchSingle } from '../../utils/utils'; import { mkLovelacesOf } from '../../utils/value-helpers'; import { serialiseTreasuryRedeemer } from './types'; -import { createScriptAddress } from '../../utils/lucid-utils'; +import { + createScriptAddress, + resolveUtxo, + UTxOOrOutRef, +} from '../../utils/lucid-utils'; export async function treasuryFeeTx( fee: bigint, lucid: LucidEvolution, sysParams: SystemParams, tx: TxBuilder, - treasuryOref: OutRef, + treasury: UTxOOrOutRef, ): Promise { if (fee <= 0n) return; - const treasuryUtxo = matchSingle( - await lucid.utxosByOutRef([treasuryOref]), - (_) => new Error('Expected a single treasury UTXO'), + const treasuryUtxo = await resolveUtxo( + treasury, + lucid, + 'Expected a single treasury UTXO', ); const treasuryRefScriptUtxo = matchSingle( diff --git a/src/utils/lucid-utils.ts b/src/utils/lucid-utils.ts index 8b12122..0617064 100644 --- a/src/utils/lucid-utils.ts +++ b/src/utils/lucid-utils.ts @@ -16,6 +16,39 @@ import { } from '@lucid-evolution/lucid'; import { ScriptReference } from '../types/system-params'; +/** + * Union type accepting either a full UTxO or just an OutRef. + * When a full UTxO is provided, no network fetch is needed. + * When only an OutRef is provided, the UTxO will be fetched via utxosByOutRef. + */ +export type UTxOOrOutRef = UTxO | OutRef; + +/** + * Resolves a UTxOOrOutRef to a full UTxO. + * If the input is already a UTxO (has 'address' property), returns it directly. + * If the input is an OutRef, fetches the UTxO from the network. + * + * @param input - Either a full UTxO or an OutRef + * @param lucid - The LucidEvolution instance for network queries + * @param errorMsg - Custom error message if the UTxO cannot be found + * @returns The resolved UTxO + */ +export async function resolveUtxo( + input: UTxOOrOutRef, + lucid: LucidEvolution, + errorMsg: string = 'Expected a single UTXO', +): Promise { + // UTxO has 'address' property, OutRef only has 'txHash' and 'outputIndex' + if ('address' in input) { + return input; + } + const utxos = await lucid.utxosByOutRef([input]); + if (utxos.length !== 1) { + throw new Error(errorMsg); + } + return utxos[0]; +} + /** * Returns the inline datum. * Throws when the UTXO doesn't have an inline datum diff --git a/tests/gov.test.ts b/tests/gov.test.ts index 1cf4678..997e339 100644 --- a/tests/gov.test.ts +++ b/tests/gov.test.ts @@ -27,6 +27,7 @@ import { createShardsChunks, endProposal, executeProposal, + findStakingManager, fromSystemParamsAsset, matchSingle, mergeShards, @@ -525,7 +526,12 @@ describe('Gov', () => { await runAndAwaitTx( context.lucid, - openStakingPosition(1_000_000n, sysParams, context.lucid), + openStakingPosition( + 1_000_000n, + sysParams, + context.lucid, + (await findStakingManager(sysParams, context.lucid)).utxo, + ), ); await runVote(pollId, 'Yes', sysParams, context); @@ -558,7 +564,12 @@ describe('Gov', () => { await runAndAwaitTx( context.lucid, - openStakingPosition(1_000_000n, sysParams, context.lucid), + openStakingPosition( + 1_000_000n, + sysParams, + context.lucid, + (await findStakingManager(sysParams, context.lucid)).utxo, + ), ); await runVote(pollId, 'Yes', sysParams, context); @@ -581,6 +592,7 @@ describe('Gov', () => { sysParams, context.lucid, context.emulator.slot, + (await findStakingManager(sysParams, context.lucid)).utxo, ), ); }); @@ -592,7 +604,12 @@ describe('Gov', () => { await runAndAwaitTx( context.lucid, - openStakingPosition(1_000_000n, sysParams, context.lucid), + openStakingPosition( + 1_000_000n, + sysParams, + context.lucid, + (await findStakingManager(sysParams, context.lucid)).utxo, + ), ); const [pkh, _] = await addrDetails(context.lucid); @@ -665,7 +682,12 @@ describe('Gov', () => { await runAndAwaitTx( context.lucid, - openStakingPosition(1_000_000n, sysParams, context.lucid), + openStakingPosition( + 1_000_000n, + sysParams, + context.lucid, + (await findStakingManager(sysParams, context.lucid)).utxo, + ), ); const [pkh, _] = await addrDetails(context.lucid); @@ -765,7 +787,12 @@ describe('Gov', () => { await runAndAwaitTx( context.lucid, - openStakingPosition(100_000_000_000n, sysParams, context.lucid), + openStakingPosition( + 100_000_000_000n, + sysParams, + context.lucid, + (await findStakingManager(sysParams, context.lucid)).utxo, + ), ); await runVote(pollId, 'Yes', sysParams, context); @@ -813,7 +840,12 @@ describe('Gov', () => { await runAndAwaitTx( context.lucid, - openStakingPosition(100_000_000_000n, sysParams, context.lucid), + openStakingPosition( + 100_000_000_000n, + sysParams, + context.lucid, + (await findStakingManager(sysParams, context.lucid)).utxo, + ), ); await runVote(pollId, 'No', sysParams, context); @@ -919,7 +951,12 @@ describe('Gov', () => { await runAndAwaitTx( context.lucid, - openStakingPosition(100_000_000_000n, sysParams, context.lucid), + openStakingPosition( + 100_000_000_000n, + sysParams, + context.lucid, + (await findStakingManager(sysParams, context.lucid)).utxo, + ), ); await runVote(pollId, 'Yes', sysParams, context); @@ -1000,7 +1037,12 @@ describe('Gov', () => { await runAndAwaitTx( context.lucid, - openStakingPosition(100_000_000_000n, sysParams, context.lucid), + openStakingPosition( + 100_000_000_000n, + sysParams, + context.lucid, + (await findStakingManager(sysParams, context.lucid)).utxo, + ), ); await runVote(pollId, 'Yes', sysParams, context); @@ -1121,7 +1163,12 @@ describe('Gov', () => { await runAndAwaitTx( context.lucid, - openStakingPosition(100_000_000_000n, sysParams, context.lucid), + openStakingPosition( + 100_000_000_000n, + sysParams, + context.lucid, + (await findStakingManager(sysParams, context.lucid)).utxo, + ), ); await runVote(pollId, 'Yes', sysParams, context); @@ -1252,7 +1299,12 @@ describe('Gov', () => { await runAndAwaitTx( context.lucid, - openStakingPosition(100_000_000_000n, sysParams, context.lucid), + openStakingPosition( + 100_000_000_000n, + sysParams, + context.lucid, + (await findStakingManager(sysParams, context.lucid)).utxo, + ), ); await runVote(pollId, 'Yes', sysParams, context); @@ -1365,7 +1417,12 @@ describe('Gov', () => { await runAndAwaitTx( context.lucid, - openStakingPosition(100_000_000_000n, sysParams, context.lucid), + openStakingPosition( + 100_000_000_000n, + sysParams, + context.lucid, + (await findStakingManager(sysParams, context.lucid)).utxo, + ), ); await runVote(pollId, 'Yes', sysParams, context); @@ -1475,7 +1532,12 @@ describe('Gov', () => { await runAndAwaitTx( context.lucid, - openStakingPosition(100_000_000_000n, sysParams, context.lucid), + openStakingPosition( + 100_000_000_000n, + sysParams, + context.lucid, + (await findStakingManager(sysParams, context.lucid)).utxo, + ), ); await runVote(pollId, 'Yes', sysParams, context); @@ -1576,7 +1638,12 @@ describe('Gov', () => { await runAndAwaitTx( context.lucid, - openStakingPosition(100_000_000_000n, sysParams, context.lucid), + openStakingPosition( + 100_000_000_000n, + sysParams, + context.lucid, + (await findStakingManager(sysParams, context.lucid)).utxo, + ), ); await runVote(pollId, 'Yes', sysParams, context); @@ -1680,7 +1747,12 @@ describe('Gov', () => { await runAndAwaitTx( context.lucid, - openStakingPosition(100_000_000_000n, sysParams, context.lucid), + openStakingPosition( + 100_000_000_000n, + sysParams, + context.lucid, + (await findStakingManager(sysParams, context.lucid)).utxo, + ), ); await runVote(pollId, 'Yes', sysParams, context); @@ -1776,7 +1848,12 @@ describe('Gov', () => { await runAndAwaitTx( context.lucid, - openStakingPosition(100_000_000_000n, sysParams, context.lucid), + openStakingPosition( + 100_000_000_000n, + sysParams, + context.lucid, + (await findStakingManager(sysParams, context.lucid)).utxo, + ), ); await runVote(pollId, 'Yes', sysParams, context); @@ -1875,7 +1952,12 @@ describe('Gov', () => { await runAndAwaitTx( context.lucid, - openStakingPosition(100_000_000_000n, sysParams, context.lucid), + openStakingPosition( + 100_000_000_000n, + sysParams, + context.lucid, + (await findStakingManager(sysParams, context.lucid)).utxo, + ), ); await runVote(pollId, 'Yes', sysParams, context); diff --git a/tests/staking.test.ts b/tests/staking.test.ts index f6acc5f..2e5fd19 100644 --- a/tests/staking.test.ts +++ b/tests/staking.test.ts @@ -44,10 +44,11 @@ test('Staking - Create Position', async ({ }: MyContext) => { lucid.selectWallet.fromSeed(users.admin.seedPhrase); const [systemParams, _] = await init(lucid, [iusdInitialAssetCfg]); + const stakingManager = await findStakingManager(systemParams, lucid); await runAndAwaitTx( lucid, - openStakingPosition(1_000_000n, systemParams, lucid), + openStakingPosition(1_000_000n, systemParams, lucid, stakingManager.utxo), ); }); @@ -61,7 +62,12 @@ test('Staking - Adjust Position', async ({ await runAndAwaitTx( lucid, - openStakingPosition(1_000_000n, systemParams, lucid), + openStakingPosition( + 1_000_000n, + systemParams, + lucid, + (await findStakingManager(systemParams, lucid)).utxo, + ), ); const [pkh, __] = await addrDetails(lucid); @@ -80,6 +86,7 @@ test('Staking - Adjust Position', async ({ systemParams, lucid, emulator.slot, + (await findStakingManager(systemParams, lucid)).utxo, ), ); }); @@ -94,7 +101,12 @@ test('Staking - Close Position', async ({ await runAndAwaitTx( lucid, - openStakingPosition(1_000_000n, systemParams, lucid), + openStakingPosition( + 1_000_000n, + systemParams, + lucid, + (await findStakingManager(systemParams, lucid)).utxo, + ), ); const [pkh, __] = await addrDetails(lucid); @@ -112,6 +124,7 @@ test('Staking - Close Position', async ({ systemParams, lucid, emulator.slot, + (await findStakingManager(systemParams, lucid)).utxo, ), ); }); @@ -126,7 +139,12 @@ test('Staking - Distribute ADA to Stakers', async ({ await runAndAwaitTx( lucid, - openStakingPosition(1_000_000n, systemParams, lucid), + openStakingPosition( + 1_000_000n, + systemParams, + lucid, + (await findStakingManager(systemParams, lucid)).utxo, + ), ); const collectorOref = await findRandomCollector( @@ -165,7 +183,7 @@ test('Staking - Distribute ADA to Stakers', async ({ const [____, userValChange] = await getValueChangeAtAddressAfterAction( lucid, users.admin.address, - () => + async () => runAndAwaitTx( lucid, closeStakingPosition( @@ -173,6 +191,7 @@ test('Staking - Distribute ADA to Stakers', async ({ systemParams, lucid, emulator.slot, + (await findStakingManager(systemParams, lucid)).utxo, ), ), ); From 0ed3cf33865b6bfc8fba35172adb70bf857fa70d Mon Sep 17 00:00:00 2001 From: Cody Butz Date: Mon, 16 Feb 2026 08:28:44 -0500 Subject: [PATCH 2/2] Reesolve comments --- src/contracts/cdp/transactions.ts | 124 +++++++++--------- src/contracts/collector/transactions.ts | 4 +- src/contracts/gov/transactions.ts | 24 ++-- src/contracts/interest-oracle/transactions.ts | 4 +- src/contracts/leverage/transactions.ts | 12 +- src/contracts/lrp/transactions.ts | 12 +- src/contracts/price-oracle/transactions.ts | 4 +- src/contracts/stability-pool/transactions.ts | 4 +- src/contracts/staking/helpers.ts | 6 +- src/contracts/staking/transactions.ts | 14 +- src/contracts/treasury/transactions.ts | 4 +- src/utils/lucid-utils.ts | 14 +- 12 files changed, 113 insertions(+), 113 deletions(-) diff --git a/src/contracts/cdp/transactions.ts b/src/contracts/cdp/transactions.ts index d7785f0..e81cc29 100644 --- a/src/contracts/cdp/transactions.ts +++ b/src/contracts/cdp/transactions.ts @@ -18,7 +18,7 @@ import { createScriptAddress, getInlineDatumOrThrow, resolveUtxo, - UTxOOrOutRef, + UtxoOrOutRef, } from '../../utils/lucid-utils'; import { matchSingle } from '../../utils/utils'; import { @@ -63,11 +63,11 @@ export async function openCdp( collateralAmount: bigint, mintedAmount: bigint, sysParams: SystemParams, - cdpCreator: UTxOOrOutRef, - iasset: UTxOOrOutRef, - priceOracle: UTxOOrOutRef, - interestOracle: UTxOOrOutRef, - collector: UTxOOrOutRef, + cdpCreator: UtxoOrOutRef, + iasset: UtxoOrOutRef, + priceOracle: UtxoOrOutRef, + interestOracle: UtxoOrOutRef, + collector: UtxoOrOutRef, lucid: LucidEvolution, currentSlot: number, ): Promise { @@ -227,13 +227,13 @@ export async function openCdp( async function adjustCdp( collateralAmount: bigint, mintAmount: bigint, - cdp: UTxOOrOutRef, - iasset: UTxOOrOutRef, - priceOracle: UTxOOrOutRef, - interestOracle: UTxOOrOutRef, - collector: UTxOOrOutRef, - gov: UTxOOrOutRef, - treasury: UTxOOrOutRef, + cdp: UtxoOrOutRef, + iasset: UtxoOrOutRef, + priceOracle: UtxoOrOutRef, + interestOracle: UtxoOrOutRef, + collector: UtxoOrOutRef, + gov: UtxoOrOutRef, + treasury: UtxoOrOutRef, sysParams: SystemParams, lucid: LucidEvolution, currentSlot: number, @@ -421,13 +421,13 @@ async function adjustCdp( export async function depositCdp( amount: bigint, - cdp: UTxOOrOutRef, - iasset: UTxOOrOutRef, - priceOracle: UTxOOrOutRef, - interestOracle: UTxOOrOutRef, - collector: UTxOOrOutRef, - gov: UTxOOrOutRef, - treasury: UTxOOrOutRef, + cdp: UtxoOrOutRef, + iasset: UtxoOrOutRef, + priceOracle: UtxoOrOutRef, + interestOracle: UtxoOrOutRef, + collector: UtxoOrOutRef, + gov: UtxoOrOutRef, + treasury: UtxoOrOutRef, params: SystemParams, lucid: LucidEvolution, currentSlot: number, @@ -450,13 +450,13 @@ export async function depositCdp( export async function withdrawCdp( amount: bigint, - cdp: UTxOOrOutRef, - iasset: UTxOOrOutRef, - priceOracle: UTxOOrOutRef, - interestOracle: UTxOOrOutRef, - collector: UTxOOrOutRef, - gov: UTxOOrOutRef, - treasury: UTxOOrOutRef, + cdp: UtxoOrOutRef, + iasset: UtxoOrOutRef, + priceOracle: UtxoOrOutRef, + interestOracle: UtxoOrOutRef, + collector: UtxoOrOutRef, + gov: UtxoOrOutRef, + treasury: UtxoOrOutRef, params: SystemParams, lucid: LucidEvolution, currentSlot: number, @@ -479,13 +479,13 @@ export async function withdrawCdp( export async function mintCdp( amount: bigint, - cdp: UTxOOrOutRef, - iasset: UTxOOrOutRef, - priceOracle: UTxOOrOutRef, - interestOracle: UTxOOrOutRef, - collector: UTxOOrOutRef, - gov: UTxOOrOutRef, - treasury: UTxOOrOutRef, + cdp: UtxoOrOutRef, + iasset: UtxoOrOutRef, + priceOracle: UtxoOrOutRef, + interestOracle: UtxoOrOutRef, + collector: UtxoOrOutRef, + gov: UtxoOrOutRef, + treasury: UtxoOrOutRef, params: SystemParams, lucid: LucidEvolution, currentSlot: number, @@ -508,13 +508,13 @@ export async function mintCdp( export async function burnCdp( amount: bigint, - cdp: UTxOOrOutRef, - iasset: UTxOOrOutRef, - priceOracle: UTxOOrOutRef, - interestOracle: UTxOOrOutRef, - collector: UTxOOrOutRef, - gov: UTxOOrOutRef, - treasury: UTxOOrOutRef, + cdp: UtxoOrOutRef, + iasset: UtxoOrOutRef, + priceOracle: UtxoOrOutRef, + interestOracle: UtxoOrOutRef, + collector: UtxoOrOutRef, + gov: UtxoOrOutRef, + treasury: UtxoOrOutRef, params: SystemParams, lucid: LucidEvolution, currentSlot: number, @@ -536,13 +536,13 @@ export async function burnCdp( } export async function closeCdp( - cdp: UTxOOrOutRef, - iasset: UTxOOrOutRef, - priceOracle: UTxOOrOutRef, - interestOracle: UTxOOrOutRef, - collector: UTxOOrOutRef, - gov: UTxOOrOutRef, - treasury: UTxOOrOutRef, + cdp: UtxoOrOutRef, + iasset: UtxoOrOutRef, + priceOracle: UtxoOrOutRef, + interestOracle: UtxoOrOutRef, + collector: UtxoOrOutRef, + gov: UtxoOrOutRef, + treasury: UtxoOrOutRef, sysParams: SystemParams, lucid: LucidEvolution, currentSlot: number, @@ -700,12 +700,12 @@ export async function redeemCdp( * The logic will automatically cap the amount to the max. */ attemptedRedemptionIAssetAmt: bigint, - cdp: UTxOOrOutRef, - iasset: UTxOOrOutRef, - priceOracle: UTxOOrOutRef, - interestOracle: UTxOOrOutRef, - collector: UTxOOrOutRef, - treasury: UTxOOrOutRef, + cdp: UtxoOrOutRef, + iasset: UtxoOrOutRef, + priceOracle: UtxoOrOutRef, + interestOracle: UtxoOrOutRef, + collector: UtxoOrOutRef, + treasury: UtxoOrOutRef, sysParams: SystemParams, lucid: LucidEvolution, currentSlot: number, @@ -899,10 +899,10 @@ export async function redeemCdp( } export async function freezeCdp( - cdp: UTxOOrOutRef, - iasset: UTxOOrOutRef, - priceOracle: UTxOOrOutRef, - interestOracle: UTxOOrOutRef, + cdp: UtxoOrOutRef, + iasset: UtxoOrOutRef, + priceOracle: UtxoOrOutRef, + interestOracle: UtxoOrOutRef, sysParams: SystemParams, lucid: LucidEvolution, currentSlot: number, @@ -1043,10 +1043,10 @@ export async function freezeCdp( } export async function liquidateCdp( - cdp: UTxOOrOutRef, - stabilityPool: UTxOOrOutRef, - collector: UTxOOrOutRef, - treasury: UTxOOrOutRef, + cdp: UtxoOrOutRef, + stabilityPool: UtxoOrOutRef, + collector: UtxoOrOutRef, + treasury: UtxoOrOutRef, sysParams: SystemParams, lucid: LucidEvolution, ): Promise { diff --git a/src/contracts/collector/transactions.ts b/src/contracts/collector/transactions.ts index 1e6c98b..d32d9fe 100644 --- a/src/contracts/collector/transactions.ts +++ b/src/contracts/collector/transactions.ts @@ -4,7 +4,7 @@ import { SystemParams, } from '../../types/system-params'; import { matchSingle } from '../../utils/utils'; -import { resolveUtxo, UTxOOrOutRef } from '../../utils/lucid-utils'; +import { resolveUtxo, UtxoOrOutRef } from '../../utils/lucid-utils'; import { serialiseCollectorRedeemer } from './types'; export async function collectorFeeTx( @@ -12,7 +12,7 @@ export async function collectorFeeTx( lucid: LucidEvolution, params: SystemParams, tx: TxBuilder, - collector: UTxOOrOutRef, + collector: UtxoOrOutRef, ): Promise { const collectorUtxo: UTxO = await resolveUtxo( collector, diff --git a/src/contracts/gov/transactions.ts b/src/contracts/gov/transactions.ts index 2e5aaeb..5c8c52e 100644 --- a/src/contracts/gov/transactions.ts +++ b/src/contracts/gov/transactions.ts @@ -22,7 +22,7 @@ import { createScriptAddress, getInlineDatumOrThrow, resolveUtxo, - UTxOOrOutRef, + UtxoOrOutRef, } from '../../utils/lucid-utils'; import { parsePollManagerOrThrow, @@ -102,7 +102,7 @@ export async function createProposal( sysParams: SystemParams, lucid: LucidEvolution, currentSlot: number, - gov: UTxOOrOutRef, + gov: UtxoOrOutRef, /** * This has to be passed only in case of createAsset proposal */ @@ -255,7 +255,7 @@ export async function createShardsChunks( * This gets automatically capped to total shards count. */ chunkSize: bigint, - pollManager: UTxOOrOutRef, + pollManager: UtxoOrOutRef, sysParams: SystemParams, currentSlot: number, lucid: LucidEvolution, @@ -403,8 +403,8 @@ function voteHelper( export async function vote( voteOption: VoteOption, - pollShard: UTxOOrOutRef, - stakingPosition: UTxOOrOutRef, + pollShard: UtxoOrOutRef, + stakingPosition: UtxoOrOutRef, sysParams: SystemParams, lucid: LucidEvolution, currentSlot: number, @@ -515,7 +515,7 @@ export async function vote( } export async function mergeShards( - pollManager: UTxOOrOutRef, + pollManager: UtxoOrOutRef, shardsOutRefs: OutRef[], sysParams: SystemParams, lucid: LucidEvolution, @@ -635,8 +635,8 @@ export async function mergeShards( } export async function endProposal( - pollManager: UTxOOrOutRef, - gov: UTxOOrOutRef, + pollManager: UtxoOrOutRef, + gov: UtxoOrOutRef, sysParams: SystemParams, lucid: LucidEvolution, currentSlot: number, @@ -781,11 +781,11 @@ export async function endProposal( } export async function executeProposal( - execute: UTxOOrOutRef, - gov: UTxOOrOutRef, - treasuryWithdrawal: UTxOOrOutRef | null, + execute: UtxoOrOutRef, + gov: UtxoOrOutRef, + treasuryWithdrawal: UtxoOrOutRef | null, allIAssetOrefs: OutRef[] | null, - modifyIAsset: UTxOOrOutRef | null, + modifyIAsset: UtxoOrOutRef | null, sysParams: SystemParams, lucid: LucidEvolution, currentSlot: number, diff --git a/src/contracts/interest-oracle/transactions.ts b/src/contracts/interest-oracle/transactions.ts index cdde7a6..e796cbe 100644 --- a/src/contracts/interest-oracle/transactions.ts +++ b/src/contracts/interest-oracle/transactions.ts @@ -6,7 +6,7 @@ import { UTxO, validatorToAddress, } from '@lucid-evolution/lucid'; -import { UTxOOrOutRef } from '../../utils/lucid-utils'; +import { UtxoOrOutRef } from '../../utils/lucid-utils'; import { AssetClass } from '../../types/generic'; import { InterestOracleParams, @@ -29,7 +29,7 @@ export async function startInterestOracle( lucid: LucidEvolution, interestTokenName?: string, withScriptRef: boolean = false, - refUtxo?: UTxOOrOutRef, + refUtxo?: UtxoOrOutRef, ): Promise<[TxBuilder, AssetClass]> { const network = lucid.config().network!; diff --git a/src/contracts/leverage/transactions.ts b/src/contracts/leverage/transactions.ts index 46cd12c..07c579d 100644 --- a/src/contracts/leverage/transactions.ts +++ b/src/contracts/leverage/transactions.ts @@ -11,7 +11,7 @@ import { createScriptAddress, getInlineDatumOrThrow, resolveUtxo, - UTxOOrOutRef, + UtxoOrOutRef, } from '../../utils/lucid-utils'; import { parsePriceOracleDatum } from '../price-oracle/types'; import { ocdMul } from '../../types/on-chain-decimal'; @@ -44,11 +44,11 @@ import { export async function leverageCdpWithLrp( leverage: number, baseCollateral: bigint, - priceOracle: UTxOOrOutRef, - iasset: UTxOOrOutRef, - cdpCreator: UTxOOrOutRef, - interestOracle: UTxOOrOutRef, - collector: UTxOOrOutRef, + priceOracle: UtxoOrOutRef, + iasset: UtxoOrOutRef, + cdpCreator: UtxoOrOutRef, + interestOracle: UtxoOrOutRef, + collector: UtxoOrOutRef, sysParams: SystemParams, lucid: LucidEvolution, allLrps: [UTxO, LRPDatum][], diff --git a/src/contracts/lrp/transactions.ts b/src/contracts/lrp/transactions.ts index 95c668b..dfd86e5 100644 --- a/src/contracts/lrp/transactions.ts +++ b/src/contracts/lrp/transactions.ts @@ -12,7 +12,7 @@ import { createScriptAddress, getInlineDatumOrThrow, resolveUtxo, - UTxOOrOutRef, + UtxoOrOutRef, } from '../../utils/lucid-utils'; import { unzip, zip } from 'fp-ts/lib/Array'; import { @@ -71,7 +71,7 @@ export async function openLrp( } export async function cancelLrp( - lrp: UTxOOrOutRef, + lrp: UtxoOrOutRef, sysParams: SystemParams, lucid: LucidEvolution, ): Promise { @@ -96,8 +96,8 @@ export async function cancelLrp( export async function redeemLrp( /** The tuple represents the LRP outref and the amount of iAssets to redeem against it. */ redemptionLrpsData: [OutRef, bigint][], - priceOracle: UTxOOrOutRef, - iasset: UTxOOrOutRef, + priceOracle: UtxoOrOutRef, + iasset: UtxoOrOutRef, lucid: LucidEvolution, sysParams: SystemParams, ): Promise { @@ -168,7 +168,7 @@ export async function redeemLrp( */ export async function adjustLrp( lucid: LucidEvolution, - lrp: UTxOOrOutRef, + lrp: UtxoOrOutRef, /** * A positive amount increases the lovelaces in the LRP, * and a negative amount takes lovelaces from the LRP. @@ -243,7 +243,7 @@ export async function adjustLrp( */ export async function claimLrp( lucid: LucidEvolution, - lrp: UTxOOrOutRef, + lrp: UtxoOrOutRef, sysParams: SystemParams, ): Promise { return adjustLrp(lucid, lrp, 0n, undefined, sysParams); diff --git a/src/contracts/price-oracle/transactions.ts b/src/contracts/price-oracle/transactions.ts index 94b43d8..e15290b 100644 --- a/src/contracts/price-oracle/transactions.ts +++ b/src/contracts/price-oracle/transactions.ts @@ -20,7 +20,7 @@ import { oneShotMintTx } from '../one-shot/transactions'; import { mkAssetsOf, mkLovelacesOf } from '../../utils/value-helpers'; import { OnChainDecimal } from '../../types/on-chain-decimal'; import { ONE_SECOND } from '../../utils/time-helpers'; -import { resolveUtxo, UTxOOrOutRef } from '../../utils/lucid-utils'; +import { resolveUtxo, UtxoOrOutRef } from '../../utils/lucid-utils'; export async function startPriceOracleTx( lucid: LucidEvolution, @@ -70,7 +70,7 @@ export async function startPriceOracleTx( export async function feedPriceOracleTx( lucid: LucidEvolution, - oracle: UTxOOrOutRef, + oracle: UtxoOrOutRef, newPrice: OnChainDecimal, oracleParams: PriceOracleParams, currentSlot: number, diff --git a/src/contracts/stability-pool/transactions.ts b/src/contracts/stability-pool/transactions.ts index d945510..d01a6c0 100644 --- a/src/contracts/stability-pool/transactions.ts +++ b/src/contracts/stability-pool/transactions.ts @@ -16,7 +16,7 @@ import { addrDetails, getInlineDatumOrThrow, scriptRef, - UTxOOrOutRef, + UtxoOrOutRef, } from '../../utils/lucid-utils'; import { mkStabilityPoolValidatorFromSP } from './scripts'; import { @@ -236,7 +236,7 @@ export async function processSpRequest( newSnapshotUtxo: UTxO | undefined, params: SystemParams, lucid: LucidEvolution, - collector: UTxOOrOutRef, + collector: UtxoOrOutRef, ): Promise { const redeemer: StabilityPoolRedeemer = { ProcessRequest: { diff --git a/src/contracts/staking/helpers.ts b/src/contracts/staking/helpers.ts index ed08fdf..e23db9a 100644 --- a/src/contracts/staking/helpers.ts +++ b/src/contracts/staking/helpers.ts @@ -11,7 +11,7 @@ import { import { createScriptAddress, resolveUtxo, - UTxOOrOutRef, + UtxoOrOutRef, } from '../../utils/lucid-utils'; import { mkStakingValidatorFromSP } from './scripts'; import { OCD_DECIMAL_UNIT } from '../../types/on-chain-decimal'; @@ -37,7 +37,7 @@ export function updateStakingLockedAmount( } export async function findStakingManagerByOutRef( - stakingManager: UTxOOrOutRef, + stakingManager: UtxoOrOutRef, lucid: LucidEvolution, ): Promise { const utxo = await resolveUtxo( @@ -84,7 +84,7 @@ export function findStakingManager( } export async function findStakingPositionByOutRef( - stakingPosition: UTxOOrOutRef, + stakingPosition: UtxoOrOutRef, lucid: LucidEvolution, ): Promise { const utxo = await resolveUtxo( diff --git a/src/contracts/staking/transactions.ts b/src/contracts/staking/transactions.ts index 8b6f6b8..6e75f6a 100644 --- a/src/contracts/staking/transactions.ts +++ b/src/contracts/staking/transactions.ts @@ -17,7 +17,7 @@ import { addrDetails, getInlineDatumOrThrow, resolveUtxo, - UTxOOrOutRef, + UtxoOrOutRef, } from '../../utils/lucid-utils'; import { distributeReward, @@ -41,7 +41,7 @@ export async function openStakingPosition( amount: bigint, params: SystemParams, lucid: LucidEvolution, - stakingManager: UTxOOrOutRef, + stakingManager: UtxoOrOutRef, ): Promise { const [pkh, _] = await addrDetails(lucid); @@ -129,12 +129,12 @@ export async function openStakingPosition( } export async function adjustStakingPosition( - stakingPosition: UTxOOrOutRef, + stakingPosition: UtxoOrOutRef, amount: bigint, params: SystemParams, lucid: LucidEvolution, currentSlot: number, - stakingManager: UTxOOrOutRef, + stakingManager: UtxoOrOutRef, ): Promise { const network = lucid.config().network!; const currentTime = slotToUnixTime(network, currentSlot) - 120 * ONE_SECOND; @@ -230,11 +230,11 @@ export async function adjustStakingPosition( } export async function closeStakingPosition( - stakingPosition: UTxOOrOutRef, + stakingPosition: UtxoOrOutRef, params: SystemParams, lucid: LucidEvolution, currentSlot: number, - stakingManager: UTxOOrOutRef, + stakingManager: UtxoOrOutRef, ): Promise { const network = lucid.config().network!; const currentTime = slotToUnixTime(network, currentSlot) - ONE_SECOND; @@ -318,7 +318,7 @@ export async function closeStakingPosition( const MIN_UTXO_AMOUNT = 2_000_000n; export async function distributeAda( - stakingManager: UTxOOrOutRef, + stakingManager: UtxoOrOutRef, collectorRefs: OutRef[], params: SystemParams, lucid: LucidEvolution, diff --git a/src/contracts/treasury/transactions.ts b/src/contracts/treasury/transactions.ts index 9ff0db9..b51a6c1 100644 --- a/src/contracts/treasury/transactions.ts +++ b/src/contracts/treasury/transactions.ts @@ -15,7 +15,7 @@ import { serialiseTreasuryRedeemer } from './types'; import { createScriptAddress, resolveUtxo, - UTxOOrOutRef, + UtxoOrOutRef, } from '../../utils/lucid-utils'; export async function treasuryFeeTx( @@ -23,7 +23,7 @@ export async function treasuryFeeTx( lucid: LucidEvolution, sysParams: SystemParams, tx: TxBuilder, - treasury: UTxOOrOutRef, + treasury: UtxoOrOutRef, ): Promise { if (fee <= 0n) return; diff --git a/src/utils/lucid-utils.ts b/src/utils/lucid-utils.ts index 0617064..ff3cac7 100644 --- a/src/utils/lucid-utils.ts +++ b/src/utils/lucid-utils.ts @@ -15,13 +15,14 @@ import { UTxO, } from '@lucid-evolution/lucid'; import { ScriptReference } from '../types/system-params'; +import { matchSingle } from './utils'; /** * Union type accepting either a full UTxO or just an OutRef. * When a full UTxO is provided, no network fetch is needed. * When only an OutRef is provided, the UTxO will be fetched via utxosByOutRef. */ -export type UTxOOrOutRef = UTxO | OutRef; +export type UtxoOrOutRef = UTxO | OutRef; /** * Resolves a UTxOOrOutRef to a full UTxO. @@ -34,7 +35,7 @@ export type UTxOOrOutRef = UTxO | OutRef; * @returns The resolved UTxO */ export async function resolveUtxo( - input: UTxOOrOutRef, + input: UtxoOrOutRef, lucid: LucidEvolution, errorMsg: string = 'Expected a single UTXO', ): Promise { @@ -42,11 +43,10 @@ export async function resolveUtxo( if ('address' in input) { return input; } - const utxos = await lucid.utxosByOutRef([input]); - if (utxos.length !== 1) { - throw new Error(errorMsg); - } - return utxos[0]; + return matchSingle( + await lucid.utxosByOutRef([input]), + (_) => new Error(errorMsg), + ); } /**