From ac55fec446b83bd594925171e390e968ca0fe135 Mon Sep 17 00:00:00 2001 From: Ha Quang Minh Date: Thu, 31 Oct 2024 15:01:25 +0700 Subject: [PATCH] example+wip of counting seller --- examples/example.ts | 37 +++++++++- src/lbe-v2.ts | 174 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 209 insertions(+), 2 deletions(-) diff --git a/examples/example.ts b/examples/example.ts index 60bba35..46b95f6 100644 --- a/examples/example.ts +++ b/examples/example.ts @@ -67,7 +67,7 @@ async function main(): Promise { // const utxos = await lucid.utxosAt(address); - const txComplete = await _cancelLbeV2EventByOwnerExample( + const txComplete = await _lbeV2AddMoreSellersExample( lucid, address, blockfrostAdapter @@ -1221,6 +1221,41 @@ async function _createLbeV2EventExample( }); } +// Example Tx: b3c7049ff4402bdb2f3fe6522c720fad499d5f3dae512299dfb3a5e011a66496 +async function _lbeV2AddMoreSellersExample( + lucid: Lucid, + address: Address, + blockfrostAdapter: BlockfrostAdapter +): Promise { + const baseAsset = Asset.fromString( + "e16c2dc8ae937e8d3790c7fd7168d7b994621ba14ca11415f39fed7243414b45" + ); + const raiseAsset = Asset.fromString("lovelace"); + + const lbeId = PoolV2.computeLPAssetName(baseAsset, raiseAsset); + const treasury = await blockfrostAdapter.getLbeV2TreasuryByLbeId(lbeId); + invariant(treasury !== null, `Can not find treasury by lbeId ${lbeId}`); + const treasuryUtxos = await lucid.utxosByOutRef([ + { txHash: treasury.txIn.txHash, outputIndex: treasury.txIn.index }, + ]); + invariant(treasuryUtxos.length === 1, "Can not find treasury Utxo"); + + const manager = await blockfrostAdapter.getLbeV2ManagerByLbeId(lbeId); + invariant(manager !== null, `Can not find manager by lbeId ${lbeId}`); + const managerUtxos = await lucid.utxosByOutRef([ + { txHash: manager.txIn.txHash, outputIndex: manager.txIn.index }, + ]); + invariant(managerUtxos.length === 1, "Can not find manager Utxo"); + + return new LbeV2(lucid).addSellers({ + treasuryUtxo: treasuryUtxos[0], + managerUtxo: managerUtxos[0], + addSellerCount: 2, + sellerOwner: address, + currentSlot: await blockfrostAdapter.currentSlot(), + }); +} + // Example Tx: b1819fbee0bb1eace80f97a75089a8b87047ea2f18959092949306e5301b048d async function _cancelLbeV2EventByOwnerExample( lucid: Lucid, diff --git a/src/lbe-v2.ts b/src/lbe-v2.ts index f93a0d4..aa32522 100644 --- a/src/lbe-v2.ts +++ b/src/lbe-v2.ts @@ -87,6 +87,13 @@ export type AddSellersOptions = { currentSlot: number; }; +export type CountingSellersOptions = { + treasuryUtxo: UTxO; + managerUtxo: UTxO; + sellerUtxos: UTxO[]; + currentSlot: number; +}; + const THREE_HOUR_IN_MS = 3 * 60 * 60 * 1000; export class LbeV2 { @@ -102,7 +109,7 @@ export class LbeV2 { } // MARK: CREATE EVENT - private validateCreateEvent(options: LbeV2CreateEventOptions): void { + validateCreateEvent(options: LbeV2CreateEventOptions): void { const { lbeV2Parameters, currentSlot, factoryUtxo, projectDetails } = options; const currentTime = this.lucid.utils.slotToUnixTime(currentSlot); @@ -1218,4 +1225,169 @@ export class LbeV2 { return lucidTx.complete(); } + + // MARK: COUNTING SELLER + validateCountingSeller(options: CountingSellersOptions): void { + const { treasuryUtxo, managerUtxo, sellerUtxos, currentSlot } = options; + const currentTime = this.lucid.utils.slotToUnixTime(currentSlot); + const config = LbeV2Constant.CONFIG[this.networkId]; + + const rawTreasuryDatum = treasuryUtxo.datum; + invariant(rawTreasuryDatum, "Treasury utxo must have inline datum"); + const treasuryDatum = LbeV2Types.TreasuryDatum.fromPlutusData( + this.networkId, + Data.from(rawTreasuryDatum) + ); + invariant( + config.treasuryAsset in treasuryUtxo.assets, + "Treasury utxo assets must have treasury asset" + ); + + const rawManagerDatum = managerUtxo.datum; + invariant(rawManagerDatum, "Treasury utxo must have inline datum"); + const managerDatum = LbeV2Types.ManagerDatum.fromPlutusData( + Data.from(rawManagerDatum) + ); + invariant( + config.managerAsset in managerUtxo.assets, + "Manager utxo assets must have manager asset" + ); + + invariant(addSellerCount > 0, "Must add at least one seller"); + invariant( + PoolV2.computeLPAssetName( + treasuryDatum.baseAsset, + treasuryDatum.raiseAsset + ) === + PoolV2.computeLPAssetName( + managerDatum.baseAsset, + managerDatum.raiseAsset + ), + "treasury, manager must have same Lbe ID" + ); + invariant( + currentTime > treasuryDatum.endTime, + "Must counting seller in encounter phase" + ); + } + + async countingSellers(options: CountingSellersOptions): Promise { + this.validateAddSeller(options); + const { + treasuryUtxo, + managerUtxo, + addSellerCount, + sellerOwner, + currentSlot, + } = options; + const currentTime = this.lucid.utils.slotToUnixTime(currentSlot); + const config = LbeV2Constant.CONFIG[this.networkId]; + + const rawTreasuryDatum = treasuryUtxo.datum; + invariant(rawTreasuryDatum, "Treasury utxo must have inline datum"); + const treasuryDatum = LbeV2Types.TreasuryDatum.fromPlutusData( + this.networkId, + Data.from(rawTreasuryDatum) + ); + + const rawManagerDatum = managerUtxo.datum; + invariant(rawManagerDatum, "Treasury utxo must have inline datum"); + const managerDatum = LbeV2Types.ManagerDatum.fromPlutusData( + Data.from(rawManagerDatum) + ); + + const lucidTx = this.lucid.newTx(); + + // READ FROM + const factoryRefs = await this.lucid.utxosByOutRef([ + LbeV2Constant.DEPLOYED_SCRIPTS[this.networkId].factory, + ]); + invariant( + factoryRefs.length === 1, + "cannot find deployed script for LbeV2 Factory" + ); + lucidTx.readFrom(factoryRefs); + + const managerRefs = await this.lucid.utxosByOutRef([ + LbeV2Constant.DEPLOYED_SCRIPTS[this.networkId].manager, + ]); + invariant( + managerRefs.length === 1, + "cannot find deployed script for LbeV2 Manager" + ); + lucidTx.readFrom(managerRefs); + + lucidTx.readFrom([treasuryUtxo]); + + // COLLECT FROM + lucidTx.collectFrom( + [managerUtxo], + Data.to( + LbeV2Types.ManagerRedeemer.toPlutusData( + LbeV2Types.ManagerRedeemer.ADD_SELLERS + ) + ) + ); + + // MINT + lucidTx.mintAssets( + { [config.sellerAsset]: BigInt(addSellerCount) }, + Data.to( + LbeV2Types.FactoryRedeemer.toPlutusData({ + type: LbeV2Types.FactoryRedeemerType.MINT_SELLER, + }) + ) + ); + + // PAY TO + const newManagerDatum: LbeV2Types.ManagerDatum = { + ...managerDatum, + sellerCount: managerDatum.sellerCount + BigInt(addSellerCount), + }; + lucidTx.payToContract( + config.managerAddress, + { + inline: Data.to(LbeV2Types.ManagerDatum.toPlutusData(newManagerDatum)), + }, + { ...managerUtxo.assets } + ); + for (let i = 0; i < addSellerCount; ++i) { + lucidTx.payToContract( + config.sellerAddress, + { + inline: Data.to( + LbeV2Types.SellerDatum.toPlutusData({ + factoryPolicyId: config.factoryHash, + owner: sellerOwner, + baseAsset: treasuryDatum.baseAsset, + raiseAsset: treasuryDatum.raiseAsset, + amount: 0n, + penaltyAmount: 0n, + }) + ), + }, + { + [config.sellerAsset]: 1n, + lovelace: LbeV2Constant.SELLER_MIN_ADA, + } + ); + } + + // VALID TIME RANGE + lucidTx + .validFrom(currentTime) + .validTo( + Math.min( + currentTime + THREE_HOUR_IN_MS, + Number(treasuryDatum.endTime) - 1000 + ) + ); + + // METADATA + lucidTx.attachMetadata(674, { + msg: [MetadataMessage.ADD_SELLERS], + }); + + return lucidTx.complete(); + } }