diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6570fb3..c099559 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,7 +19,7 @@ jobs: run_install: false - uses: actions/setup-node@v4 with: - node-version: 20.x + node-version: 20.17 cache: "pnpm" - name: Install dependencies run: pnpm install --frozen-lockfile diff --git a/.nvmrc b/.nvmrc index 85aee5a..5d41b5b 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -v20 \ No newline at end of file +v20.17 \ No newline at end of file diff --git a/docs/transaction.md b/docs/dex-transaction.md similarity index 79% rename from docs/transaction.md rename to docs/dex-transaction.md index df95b92..249b90e 100644 --- a/docs/transaction.md +++ b/docs/dex-transaction.md @@ -1,4 +1,4 @@ -# Minswap AMM V2 & Stableswap Classes Documentation +# Minswap DEX Classes documentation ## Overview @@ -9,6 +9,8 @@ This documentation provides details on how to interact with the **Stableswap** a - **Stableswap class**: Located in `src/stableswap.ts`. - **AMM V2 class**: Located in `src/dex-v2.ts`. - **Example file**: Demonstrates usage of both classes, located in `examples/example.ts`. +- **ExpiredOrderMonitor Class**: Located in `src/expired-order-monitor.ts`. +- **ExpiredOrderMonitor Example**: Located in `examples/expired-order-monitor-example.ts`. ### Utility Functions @@ -54,7 +56,10 @@ const blockfrostAdapter = new BlockfrostAdapter( const utxos = await lucid.utxosAt(address); const lpAsset = Asset.fromString(""); -const config = StableswapConstant.getConfigByLpAsset(lpAsset, NetworkId.TESTNET); +const config = StableswapConstant.getConfigByLpAsset( + lpAsset, + NetworkId.TESTNET +); const pool = await blockfrostAdapter.getStablePoolByLpAsset(lpAsset); @@ -92,7 +97,9 @@ const txComplete = await new Stableswap(lucid).createBulkOrdersTx({ ], }); -const signedTx = await txComplete.signWithPrivateKey("").complete(); +const signedTx = await txComplete + .signWithPrivateKey("") + .complete(); const txId = await signedTx.submit(); console.info(`Transaction submitted successfully: ${txId}`); ``` @@ -144,27 +151,30 @@ const acceptedAmountOut = Slippage.apply({ type: "down", }); -const txComplete = await new DexV2(lucid, blockfrostAdapter).createBulkOrdersTx({ - sender: address, - availableUtxos: utxos, - orderOptions: [ - { - type: OrderV2.StepType.SWAP_EXACT_IN, - amountIn: swapAmount, - assetIn: assetA, - direction: OrderV2.Direction.A_TO_B, - minimumAmountOut: acceptedAmountOut, - lpAsset: pool.lpAsset, - isLimitOrder: false, - killOnFailed: false, - }, - ], -}); +const txComplete = await new DexV2(lucid, blockfrostAdapter).createBulkOrdersTx( + { + sender: address, + availableUtxos: utxos, + orderOptions: [ + { + type: OrderV2.StepType.SWAP_EXACT_IN, + amountIn: swapAmount, + assetIn: assetA, + direction: OrderV2.Direction.A_TO_B, + minimumAmountOut: acceptedAmountOut, + lpAsset: pool.lpAsset, + isLimitOrder: false, + killOnFailed: false, + }, + ], + } +); -const signedTx = await txComplete.signWithPrivateKey("").complete(); +const signedTx = await txComplete + .signWithPrivateKey("") + .complete(); const txId = await signedTx.submit(); console.info(`Transaction submitted successfully: ${txId}`); - ``` ### 3. Create the DEX V2 Liquiditiy Pool @@ -204,19 +214,54 @@ const txComplete = await new DexV2(lucid, blockfrostAdapter).createPoolTx({ tradingFeeNumerator: 100n, }); -const signedTx = await txComplete.signWithPrivateKey("").complete(); +const signedTx = await txComplete + .signWithPrivateKey("") + .complete(); const txId = await signedTx.submit(); console.info(`Transaction submitted successfully: ${txId}`); ``` +### 4. Off-chain component to track and cancel the expired orders + +```ts +const network: Network = "Preprod"; +const blockfrostProjectId = ""; +const blockfrostUrl = "https://cardano-preprod.blockfrost.io/api/v0"; + +const address = ""; +const lucid = await getBackendLucidInstance( + network, + blockfrostProjectId, + blockfrostUrl, + address +); + +const blockfrostAdapter = new BlockfrostAdapter( + NetworkId.TESTNET, + new BlockFrostAPI({ + projectId: blockfrostProjectId, + network: "preprod", + }) +); + +const monitor = new ExpiredOrderMonitor({ + lucid, + blockfrostAdapter, + privateKey: "", +}); + +await monitor.start(); +``` + ## Additional Examples You can explore more examples in the [Examples](../examples/example.ts) folder to learn how to integrate the Stableswap and DexV2 classes in more complex scenarios. ## Conclusion + The Stableswap and AMM V2 classes offer powerful tools for interacting with Minswap’s decentralized exchange. They allow users to easily manage liquidity pools and make swaps, with built-in support for Minswap Batcher Fee discounts. By utilizing these classes, users can create efficient transactions and leverage the utility of $MIN to reduce costs. For more details, you can refer to the specific class files: - [Stableswap class](../src/stableswap.ts) -- [AMM V2 class](../src/dex-v2.ts) \ No newline at end of file +- [AMM V2 class](../src/dex-v2.ts) diff --git a/docs/lbe-v2/LBE Specification.pdf b/docs/lbe-v2/LBE Specification.pdf new file mode 100644 index 0000000..01d381b Binary files /dev/null and b/docs/lbe-v2/LBE Specification.pdf differ diff --git a/docs/lbe-v2/lbe-v2.md b/docs/lbe-v2/lbe-v2.md new file mode 100644 index 0000000..3f59cdf --- /dev/null +++ b/docs/lbe-v2/lbe-v2.md @@ -0,0 +1,294 @@ +# LBE V2 Documentation + +## Overview + +This documentation provides guidelines for communicating with and interacting with the LBE V2 protocol. It includes creating, editing, and deleting events, creating, editing, and deleting orders, how the worker operates. + +### Specification + +[LBE Specification](./LBE%20Specification.pdf) + +### Transaction Builder Function + +- **LBEV2 Class**: Located in `src/lbe-v2/lbe-v2.ts`. +- **User and project owner action Example**: Located in `example/example.ts`. +- **LBEV2Worker Class**: is a class that executes off-chain actions when an event ends. Located in `src/lbe-v2-worker/worker.ts`. +- **LBEV2Worker Example**: Located in `examples/lbe-v2-worker-example.ts`. + +## Example Usage + +### Create Event + +```ts +const network: Network = "Preprod"; +const blockfrostProjectId = ""; +const blockfrostUrl = "https://cardano-preprod.blockfrost.io/api/v0"; + +const address = + "addr_test1qqf2dhk96l2kq4xh2fkhwksv0h49vy9exw383eshppn863jereuqgh2zwxsedytve5gp9any9jwc5hz98sd47rwfv40stc26fr"; +const lucid = await getBackendLucidInstance( + network, + blockfrostProjectId, + blockfrostUrl, + address +); + +const blockfrostAdapter = new BlockfrostAdapter( + NetworkId.TESTNET, + new BlockFrostAPI({ + projectId: blockfrostProjectId, + network: "preprod", + }) +); + +const baseAsset: Asset = { + policyId: "d6aae2059baee188f74917493cf7637e679cd219bdfbbf4dcbeb1d0b", + tokenName: "fdfc61f25b3065a310ba3e352159125910b947b7aee704728318949933127cdc", +}; +const raiseAsset: Asset = { + policyId: "", + tokenName: "", +}; +const curSlot = lucid.currentSlot(); +const curDate = lucid.utils.slotToUnixTime(curSlot); +const lbeV2Parameters: LbeV2Types.LbeV2Parameters = { + baseAsset: baseAsset, + reserveBase: 100_000n, + raiseAsset: raiseAsset, + startTime: BigInt(curDate + ONE_HOUR_IN_MS), + endTime: BigInt(curDate + 2 * ONE_HOUR_IN_MS), + owner: address, + receiver: address, + poolAllocation: 100n, + minimumOrderRaise: undefined, + minimumRaise: 10_000_000n, + maximumRaise: 100_000_000n, + penaltyConfig: { + penaltyStartTime: BigInt(curDate + ONE_HOUR_IN_MS + 20 * ONE_MINUTE_IN_MS), + percent: 20n, + }, + revocable: true, + poolBaseFee: 30n, +}; +const factory = await blockfrostAdapter.getLbeV2Factory(baseAsset, raiseAsset); +invariant(factory !== null, "Can not find factory"); +const factoryUtxos = await lucid.utxosByOutRef([ + { outputIndex: factory.txIn.index, txHash: factory.txIn.txHash }, +]); +invariant(factoryUtxos.length !== 0, "Can not find factory utxo"); +const projectDetails = { + eventName: "TEST SDK", + description: "test lbe v2 in public sdk", + socialLinks: { + twitter: "https://x.com/MinswapDEX", + telegram: "https://t.me/MinswapMafia", + discord: "https://discord.gg/minswap", + website: "https://minswap.org/", + }, + tokenomics: [ + { + tag: "admin", + percentage: "70", + }, + { + tag: "LBE", + percentage: "30", + }, + ], +}; +const currentSlot = await blockfrostAdapter.currentSlot(); +const txComplete = await new LbeV2(lucid).createEvent({ + factoryUtxo: factoryUtxos[0], + lbeV2Parameters: lbeV2Parameters, + currentSlot: currentSlot, + sellerOwner: address, + sellerCount: 10, + projectDetails: projectDetails, +}); +const signedTx = await txComplete + .signWithPrivateKey("") + .complete(); + +const txId = await signedTx.submit(); +console.info(`Transaction submitted successfully: ${txId}`); +``` + +### Create Order + +```ts +const network: Network = "Preprod"; +const blockfrostProjectId = ""; +const blockfrostUrl = "https://cardano-preprod.blockfrost.io/api/v0"; + +const address = ""; + +const lucid = await getBackendLucidInstance( + network, + blockfrostProjectId, + blockfrostUrl, + address +); + +const blockfrostAdapter = new BlockfrostAdapter( + NetworkId.TESTNET, + new BlockFrostAPI({ + projectId: blockfrostProjectId, + network: "preprod", + }) +); + +const baseAsset: Asset = { + policyId: "d6aae2059baee188f74917493cf7637e679cd219bdfbbf4dcbeb1d0b", + tokenName: "fdfc61f25b3065a310ba3e352159125910b947b7aee704728318949933127cdc", +}; +const raiseAsset: Asset = { + policyId: "", + tokenName: "", +}; +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 seller = await blockfrostAdapter.getLbeV2SellerByLbeId(lbeId); +invariant(seller !== null, `Can not find seller by lbeId ${lbeId}`); +const sellerUtxos = await lucid.utxosByOutRef([ + { txHash: seller.txIn.txHash, outputIndex: seller.txIn.index }, +]); +invariant(sellerUtxos.length === 1, "Can not find seller Utxo"); + +const orders = await blockfrostAdapter.getLbeV2OrdersByLbeIdAndOwner( + lbeId, + address +); +const orderUtxos = + orders.length > 0 + ? await lucid.utxosByOutRef( + orders.map((o) => ({ + txHash: o.txIn.txHash, + outputIndex: o.txIn.index, + })) + ) + : []; + +invariant( + orderUtxos.length === orders.length, + "Can not find enough order Utxos" +); + +const currentSlot = await blockfrostAdapter.currentSlot(); +return new LbeV2(lucid).depositOrWithdrawOrder({ + currentSlot: currentSlot, + existingOrderUtxos: orderUtxos, + treasuryUtxo: treasuryUtxos[0], + sellerUtxo: sellerUtxos[0], + owner: address, + action: { type: "deposit", additionalAmount: 1_000_000n }, +}); + +const signedTx = await txComplete + .signWithPrivateKey("") + .complete(); + +const txId = await signedTx.submit(); +console.info(`Transaction submitted successfully: ${txId}`); +``` + +### Add seller(Increase Concurrency Performance) + +```ts +const network: Network = "Preprod"; +const blockfrostProjectId = ""; +const blockfrostUrl = "https://cardano-preprod.blockfrost.io/api/v0"; + +const address = + "addr_test1qqf2dhk96l2kq4xh2fkhwksv0h49vy9exw383eshppn863jereuqgh2zwxsedytve5gp9any9jwc5hz98sd47rwfv40stc26fr"; +const lucid = await getBackendLucidInstance( + network, + blockfrostProjectId, + blockfrostUrl, + address +); + +const blockfrostAdapter = new BlockfrostAdapter( + NetworkId.TESTNET, + new BlockFrostAPI({ + projectId: blockfrostProjectId, + network: "preprod", + }) +); + +const baseAsset: Asset = { + policyId: "d6aae2059baee188f74917493cf7637e679cd219bdfbbf4dcbeb1d0b", + tokenName: "fdfc61f25b3065a310ba3e352159125910b947b7aee704728318949933127cdc", +}; +const raiseAsset: Asset = { + policyId: "", + tokenName: "", +}; +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"); + +const txComplete = await new LbeV2(lucid).addSellers({ + treasuryUtxo: treasuryUtxos[0], + managerUtxo: managerUtxos[0], + addSellerCount: 2, + sellerOwner: address, + currentSlot: await blockfrostAdapter.currentSlot(), +}); +const signedTx = await txComplete + .signWithPrivateKey("") + .complete(); + +const txId = await signedTx.submit(); +console.info(`Transaction submitted successfully: ${txId}`); +``` + +### Run Worker + +```ts +const network: Network = "Preprod"; +const blockfrostProjectId = ""; +const blockfrostUrl = "https://cardano-preprod.blockfrost.io/api/v0"; + +const address = ""; +const lucid = await getBackendLucidInstance( + network, + blockfrostProjectId, + blockfrostUrl, + address +); + +const blockfrostAdapter = new BlockfrostAdapter( + NetworkId.TESTNET, + new BlockFrostAPI({ + projectId: blockfrostProjectId, + network: "preprod", + }) +); + +const worker = new LbeV2Worker({ + networkEnv: NetworkEnvironment.TESTNET_PREPROD, + networkId: NetworkId.TESTNET, + lucid, + blockfrostAdapter, + privateKey: "", +}); + +await worker.start(); +``` diff --git a/examples/example.ts b/examples/example.ts index 7f915e3..e1d4f5c 100644 --- a/examples/example.ts +++ b/examples/example.ts @@ -1,6 +1,4 @@ import { BlockFrostAPI } from "@blockfrost/blockfrost-js"; -import invariant from "@minswap/tiny-invariant"; -import BigNumber from "bignumber.js"; import { Address, Blockfrost, @@ -11,7 +9,9 @@ import { OutRef, TxComplete, UTxO, -} from "lucid-cardano"; +} from "@minswap/lucid-cardano"; +import invariant from "@minswap/tiny-invariant"; +import BigNumber from "bignumber.js"; import { ADA, @@ -28,11 +28,15 @@ import { NetworkId, OrderV2, PoolV1, + PoolV2, StableOrder, StableswapCalculation, StableswapConstant, } from "../src"; +import { LbeV2 } from "../src/lbe-v2/lbe-v2"; import { Stableswap } from "../src/stableswap"; +import { LbeV2Types } from "../src/types/lbe-v2"; +import { getBackendLucidInstance } from "../src/utils/lucid"; import { Slippage } from "../src/utils/slippage.internal"; const MIN: Asset = { @@ -46,7 +50,7 @@ async function main(): Promise { const blockfrostUrl = "https://cardano-preprod.blockfrost.io/api/v0"; const address = - "addr_test1vrd9v47japxwp8540vsrh4grz4u9urfpfawwy7sf6r0vxqgm7wdxh"; + "addr_test1qqf2dhk96l2kq4xh2fkhwksv0h49vy9exw383eshppn863jereuqgh2zwxsedytve5gp9any9jwc5hz98sd47rwfv40stc26fr"; const lucid = await getBackendLucidInstance( network, blockfrostProjectId, @@ -62,17 +66,15 @@ async function main(): Promise { }) ); - const utxos = await lucid.utxosAt(address); - - const txComplete = await _stopV2TxExample( + const txComplete = await _lbeV2DepositOrderExample( lucid, - blockfrostAdapter, address, - utxos + blockfrostAdapter ); const signedTx = await txComplete .signWithPrivateKey("") .complete(); + const txId = await signedTx.submit(); console.info(`Transaction submitted successfully: ${txId}`); } @@ -102,6 +104,7 @@ async function getPoolById( }; } +// MARK: DEX V1 async function _depositTxExample( network: Network, lucid: Lucid, @@ -362,6 +365,7 @@ async function _cancelTxExample( }); } +// MARK: DEX V2 async function _createPoolV2( lucid: Lucid, blockFrostAdapter: BlockfrostAdapter @@ -848,6 +852,7 @@ async function _cancelV2TxExample( }); } +// MARK: STABLESWAP async function _swapStableExample( lucid: Lucid, blockfrostAdapter: BlockfrostAdapter, @@ -1140,6 +1145,373 @@ async function _cancelStableExample(lucid: Lucid): Promise { }); } +// MARK: LBE V2 +const ONE_MINUTE_IN_MS = 1000 * 60; +const ONE_HOUR_IN_MS = 1000 * 60 * 60; +const _ONE_DAY_IN_MS = 1000 * 60 * 60 * 24; + +// Example Tx: e1f42baa7b685acf083d5a3ffe4eefd1f53f4682226f0f39de56310de108239b +async function _createLbeV2EventExample( + lucid: Lucid, + address: Address, + blockfrostAdapter: BlockfrostAdapter +): Promise { + const baseAsset = Asset.fromString( + "d6aae2059baee188f74917493cf7637e679cd219bdfbbf4dcbeb1d0bfdfc61f25b3065a310ba3e352159125910b947b7aee704728318949933127cdc" + ); + const curSlot = lucid.currentSlot(); + const curDate = lucid.utils.slotToUnixTime(curSlot); + const lbeV2Parameters: LbeV2Types.LbeV2Parameters = { + baseAsset: baseAsset, + reserveBase: 100_000n, + raiseAsset: ADA, + startTime: BigInt(curDate + ONE_HOUR_IN_MS), + endTime: BigInt(curDate + 2 * ONE_HOUR_IN_MS), + owner: address, + receiver: address, + poolAllocation: 100n, + minimumOrderRaise: undefined, + minimumRaise: 10_000_000n, + maximumRaise: 100_000_000n, + penaltyConfig: { + penaltyStartTime: BigInt( + curDate + ONE_HOUR_IN_MS + 20 * ONE_MINUTE_IN_MS + ), + percent: 20n, + }, + revocable: true, + poolBaseFee: 30n, + }; + const factory = await blockfrostAdapter.getLbeV2Factory( + lbeV2Parameters.baseAsset, + lbeV2Parameters.raiseAsset + ); + invariant(factory !== null, "Can not find factory"); + const factoryUtxos = await lucid.utxosByOutRef([ + { outputIndex: factory.txIn.index, txHash: factory.txIn.txHash }, + ]); + invariant(factoryUtxos.length !== 0, "Can not find factory utxo"); + const projectDetails = { + eventName: "TEST SDK", + description: "test lbe v2 in public sdk", + socialLinks: { + twitter: "https://x.com/MinswapDEX", + telegram: "https://t.me/MinswapMafia", + discord: "https://discord.gg/minswap", + website: "https://minswap.org/", + }, + tokenomics: [ + { + tag: "admin", + percentage: "70", + }, + { + tag: "LBE", + percentage: "30", + }, + ], + }; + const currentSlot = await blockfrostAdapter.currentSlot(); + return new LbeV2(lucid).createEvent({ + factoryUtxo: factoryUtxos[0], + lbeV2Parameters: lbeV2Parameters, + currentSlot: currentSlot, + sellerOwner: address, + sellerCount: 10, + projectDetails: projectDetails, + }); +} + +// Example Tx: 40116c275da234ec6b7c88ff38dfa45ad18c7c1388c2d3f8f6e43dfef90b7e70 +async function _updateLbeV2EventExample( + lucid: Lucid, + address: Address, + blockfrostAdapter: BlockfrostAdapter +): Promise { + const baseAsset = Asset.fromString( + "d6aae2059baee188f74917493cf7637e679cd219bdfbbf4dcbeb1d0ba547d1ae595c49041570991a1c33729106e635f20643b99e3ddb1e77dc439586" + ); + const curSlot = lucid.currentSlot(); + const curDate = lucid.utils.slotToUnixTime(curSlot); + const lbeV2Parameters: LbeV2Types.LbeV2Parameters = { + baseAsset: baseAsset, + reserveBase: 100_000n, + raiseAsset: ADA, + startTime: BigInt(curDate + _ONE_DAY_IN_MS * 20), + endTime: BigInt(curDate + _ONE_DAY_IN_MS * 20 + 2 * ONE_HOUR_IN_MS), + owner: address, + receiver: address, + poolAllocation: 100n, + minimumOrderRaise: undefined, + minimumRaise: 10_000_000n, + maximumRaise: 100_000_000n, + penaltyConfig: { + penaltyStartTime: BigInt( + curDate + _ONE_DAY_IN_MS * 20 + 10 * ONE_MINUTE_IN_MS + ), + percent: 20n, + }, + revocable: true, + poolBaseFee: 30n, + }; + const projectDetails = { + eventName: "TEST SDK hiiiiiiii", + description: "test lbe v2 in public sdk", + socialLinks: { + twitter: "https://x.com/MinswapDEX", + telegram: "https://t.me/MinswapMafia", + discord: "https://discord.gg/minswap", + website: "https://app.minswap.org/", + }, + tokenomics: [ + { + tag: "admin", + percentage: "70", + }, + { + tag: "LBE", + percentage: "30", + }, + ], + }; + const currentSlot = await blockfrostAdapter.currentSlot(); + const lbeId = PoolV2.computeLPAssetName(baseAsset, ADA); + const treasury = await blockfrostAdapter.getLbeV2TreasuryByLbeId(lbeId); + invariant(treasury !== null, "Event is not created"); + const treasuryUtxos = await lucid.utxosByOutRef([ + { outputIndex: treasury.txIn.index, txHash: treasury.txIn.txHash }, + ]); + invariant(treasuryUtxos.length !== 0, "Can not find factory utxo"); + return new LbeV2(lucid).updateEvent({ + owner: await lucid.wallet.address(), + treasuryUtxo: treasuryUtxos[0], + lbeV2Parameters: lbeV2Parameters, + currentSlot: currentSlot, + projectDetails: projectDetails, + }); +} + +// 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, + address: Address, + blockfrostAdapter: BlockfrostAdapter +): Promise { + const baseAsset = Asset.fromString( + "e4214b7cce62ac6fbba385d164df48e157eae5863521b4b67ca71d865190718981e4e7fab3eb80963f14148714d7a7847652d4017d0fb744db075027" + ); + 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"); + + return new LbeV2(lucid).cancelEvent({ + treasuryUtxo: treasuryUtxos[0], + cancelData: { reason: LbeV2Types.CancelReason.BY_OWNER, owner: address }, + currentSlot: await blockfrostAdapter.currentSlot(), + }); +} + +// Example Tx: 7af5ea80b6a4a587e2c6cfce383367829f0cb68c90b65656c8198a72afc3f419 +async function _lbeV2DepositOrderExample( + 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 seller = await blockfrostAdapter.getLbeV2SellerByLbeId(lbeId); + invariant(seller !== null, `Can not find seller by lbeId ${lbeId}`); + const sellerUtxos = await lucid.utxosByOutRef([ + { txHash: seller.txIn.txHash, outputIndex: seller.txIn.index }, + ]); + invariant(sellerUtxos.length === 1, "Can not find seller Utxo"); + + const orders = await blockfrostAdapter.getLbeV2OrdersByLbeIdAndOwner( + lbeId, + address + ); + const orderUtxos = + orders.length > 0 + ? await lucid.utxosByOutRef( + orders.map((o) => ({ + txHash: o.txIn.txHash, + outputIndex: o.txIn.index, + })) + ) + : []; + + invariant( + orderUtxos.length === orders.length, + "Can not find enough order Utxos" + ); + + const currentSlot = await blockfrostAdapter.currentSlot(); + return new LbeV2(lucid).depositOrWithdrawOrder({ + currentSlot: currentSlot, + existingOrderUtxos: orderUtxos, + treasuryUtxo: treasuryUtxos[0], + sellerUtxo: sellerUtxos[0], + owner: address, + action: { type: "deposit", additionalAmount: 1_000_000n }, + }); +} + +// Example Tx: 3388b9ce7f2175576b12ac48eacfb78da24b2319ab0595b5cc6bf9531e781eef +async function _lbeV2WithdrawOrderExample( + 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 seller = await blockfrostAdapter.getLbeV2SellerByLbeId(lbeId); + invariant(seller !== null, `Can not find seller by lbeId ${lbeId}`); + const sellerUtxos = await lucid.utxosByOutRef([ + { txHash: seller.txIn.txHash, outputIndex: seller.txIn.index }, + ]); + invariant(sellerUtxos.length === 1, "Can not find seller Utxo"); + + const orders = await blockfrostAdapter.getLbeV2OrdersByLbeIdAndOwner( + lbeId, + address + ); + const orderUtxos = + orders.length > 0 + ? await lucid.utxosByOutRef( + orders.map((o) => ({ + txHash: o.txIn.txHash, + outputIndex: o.txIn.index, + })) + ) + : []; + + invariant( + orderUtxos.length === orders.length, + "Can not find enough order Utxos" + ); + + const currentSlot = await blockfrostAdapter.currentSlot(); + return new LbeV2(lucid).depositOrWithdrawOrder({ + currentSlot: currentSlot, + existingOrderUtxos: orderUtxos, + treasuryUtxo: treasuryUtxos[0], + sellerUtxo: sellerUtxos[0], + owner: address, + action: { type: "withdraw", withdrawalAmount: 1_000_000n }, + }); +} + +// Example Tx: 9667528ebfe0c51aad3c6ef6b1dc7e1660c55c8d712d30eb81a5520dd4aca780 +async function _lbeV2CloseEventExample( + lucid: Lucid, + address: Address, + blockfrostAdapter: BlockfrostAdapter +): Promise { + const baseAsset = Asset.fromString( + "d6aae2059baee188f74917493cf7637e679cd219bdfbbf4dcbeb1d0bfdfc61f25b3065a310ba3e352159125910b947b7aee704728318949933127cdc" + ); + 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 headAndTailFactory = + await blockfrostAdapter.getLbeV2HeadAndTailFactory(lbeId); + invariant( + headAndTailFactory, + `Can not find head and tail factory by lbeId ${lbeId}` + ); + const { head: headFactory, tail: tailFactory } = headAndTailFactory; + + const treasuryUtxos = await lucid.utxosByOutRef([ + { txHash: treasury.txIn.txHash, outputIndex: treasury.txIn.index }, + ]); + invariant(treasuryUtxos.length !== 0, "Can not find treasury Utxo"); + + const headFactoryUtxos = await lucid.utxosByOutRef([ + { txHash: headFactory.txIn.txHash, outputIndex: headFactory.txIn.index }, + ]); + + invariant(headFactoryUtxos.length !== 0, "Can not find head factory Utxo"); + + const tailFactoryUtxos = await lucid.utxosByOutRef([ + { txHash: tailFactory.txIn.txHash, outputIndex: tailFactory.txIn.index }, + ]); + invariant(tailFactoryUtxos.length !== 0, "Can not find tail factory Utxo"); + const currentSlot = await blockfrostAdapter.currentSlot(); + + return new LbeV2(lucid).closeEventTx({ + treasuryUtxo: treasuryUtxos[0], + headFactoryUtxo: headFactoryUtxos[0], + tailFactoryUtxo: tailFactoryUtxos[0], + currentSlot: currentSlot, + owner: address, + }); +} + /** * Initialize Lucid Instance for Browser Environment * @param network Network you're working on @@ -1162,28 +1534,6 @@ async function _getBrowserLucidInstance( return lucid; } -/** - * Initialize Lucid Instance for Backend Environment - * @param network Network you're working on - * @param projectId Blockfrost API KEY - * @param blockfrostUrl Blockfrost URL - * @param address Your own address - * @returns - */ -async function getBackendLucidInstance( - network: Network, - projectId: string, - blockfrostUrl: string, - address: Address -): Promise { - const provider = new Blockfrost(blockfrostUrl, projectId); - const lucid = await Lucid.new(provider, network); - lucid.selectWalletFrom({ - address: address, - }); - return lucid; -} - function calculateGcd(a: bigint, b: bigint): bigint { if (!b) { return a; diff --git a/examples/expired-order-monitor-example.ts b/examples/expired-order-monitor-example.ts new file mode 100644 index 0000000..3b85155 --- /dev/null +++ b/examples/expired-order-monitor-example.ts @@ -0,0 +1,39 @@ +import { BlockFrostAPI } from "@blockfrost/blockfrost-js"; +import { Network } from "@minswap/lucid-cardano"; + +import { BlockfrostAdapter, NetworkId } from "../src"; +import { ExpiredOrderMonitor } from "../src/expired-order-monitor"; +import { getBackendLucidInstance } from "../src/utils/lucid"; + +async function main(): Promise { + const network: Network = "Preprod"; + const blockfrostProjectId = ""; + const blockfrostUrl = "https://cardano-preprod.blockfrost.io/api/v0"; + + const address = + "addr_test1qqf2dhk96l2kq4xh2fkhwksv0h49vy9exw383eshppn863jereuqgh2zwxsedytve5gp9any9jwc5hz98sd47rwfv40stc26fr"; + const lucid = await getBackendLucidInstance( + network, + blockfrostProjectId, + blockfrostUrl, + address + ); + + const blockfrostAdapter = new BlockfrostAdapter( + NetworkId.TESTNET, + new BlockFrostAPI({ + projectId: blockfrostProjectId, + network: "preprod", + }) + ); + + const monitor = new ExpiredOrderMonitor({ + lucid, + blockfrostAdapter, + privateKey: "", + }); + + await monitor.start(); +} + +void main(); diff --git a/examples/lbe-v2-worker-example.ts b/examples/lbe-v2-worker-example.ts new file mode 100644 index 0000000..5681f17 --- /dev/null +++ b/examples/lbe-v2-worker-example.ts @@ -0,0 +1,42 @@ +import { BlockFrostAPI } from "@blockfrost/blockfrost-js"; +import { Network } from "@minswap/lucid-cardano"; + +import { BlockfrostAdapter, NetworkId } from "../src"; +import { LbeV2Worker } from "../src/lbe-v2-worker/worker"; +import { NetworkEnvironment } from "../src/types/network"; +import { getBackendLucidInstance } from "../src/utils/lucid"; + +async function main(): Promise { + const network: Network = "Preprod"; + const blockfrostProjectId = ""; + const blockfrostUrl = "https://cardano-preprod.blockfrost.io/api/v0"; + + const address = + "addr_test1vrd9v47japxwp8540vsrh4grz4u9urfpfawwy7sf6r0vxqgm7wdxh"; + const lucid = await getBackendLucidInstance( + network, + blockfrostProjectId, + blockfrostUrl, + address + ); + + const blockfrostAdapter = new BlockfrostAdapter( + NetworkId.TESTNET, + new BlockFrostAPI({ + projectId: blockfrostProjectId, + network: "preprod", + }) + ); + + const worker = new LbeV2Worker({ + networkEnv: NetworkEnvironment.TESTNET_PREPROD, + networkId: NetworkId.TESTNET, + lucid, + blockfrostAdapter, + privateKey: "", + }); + + await worker.start(); +} + +void main(); diff --git a/package.json b/package.json index 6ed1fed..3384f3a 100644 --- a/package.json +++ b/package.json @@ -22,8 +22,8 @@ "lint": "eslint src", "format": "prettier --write **/*.ts && eslint src --fix", "check-format": "prettier --check **/*.ts && eslint src", - "exec": "ts-node --esm --experimental-specifier-resolution=node", - "example": "ts-node --transpile-only --esm --experimental-specifier-resolution=node examples/example.ts", + "exec": "tsx", + "example": "tsx examples/example.ts", "prisma:dbpull": "prisma db pull", "prisma:generate": "prisma generate", "postinstall": "prisma generate", @@ -51,12 +51,12 @@ "@blockfrost/blockfrost-js": "^5.5.0", "@cardano-ogmios/client": "^6.5.0", "@cardano-ogmios/schema": "^6.5.0", + "@minswap/lucid-cardano": "0.10.10-minswap.4", "@minswap/tiny-invariant": "^1.2.0", "big.js": "^6.2.1", "bignumber.js": "^9.1.2", "exponential-backoff": "^3.1.1", "ioredis": "^5.4.1", - "lucid-cardano": "0.10.10", "remeda": "^2.12.1", "sha3": "^2.1.4" }, @@ -85,6 +85,7 @@ "rollup-plugin-esbuild": "^6.1.1", "ts-jest": "^29.2.5", "ts-node": "^10.9.2", + "tsx": "^4.19.2", "typescript": "^5.5.4", "typescript-eslint": "^8.4.0" }, @@ -95,4 +96,4 @@ "prisma": { "schema": "./src/syncer/postgres/prisma/schema.prisma" } -} \ No newline at end of file +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 630badc..e2306cf 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -10,13 +10,16 @@ importers: dependencies: '@blockfrost/blockfrost-js': specifier: ^5.5.0 - version: 5.5.0 + version: 5.7.0 '@cardano-ogmios/client': specifier: ^6.5.0 - version: 6.8.0 + version: 6.9.0 '@cardano-ogmios/schema': specifier: ^6.5.0 - version: 6.8.0 + version: 6.9.0 + '@minswap/lucid-cardano': + specifier: 0.10.10-minswap.4 + version: 0.10.10-minswap.4 '@minswap/tiny-invariant': specifier: ^1.2.0 version: 1.2.0 @@ -32,12 +35,9 @@ importers: ioredis: specifier: ^5.4.1 version: 5.4.1 - lucid-cardano: - specifier: 0.10.10 - version: 0.10.10 remeda: specifier: ^2.12.1 - version: 2.14.0 + version: 2.17.3 sha3: specifier: ^2.1.4 version: 2.1.4 @@ -48,16 +48,16 @@ importers: devDependencies: '@eslint/compat': specifier: ^1.1.1 - version: 1.1.1 + version: 1.2.3(eslint@9.15.0) '@eslint/js': specifier: ^9.9.1 - version: 9.11.0 + version: 9.15.0 '@jest/globals': specifier: ^29.7.0 version: 29.7.0 '@prisma/client': specifier: ^5.19.1 - version: 5.19.1(prisma@5.19.1) + version: 5.22.0(prisma@5.22.0) '@types/big.js': specifier: ^6.2.2 version: 6.2.2 @@ -66,31 +66,31 @@ importers: version: 8.42.3 '@types/jest': specifier: ^29.5.12 - version: 29.5.13 + version: 29.5.14 '@types/json-bigint': specifier: ^1.0.4 version: 1.0.4 '@types/node': specifier: ^20.9.2 - version: 20.16.6 + version: 20.17.7 esbuild: specifier: ^0.23.1 version: 0.23.1 eslint: specifier: ^9.9.1 - version: 9.11.0 + version: 9.15.0 eslint-plugin-simple-import-sort: specifier: ^12.1.1 - version: 12.1.1(eslint@9.11.0) + version: 12.1.1(eslint@9.15.0) eslint-plugin-unicorn: specifier: ^55.0.0 - version: 55.0.0(eslint@9.11.0) + version: 55.0.0(eslint@9.15.0) eslint-plugin-unused-imports: specifier: ^4.1.3 - version: 4.1.4(@typescript-eslint/eslint-plugin@8.6.0(@typescript-eslint/parser@8.6.0(eslint@9.11.0)(typescript@5.6.2))(eslint@9.11.0)(typescript@5.6.2))(eslint@9.11.0) + version: 4.1.4(@typescript-eslint/eslint-plugin@8.15.0(@typescript-eslint/parser@8.15.0(eslint@9.15.0)(typescript@5.7.2))(eslint@9.15.0)(typescript@5.7.2))(eslint@9.15.0) jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@20.16.6)(ts-node@10.9.2(@types/node@20.16.6)(typescript@5.6.2)) + version: 29.7.0(@types/node@20.17.7)(ts-node@10.9.2(@types/node@20.17.7)(typescript@5.7.2)) json-bigint: specifier: ^1.0.0 version: 1.0.0 @@ -99,31 +99,34 @@ importers: version: 3.3.3 prisma: specifier: ^5.19.1 - version: 5.19.1 + version: 5.22.0 rimraf: specifier: ^6.0.1 version: 6.0.1 rollup: specifier: ^4.21.2 - version: 4.22.4 + version: 4.27.4 rollup-plugin-dts: specifier: ^6.1.1 - version: 6.1.1(rollup@4.22.4)(typescript@5.6.2) + version: 6.1.1(rollup@4.27.4)(typescript@5.7.2) rollup-plugin-esbuild: specifier: ^6.1.1 - version: 6.1.1(esbuild@0.23.1)(rollup@4.22.4) + version: 6.1.1(esbuild@0.23.1)(rollup@4.27.4) ts-jest: specifier: ^29.2.5 - version: 29.2.5(@babel/core@7.25.2)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.25.2))(esbuild@0.23.1)(jest@29.7.0(@types/node@20.16.6)(ts-node@10.9.2(@types/node@20.16.6)(typescript@5.6.2)))(typescript@5.6.2) + version: 29.2.5(@babel/core@7.26.0)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.26.0))(esbuild@0.23.1)(jest@29.7.0(@types/node@20.17.7)(ts-node@10.9.2(@types/node@20.17.7)(typescript@5.7.2)))(typescript@5.7.2) ts-node: specifier: ^10.9.2 - version: 10.9.2(@types/node@20.16.6)(typescript@5.6.2) + version: 10.9.2(@types/node@20.17.7)(typescript@5.7.2) + tsx: + specifier: ^4.19.2 + version: 4.19.2 typescript: specifier: ^5.5.4 - version: 5.6.2 + version: 5.7.2 typescript-eslint: specifier: ^8.4.0 - version: 8.6.0(eslint@9.11.0)(typescript@5.6.2) + version: 8.15.0(eslint@9.15.0)(typescript@5.7.2) packages: @@ -131,66 +134,58 @@ packages: resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} engines: {node: '>=6.0.0'} - '@babel/code-frame@7.24.7': - resolution: {integrity: sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==} + '@babel/code-frame@7.26.2': + resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==} engines: {node: '>=6.9.0'} - '@babel/compat-data@7.25.4': - resolution: {integrity: sha512-+LGRog6RAsCJrrrg/IO6LGmpphNe5DiK30dGjCoxxeGv49B10/3XYGxPsAwrDlMFcFEvdAUavDT8r9k/hSyQqQ==} + '@babel/compat-data@7.26.2': + resolution: {integrity: sha512-Z0WgzSEa+aUcdiJuCIqgujCshpMWgUpgOxXotrYPSA53hA3qopNaqcJpyr0hVb1FeWdnqFA35/fUtXgBK8srQg==} engines: {node: '>=6.9.0'} - '@babel/core@7.25.2': - resolution: {integrity: sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA==} + '@babel/core@7.26.0': + resolution: {integrity: sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==} engines: {node: '>=6.9.0'} - '@babel/generator@7.25.6': - resolution: {integrity: sha512-VPC82gr1seXOpkjAAKoLhP50vx4vGNlF4msF64dSFq1P8RfB+QAuJWGHPXXPc8QyfVWwwB/TNNU4+ayZmHNbZw==} + '@babel/generator@7.26.2': + resolution: {integrity: sha512-zevQbhbau95nkoxSq3f/DC/SC+EEOUZd3DYqfSkMhY2/wfSeaHV1Ew4vk8e+x8lja31IbyuUa2uQ3JONqKbysw==} engines: {node: '>=6.9.0'} - '@babel/helper-compilation-targets@7.25.2': - resolution: {integrity: sha512-U2U5LsSaZ7TAt3cfaymQ8WHh0pxvdHoEk6HVpaexxixjyEquMh0L0YNJNM6CTGKMXV1iksi0iZkGw4AcFkPaaw==} + '@babel/helper-compilation-targets@7.25.9': + resolution: {integrity: sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ==} engines: {node: '>=6.9.0'} - '@babel/helper-module-imports@7.24.7': - resolution: {integrity: sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==} + '@babel/helper-module-imports@7.25.9': + resolution: {integrity: sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==} engines: {node: '>=6.9.0'} - '@babel/helper-module-transforms@7.25.2': - resolution: {integrity: sha512-BjyRAbix6j/wv83ftcVJmBt72QtHI56C7JXZoG2xATiLpmoC7dpd8WnkikExHDVPpi/3qCmO6WY1EaXOluiecQ==} + '@babel/helper-module-transforms@7.26.0': + resolution: {integrity: sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/helper-plugin-utils@7.24.8': - resolution: {integrity: sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==} + '@babel/helper-plugin-utils@7.25.9': + resolution: {integrity: sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw==} engines: {node: '>=6.9.0'} - '@babel/helper-simple-access@7.24.7': - resolution: {integrity: sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==} + '@babel/helper-string-parser@7.25.9': + resolution: {integrity: sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==} engines: {node: '>=6.9.0'} - '@babel/helper-string-parser@7.24.8': - resolution: {integrity: sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==} + '@babel/helper-validator-identifier@7.25.9': + resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==} engines: {node: '>=6.9.0'} - '@babel/helper-validator-identifier@7.24.7': - resolution: {integrity: sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==} + '@babel/helper-validator-option@7.25.9': + resolution: {integrity: sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==} engines: {node: '>=6.9.0'} - '@babel/helper-validator-option@7.24.8': - resolution: {integrity: sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==} + '@babel/helpers@7.26.0': + resolution: {integrity: sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==} engines: {node: '>=6.9.0'} - '@babel/helpers@7.25.6': - resolution: {integrity: sha512-Xg0tn4HcfTijTwfDwYlvVCl43V6h4KyVVX2aEm4qdO/PC6L2YvzLHFdmxhoeSA3eslcE6+ZVXHgWwopXYLNq4Q==} - engines: {node: '>=6.9.0'} - - '@babel/highlight@7.24.7': - resolution: {integrity: sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==} - engines: {node: '>=6.9.0'} - - '@babel/parser@7.25.6': - resolution: {integrity: sha512-trGdfBdbD0l1ZPmcJ83eNxB9rbEax4ALFTF7fN386TMYbeCQbyme5cOEXQhbGXKebwGaB/J52w1mrklMcbgy6Q==} + '@babel/parser@7.26.2': + resolution: {integrity: sha512-DWMCZH9WA4Maitz2q21SRKHo9QXZxkDsbNZoVD62gusNtNBBqDg9i7uOhASfTfIGNzW+O+r7+jAlM8dwphcJKQ==} engines: {node: '>=6.0.0'} hasBin: true @@ -215,8 +210,8 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-syntax-import-attributes@7.25.6': - resolution: {integrity: sha512-sXaDXaJN9SNLymBdlWFA+bjzBhFD617ZaFiY13dGt7TVslVvVgA6fkZOP7Ki3IGElC45lwHdOTrCtKZGVAWeLQ==} + '@babel/plugin-syntax-import-attributes@7.26.0': + resolution: {integrity: sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -231,8 +226,8 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-syntax-jsx@7.24.7': - resolution: {integrity: sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ==} + '@babel/plugin-syntax-jsx@7.25.9': + resolution: {integrity: sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -279,40 +274,41 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-syntax-typescript@7.25.4': - resolution: {integrity: sha512-uMOCoHVU52BsSWxPOMVv5qKRdeSlPuImUCB2dlPuBSU+W2/ROE7/Zg8F2Kepbk+8yBa68LlRKxO+xgEVWorsDg==} + '@babel/plugin-syntax-typescript@7.25.9': + resolution: {integrity: sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/template@7.25.0': - resolution: {integrity: sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q==} + '@babel/template@7.25.9': + resolution: {integrity: sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==} engines: {node: '>=6.9.0'} - '@babel/traverse@7.25.6': - resolution: {integrity: sha512-9Vrcx5ZW6UwK5tvqsj0nGpp/XzqthkT0dqIc9g1AdtygFToNtTF67XzYS//dm+SAK9cp3B9R4ZO/46p63SCjlQ==} + '@babel/traverse@7.25.9': + resolution: {integrity: sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==} engines: {node: '>=6.9.0'} - '@babel/types@7.25.6': - resolution: {integrity: sha512-/l42B1qxpG6RdfYf343Uw1vmDjeNhneUXtzhojE7pDgfpEypmRhI6j1kr17XCVv4Cgl9HdAiQY2x0GwKm7rWCw==} + '@babel/types@7.26.0': + resolution: {integrity: sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==} engines: {node: '>=6.9.0'} '@bcoe/v8-coverage@0.2.3': resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} - '@blockfrost/blockfrost-js@5.5.0': - resolution: {integrity: sha512-9UZIo6jRDSkRJt1r9sU2YPlz9MC3Ndh/5nCxS04H9B2MIak/jtPoJ3jTvn5dED06P8lPSKPn0QYPsIiJQ+8Kew==} + '@blockfrost/blockfrost-js@5.7.0': + resolution: {integrity: sha512-Rzw+Ya+LlKJNv9k5g7xW0uM33Xf6Lt3MXANtuwtm7+R9xuMFc7iKocwHSgrGUTTZ1EKou4n4Znai18MdvqG2bw==} engines: {node: '>=16'} - '@blockfrost/openapi@0.1.60': - resolution: {integrity: sha512-Q4hebu5NkWBi4TEn3kKNqExCDk/YYel10QfLCBbY+39pr0/RUC/AzMCq4bwAkO6I168LOnl8A3WWjJt8+iwjaQ==} + '@blockfrost/openapi@0.1.70-beta.0': + resolution: {integrity: sha512-js+ZpOWJHRHE+C1bVTDRen/MKVuaA8Bygjlil8O55bN3MzWfwQ0jzzZCYOAHhkbgEwE+j6ziCbP2+1xwFmtR+Q==} + engines: {node: '>=20'} - '@cardano-ogmios/client@6.8.0': - resolution: {integrity: sha512-12DmFZKXR4F+nn2U2vTNXka2zal/l20XfU3UimLTT9HPD0NTrNKxBE3rzmKIsDTB40EvyB5lPLc6xyO3ODffQA==} + '@cardano-ogmios/client@6.9.0': + resolution: {integrity: sha512-IsoUVsaMXiYyhWrdVKYOA5PDlX0EZ2gaq4lfk4JelRw6mcWVxemUrMaU2ndvugO9LQ3SCM1nESPgMIU0xe5FWw==} engines: {node: '>=14'} - '@cardano-ogmios/schema@6.8.0': - resolution: {integrity: sha512-U5uyO1nNa/rNMArtr8c44teeXJRqVdU62/KVzldrtfqFEoK4Oy6B0GcDcwREGdWlwtnyMkGvpu04+w/mWs0C5g==} + '@cardano-ogmios/schema@6.9.0': + resolution: {integrity: sha512-e7QVLF+dQMIv9p+p5CWQjMfBmkERYRa2wK2AjyehQZCJnecZ0gvTbRqewdX5VW4mVXf6KUfFyphsxWK46Pg6LA==} engines: {node: '>=14'} '@cardanosolutions/json-bigint@1.0.1': @@ -472,46 +468,67 @@ packages: cpu: [x64] os: [win32] - '@eslint-community/eslint-utils@4.4.0': - resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} + '@eslint-community/eslint-utils@4.4.1': + resolution: {integrity: sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - '@eslint-community/regexpp@4.11.1': - resolution: {integrity: sha512-m4DVN9ZqskZoLU5GlWZadwDnYo3vAEydiUayB9widCl9ffWx2IvPnp6n3on5rJmziJSw9Bv+Z3ChDVdMwXCY8Q==} + '@eslint-community/regexpp@4.12.1': + resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - '@eslint/compat@1.1.1': - resolution: {integrity: sha512-lpHyRyplhGPL5mGEh6M9O5nnKk0Gz4bFI+Zu6tKlPpDUN7XshWvH9C/px4UVm87IAANE0W81CEsNGbS1KlzXpA==} + '@eslint/compat@1.2.3': + resolution: {integrity: sha512-wlZhwlDFxkxIZ571aH0FoK4h4Vwx7P3HJx62Gp8hTc10bfpwT2x0nULuAHmQSJBOWPgPeVf+9YtnD4j50zVHmA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^9.10.0 + peerDependenciesMeta: + eslint: + optional: true + + '@eslint/config-array@0.19.0': + resolution: {integrity: sha512-zdHg2FPIFNKPdcHWtiNT+jEFCHYVplAXRDlQDyqy0zGx/q2parwh7brGJSiTxRk/TSMkbM//zt/f5CHgyTyaSQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/config-array@0.18.0': - resolution: {integrity: sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw==} + '@eslint/core@0.9.0': + resolution: {integrity: sha512-7ATR9F0e4W85D/0w7cU0SNj7qkAexMG+bAHEZOjo9akvGuhHE2m7umzWzfnpa0XAg5Kxc1BWmtPMV67jJ+9VUg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/eslintrc@3.1.0': - resolution: {integrity: sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==} + '@eslint/eslintrc@3.2.0': + resolution: {integrity: sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/js@9.11.0': - resolution: {integrity: sha512-LPkkenkDqyzTFauZLLAPhIb48fj6drrfMvRGSL9tS3AcZBSVTllemLSNyCvHNNL2t797S/6DJNSIwRwXgMO/eQ==} + '@eslint/js@9.15.0': + resolution: {integrity: sha512-tMTqrY+EzbXmKJR5ToI8lxu7jaN5EdmrBFJpQk5JmSlyLsx6o4t27r883K5xsLuCYCpfKBCGswMSWXsM+jB7lg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/object-schema@2.1.4': resolution: {integrity: sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/plugin-kit@0.2.0': - resolution: {integrity: sha512-vH9PiIMMwvhCx31Af3HiGzsVNULDbyVkHXwlemn/B0TFj/00ho3y55efXrUZTfQipxoHC5u4xq6zblww1zm1Ig==} + '@eslint/plugin-kit@0.2.3': + resolution: {integrity: sha512-2b/g5hRmpbb1o4GnTZax9N9m0FXzz9OV42ZzI4rDDMDuHUqigAiQCEWChBWCY4ztAGVRjoWT19v0yMmc5/L5kA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@humanfs/core@0.19.1': + resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} + engines: {node: '>=18.18.0'} + + '@humanfs/node@0.16.6': + resolution: {integrity: sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==} + engines: {node: '>=18.18.0'} + '@humanwhocodes/module-importer@1.0.1': resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} engines: {node: '>=12.22'} - '@humanwhocodes/retry@0.3.0': - resolution: {integrity: sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==} + '@humanwhocodes/retry@0.3.1': + resolution: {integrity: sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==} + engines: {node: '>=18.18'} + + '@humanwhocodes/retry@0.4.1': + resolution: {integrity: sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==} engines: {node: '>=18.18'} '@ioredis/commands@1.2.0': @@ -616,6 +633,10 @@ packages: '@jridgewell/trace-mapping@0.3.9': resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} + '@minswap/lucid-cardano@0.10.10-minswap.4': + resolution: {integrity: sha512-LFBm2F4ZuLC4z5ktXwQQPeyi9l2P2ypBu/5ZZr+b/ievYw6lDnwhYk6ju0zxjXYk5FG3wlQjW4Qpwqsy0ZlsKA==} + engines: {node: '>=14'} + '@minswap/tiny-invariant@1.2.0': resolution: {integrity: sha512-m4CMTsZ4MDB2WLND6rV0eti+f2WcMPhKvXf9ZHXlQMqvNmgoX1z//84FpEX0D1vVTPfJtNS8XIoIQ9pm6X590A==} @@ -642,12 +663,8 @@ packages: resolution: {integrity: sha512-BRs5XUAwiyCDQMsVA9IDvDa7UBR9gAvPHgugOeGng3YN6vJ9JYonyDc0lNczErgtCWtucjR5N7VtaonboD/ezg==} engines: {node: '>=10.12.0'} - '@pkgjs/parseargs@0.11.0': - resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} - engines: {node: '>=14'} - - '@prisma/client@5.19.1': - resolution: {integrity: sha512-x30GFguInsgt+4z5I4WbkZP2CGpotJMUXy+Gl/aaUjHn2o1DnLYNTA+q9XdYmAQZM8fIIkvUiA2NpgosM3fneg==} + '@prisma/client@5.22.0': + resolution: {integrity: sha512-M0SVXfyHnQREBKxCgyo7sffrKttwE6R8PMq330MIUF0pTwjUhLbW84pFDlf06B27XyCR++VtjugEnIHdr07SVA==} engines: {node: '>=16.13'} peerDependencies: prisma: '*' @@ -655,23 +672,23 @@ packages: prisma: optional: true - '@prisma/debug@5.19.1': - resolution: {integrity: sha512-lAG6A6QnG2AskAukIEucYJZxxcSqKsMK74ZFVfCTOM/7UiyJQi48v6TQ47d6qKG3LbMslqOvnTX25dj/qvclGg==} + '@prisma/debug@5.22.0': + resolution: {integrity: sha512-AUt44v3YJeggO2ZU5BkXI7M4hu9BF2zzH2iF2V5pyXT/lRTyWiElZ7It+bRH1EshoMRxHgpYg4VB6rCM+mG5jQ==} - '@prisma/engines-version@5.19.1-2.69d742ee20b815d88e17e54db4a2a7a3b30324e3': - resolution: {integrity: sha512-xR6rt+z5LnNqTP5BBc+8+ySgf4WNMimOKXRn6xfNRDSpHvbOEmd7+qAOmzCrddEc4Cp8nFC0txU14dstjH7FXA==} + '@prisma/engines-version@5.22.0-44.605197351a3c8bdd595af2d2a9bc3025bca48ea2': + resolution: {integrity: sha512-2PTmxFR2yHW/eB3uqWtcgRcgAbG1rwG9ZriSvQw+nnb7c4uCr3RAcGMb6/zfE88SKlC1Nj2ziUvc96Z379mHgQ==} - '@prisma/engines@5.19.1': - resolution: {integrity: sha512-kR/PoxZDrfUmbbXqqb8SlBBgCjvGaJYMCOe189PEYzq9rKqitQ2fvT/VJ8PDSe8tTNxhc2KzsCfCAL+Iwm/7Cg==} + '@prisma/engines@5.22.0': + resolution: {integrity: sha512-UNjfslWhAt06kVL3CjkuYpHAWSO6L4kDCVPegV6itt7nD1kSJavd3vhgAEhjglLJJKEdJ7oIqDJ+yHk6qO8gPA==} - '@prisma/fetch-engine@5.19.1': - resolution: {integrity: sha512-pCq74rtlOVJfn4pLmdJj+eI4P7w2dugOnnTXpRilP/6n5b2aZiA4ulJlE0ddCbTPkfHmOL9BfaRgA8o+1rfdHw==} + '@prisma/fetch-engine@5.22.0': + resolution: {integrity: sha512-bkrD/Mc2fSvkQBV5EpoFcZ87AvOgDxbG99488a5cexp5Ccny+UM6MAe/UFkUC0wLYD9+9befNOqGiIJhhq+HbA==} - '@prisma/get-platform@5.19.1': - resolution: {integrity: sha512-sCeoJ+7yt0UjnR+AXZL7vXlg5eNxaFOwC23h0KvW1YIXUoa7+W2ZcAUhoEQBmJTW4GrFqCuZ8YSP0mkDa4k3Zg==} + '@prisma/get-platform@5.22.0': + resolution: {integrity: sha512-pHhpQdr1UPFpt+zFfnPazhulaZYCUqeIcPpJViYoq9R+D/yw4fjE+CtnsnKzPYm0ddUbeXUzjGVGIRVgPDCk4Q==} - '@rollup/pluginutils@5.1.0': - resolution: {integrity: sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==} + '@rollup/pluginutils@5.1.3': + resolution: {integrity: sha512-Pnsb6f32CD2W3uCaLZIzDmeFyQ2b8UWMFI7xtwUezpcGBDVDW6y9XgAWIlARiGAo6eNF5FK5aQTr0LFyNyqq5A==} engines: {node: '>=14.0.0'} peerDependencies: rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 @@ -679,58 +696,68 @@ packages: rollup: optional: true - '@rollup/rollup-android-arm-eabi@4.22.4': - resolution: {integrity: sha512-Fxamp4aEZnfPOcGA8KSNEohV8hX7zVHOemC8jVBoBUHu5zpJK/Eu3uJwt6BMgy9fkvzxDaurgj96F/NiLukF2w==} + '@rollup/rollup-android-arm-eabi@4.27.4': + resolution: {integrity: sha512-2Y3JT6f5MrQkICUyRVCw4oa0sutfAsgaSsb0Lmmy1Wi2y7X5vT9Euqw4gOsCyy0YfKURBg35nhUKZS4mDcfULw==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.22.4': - resolution: {integrity: sha512-VXoK5UMrgECLYaMuGuVTOx5kcuap1Jm8g/M83RnCHBKOqvPPmROFJGQaZhGccnsFtfXQ3XYa4/jMCJvZnbJBdA==} + '@rollup/rollup-android-arm64@4.27.4': + resolution: {integrity: sha512-wzKRQXISyi9UdCVRqEd0H4cMpzvHYt1f/C3CoIjES6cG++RHKhrBj2+29nPF0IB5kpy9MS71vs07fvrNGAl/iA==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.22.4': - resolution: {integrity: sha512-xMM9ORBqu81jyMKCDP+SZDhnX2QEVQzTcC6G18KlTQEzWK8r/oNZtKuZaCcHhnsa6fEeOBionoyl5JsAbE/36Q==} + '@rollup/rollup-darwin-arm64@4.27.4': + resolution: {integrity: sha512-PlNiRQapift4LNS8DPUHuDX/IdXiLjf8mc5vdEmUR0fF/pyy2qWwzdLjB+iZquGr8LuN4LnUoSEvKRwjSVYz3Q==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.22.4': - resolution: {integrity: sha512-aJJyYKQwbHuhTUrjWjxEvGnNNBCnmpHDvrb8JFDbeSH3m2XdHcxDd3jthAzvmoI8w/kSjd2y0udT+4okADsZIw==} + '@rollup/rollup-darwin-x64@4.27.4': + resolution: {integrity: sha512-o9bH2dbdgBDJaXWJCDTNDYa171ACUdzpxSZt+u/AAeQ20Nk5x+IhA+zsGmrQtpkLiumRJEYef68gcpn2ooXhSQ==} cpu: [x64] os: [darwin] - '@rollup/rollup-linux-arm-gnueabihf@4.22.4': - resolution: {integrity: sha512-j63YtCIRAzbO+gC2L9dWXRh5BFetsv0j0va0Wi9epXDgU/XUi5dJKo4USTttVyK7fGw2nPWK0PbAvyliz50SCQ==} + '@rollup/rollup-freebsd-arm64@4.27.4': + resolution: {integrity: sha512-NBI2/i2hT9Q+HySSHTBh52da7isru4aAAo6qC3I7QFVsuhxi2gM8t/EI9EVcILiHLj1vfi+VGGPaLOUENn7pmw==} + cpu: [arm64] + os: [freebsd] + + '@rollup/rollup-freebsd-x64@4.27.4': + resolution: {integrity: sha512-wYcC5ycW2zvqtDYrE7deary2P2UFmSh85PUpAx+dwTCO9uw3sgzD6Gv9n5X4vLaQKsrfTSZZ7Z7uynQozPVvWA==} + cpu: [x64] + os: [freebsd] + + '@rollup/rollup-linux-arm-gnueabihf@4.27.4': + resolution: {integrity: sha512-9OwUnK/xKw6DyRlgx8UizeqRFOfi9mf5TYCw1uolDaJSbUmBxP85DE6T4ouCMoN6pXw8ZoTeZCSEfSaYo+/s1w==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm-musleabihf@4.22.4': - resolution: {integrity: sha512-dJnWUgwWBX1YBRsuKKMOlXCzh2Wu1mlHzv20TpqEsfdZLb3WoJW2kIEsGwLkroYf24IrPAvOT/ZQ2OYMV6vlrg==} + '@rollup/rollup-linux-arm-musleabihf@4.27.4': + resolution: {integrity: sha512-Vgdo4fpuphS9V24WOV+KwkCVJ72u7idTgQaBoLRD0UxBAWTF9GWurJO9YD9yh00BzbkhpeXtm6na+MvJU7Z73A==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm64-gnu@4.22.4': - resolution: {integrity: sha512-AdPRoNi3NKVLolCN/Sp4F4N1d98c4SBnHMKoLuiG6RXgoZ4sllseuGioszumnPGmPM2O7qaAX/IJdeDU8f26Aw==} + '@rollup/rollup-linux-arm64-gnu@4.27.4': + resolution: {integrity: sha512-pleyNgyd1kkBkw2kOqlBx+0atfIIkkExOTiifoODo6qKDSpnc6WzUY5RhHdmTdIJXBdSnh6JknnYTtmQyobrVg==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-arm64-musl@4.22.4': - resolution: {integrity: sha512-Gl0AxBtDg8uoAn5CCqQDMqAx22Wx22pjDOjBdmG0VIWX3qUBHzYmOKh8KXHL4UpogfJ14G4wk16EQogF+v8hmA==} + '@rollup/rollup-linux-arm64-musl@4.27.4': + resolution: {integrity: sha512-caluiUXvUuVyCHr5DxL8ohaaFFzPGmgmMvwmqAITMpV/Q+tPoaHZ/PWa3t8B2WyoRcIIuu1hkaW5KkeTDNSnMA==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-powerpc64le-gnu@4.22.4': - resolution: {integrity: sha512-3aVCK9xfWW1oGQpTsYJJPF6bfpWfhbRnhdlyhak2ZiyFLDaayz0EP5j9V1RVLAAxlmWKTDfS9wyRyY3hvhPoOg==} + '@rollup/rollup-linux-powerpc64le-gnu@4.27.4': + resolution: {integrity: sha512-FScrpHrO60hARyHh7s1zHE97u0KlT/RECzCKAdmI+LEoC1eDh/RDji9JgFqyO+wPDb86Oa/sXkily1+oi4FzJQ==} cpu: [ppc64] os: [linux] - '@rollup/rollup-linux-riscv64-gnu@4.22.4': - resolution: {integrity: sha512-ePYIir6VYnhgv2C5Xe9u+ico4t8sZWXschR6fMgoPUK31yQu7hTEJb7bCqivHECwIClJfKgE7zYsh1qTP3WHUA==} + '@rollup/rollup-linux-riscv64-gnu@4.27.4': + resolution: {integrity: sha512-qyyprhyGb7+RBfMPeww9FlHwKkCXdKHeGgSqmIXw9VSUtvyFZ6WZRtnxgbuz76FK7LyoN8t/eINRbPUcvXB5fw==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-s390x-gnu@4.22.4': - resolution: {integrity: sha512-GqFJ9wLlbB9daxhVlrTe61vJtEY99/xB3C8e4ULVsVfflcpmR6c8UZXjtkMA6FhNONhj2eA5Tk9uAVw5orEs4Q==} + '@rollup/rollup-linux-s390x-gnu@4.27.4': + resolution: {integrity: sha512-PFz+y2kb6tbh7m3A7nA9++eInGcDVZUACulf/KzDtovvdTizHpZaJty7Gp0lFwSQcrnebHOqxF1MaKZd7psVRg==} cpu: [s390x] os: [linux] @@ -739,28 +766,28 @@ packages: cpu: [x64] os: [linux] - '@rollup/rollup-linux-x64-gnu@4.22.4': - resolution: {integrity: sha512-87v0ol2sH9GE3cLQLNEy0K/R0pz1nvg76o8M5nhMR0+Q+BBGLnb35P0fVz4CQxHYXaAOhE8HhlkaZfsdUOlHwg==} + '@rollup/rollup-linux-x64-gnu@4.27.4': + resolution: {integrity: sha512-Ni8mMtfo+o/G7DVtweXXV/Ol2TFf63KYjTtoZ5f078AUgJTmaIJnj4JFU7TK/9SVWTaSJGxPi5zMDgK4w+Ez7Q==} cpu: [x64] os: [linux] - '@rollup/rollup-linux-x64-musl@4.22.4': - resolution: {integrity: sha512-UV6FZMUgePDZrFjrNGIWzDo/vABebuXBhJEqrHxrGiU6HikPy0Z3LfdtciIttEUQfuDdCn8fqh7wiFJjCNwO+g==} + '@rollup/rollup-linux-x64-musl@4.27.4': + resolution: {integrity: sha512-5AeeAF1PB9TUzD+3cROzFTnAJAcVUGLuR8ng0E0WXGkYhp6RD6L+6szYVX+64Rs0r72019KHZS1ka1q+zU/wUw==} cpu: [x64] os: [linux] - '@rollup/rollup-win32-arm64-msvc@4.22.4': - resolution: {integrity: sha512-BjI+NVVEGAXjGWYHz/vv0pBqfGoUH0IGZ0cICTn7kB9PyjrATSkX+8WkguNjWoj2qSr1im/+tTGRaY+4/PdcQw==} + '@rollup/rollup-win32-arm64-msvc@4.27.4': + resolution: {integrity: sha512-yOpVsA4K5qVwu2CaS3hHxluWIK5HQTjNV4tWjQXluMiiiu4pJj4BN98CvxohNCpcjMeTXk/ZMJBRbgRg8HBB6A==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.22.4': - resolution: {integrity: sha512-SiWG/1TuUdPvYmzmYnmd3IEifzR61Tragkbx9D3+R8mzQqDBz8v+BvZNDlkiTtI9T15KYZhP0ehn3Dld4n9J5g==} + '@rollup/rollup-win32-ia32-msvc@4.27.4': + resolution: {integrity: sha512-KtwEJOaHAVJlxV92rNYiG9JQwQAdhBlrjNRp7P9L8Cb4Rer3in+0A+IPhJC9y68WAi9H0sX4AiG2NTsVlmqJeQ==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.22.4': - resolution: {integrity: sha512-j8pPKp53/lq9lMXN57S8cFz0MynJk8OWNuUnXct/9KCpKU7DgU3bYMJhwWmcqC0UU29p8Lr0/7KEVcaM6bf47Q==} + '@rollup/rollup-win32-x64-msvc@4.27.4': + resolution: {integrity: sha512-3j4jx1TppORdTAoBJRd+/wJRGCPC0ETWkXOecJ6PPZLj6SptXkrXcNqdj0oclbKML6FkQltdz7bBA3rUSirZug==} cpu: [x64] os: [win32] @@ -817,9 +844,6 @@ packages: '@types/eslint__js@8.42.3': resolution: {integrity: sha512-alfG737uhmPdnvkrLdZLcEKJ/B8s9Y4hrZ+YAdzUeoArBlSUERA2E87ROfOaS4jd/C45fzOoZzidLc1IPwLqOw==} - '@types/estree@1.0.5': - resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} - '@types/estree@1.0.6': resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} @@ -838,8 +862,8 @@ packages: '@types/istanbul-reports@3.0.4': resolution: {integrity: sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==} - '@types/jest@29.5.13': - resolution: {integrity: sha512-wd+MVEZCHt23V0/L642O5APvspWply/rGY5BcW4SUETo2UzPU3Z26qr8jC2qxpimI2jjx9h7+2cj2FwIr01bXg==} + '@types/jest@29.5.14': + resolution: {integrity: sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ==} '@types/json-bigint@1.0.4': resolution: {integrity: sha512-ydHooXLbOmxBbubnA7Eh+RpBzuaIiQjh8WGJYQB50JFGFrdxW7JzVlyEV7fAXw0T2sqJ1ysTneJbiyNLqZRAag==} @@ -850,8 +874,8 @@ packages: '@types/keyv@3.1.4': resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==} - '@types/node@20.16.6': - resolution: {integrity: sha512-T7PpxM/6yeDE+AdlVysT62BX6/bECZOmQAgiFg5NoBd5MQheZ3tzal7f1wvzfiEcmrcJNRi2zRr2nY2zF+0uqw==} + '@types/node@20.17.7': + resolution: {integrity: sha512-sZXXnpBFMKbao30dUAvzKbdwA2JM1fwUtVEq/kxKuPI5mMwZiRElCpTXb0Biq/LMEVpXDZL5G5V0RPnxKeyaYg==} '@types/normalize-package-data@2.4.4': resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} @@ -868,8 +892,8 @@ packages: '@types/yargs@17.0.33': resolution: {integrity: sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==} - '@typescript-eslint/eslint-plugin@8.6.0': - resolution: {integrity: sha512-UOaz/wFowmoh2G6Mr9gw60B1mm0MzUtm6Ic8G2yM1Le6gyj5Loi/N+O5mocugRGY+8OeeKmkMmbxNqUCq3B4Sg==} + '@typescript-eslint/eslint-plugin@8.15.0': + resolution: {integrity: sha512-+zkm9AR1Ds9uLWN3fkoeXgFppaQ+uEVtfOV62dDmsy9QCNqlRHWNEck4yarvRNrvRcHQLGfqBNui3cimoz8XAg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: '@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0 @@ -879,8 +903,8 @@ packages: typescript: optional: true - '@typescript-eslint/parser@8.6.0': - resolution: {integrity: sha512-eQcbCuA2Vmw45iGfcyG4y6rS7BhWfz9MQuk409WD47qMM+bKCGQWXxvoOs1DUp+T7UBMTtRTVT+kXr7Sh4O9Ow==} + '@typescript-eslint/parser@8.15.0': + resolution: {integrity: sha512-7n59qFpghG4uazrF9qtGKBZXn7Oz4sOMm8dwNWDQY96Xlm2oX67eipqcblDj+oY1lLCbf1oltMZFpUso66Kl1A==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 @@ -889,25 +913,26 @@ packages: typescript: optional: true - '@typescript-eslint/scope-manager@8.6.0': - resolution: {integrity: sha512-ZuoutoS5y9UOxKvpc/GkvF4cuEmpokda4wRg64JEia27wX+PysIE9q+lzDtlHHgblwUWwo5/Qn+/WyTUvDwBHw==} + '@typescript-eslint/scope-manager@8.15.0': + resolution: {integrity: sha512-QRGy8ADi4J7ii95xz4UoiymmmMd/zuy9azCaamnZ3FM8T5fZcex8UfJcjkiEZjJSztKfEBe3dZ5T/5RHAmw2mA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/type-utils@8.6.0': - resolution: {integrity: sha512-dtePl4gsuenXVwC7dVNlb4mGDcKjDT/Ropsk4za/ouMBPplCLyznIaR+W65mvCvsyS97dymoBRrioEXI7k0XIg==} + '@typescript-eslint/type-utils@8.15.0': + resolution: {integrity: sha512-UU6uwXDoI3JGSXmcdnP5d8Fffa2KayOhUUqr/AiBnG1Gl7+7ut/oyagVeSkh7bxQ0zSXV9ptRh/4N15nkCqnpw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: + eslint: ^8.57.0 || ^9.0.0 typescript: '*' peerDependenciesMeta: typescript: optional: true - '@typescript-eslint/types@8.6.0': - resolution: {integrity: sha512-rojqFZGd4MQxw33SrOy09qIDS8WEldM8JWtKQLAjf/X5mGSeEFh5ixQlxssMNyPslVIk9yzWqXCsV2eFhYrYUw==} + '@typescript-eslint/types@8.15.0': + resolution: {integrity: sha512-n3Gt8Y/KyJNe0S3yDCD2RVKrHBC4gTUcLTebVBXacPy091E6tNspFLKRXlk3hwT4G55nfr1n2AdFqi/XMxzmPQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/typescript-estree@8.6.0': - resolution: {integrity: sha512-MOVAzsKJIPIlLK239l5s06YXjNqpKTVhBVDnqUumQJja5+Y94V3+4VUFRA0G60y2jNnTVwRCkhyGQpavfsbq/g==} + '@typescript-eslint/typescript-estree@8.15.0': + resolution: {integrity: sha512-1eMp2JgNec/niZsR7ioFBlsh/Fk0oJbhaqO0jRyQBMgkz7RrFfkqF9lYYmBoGBaSiLnu8TAPQTwoTUiSTUW9dg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '*' @@ -915,14 +940,18 @@ packages: typescript: optional: true - '@typescript-eslint/utils@8.6.0': - resolution: {integrity: sha512-eNp9cWnYf36NaOVjkEUznf6fEgVy1TWpE0o52e4wtojjBx7D1UV2WAWGzR+8Y5lVFtpMLPwNbC67T83DWSph4A==} + '@typescript-eslint/utils@8.15.0': + resolution: {integrity: sha512-k82RI9yGhr0QM3Dnq+egEpz9qB6Un+WLYhmoNcvl8ltMEededhh7otBVVIDDsEEttauwdY/hQoSsOv13lxrFzQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true - '@typescript-eslint/visitor-keys@8.6.0': - resolution: {integrity: sha512-wapVFfZg9H0qOYh4grNVQiMklJGluQrOUiOhYRrQWhx7BY/+I1IYb8BczWNbbUpO+pqy0rDciv3lQH5E1bCLrg==} + '@typescript-eslint/visitor-keys@8.15.0': + resolution: {integrity: sha512-h8vYOulWec9LhpwfAdZf2bjr8xIp0KNKnpgqSz0qqYYKAW/QZKw3ktRndbiAtUz4acH4QLQavwZBYCc0wulA/Q==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} acorn-jsx@5.3.2: @@ -934,8 +963,8 @@ packages: resolution: {integrity: sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==} engines: {node: '>=0.4.0'} - acorn@8.12.1: - resolution: {integrity: sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==} + acorn@8.14.0: + resolution: {integrity: sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==} engines: {node: '>=0.4.0'} hasBin: true @@ -957,10 +986,6 @@ packages: resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==} engines: {node: '>=12'} - ansi-styles@3.2.1: - resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} - engines: {node: '>=4'} - ansi-styles@4.3.0: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} @@ -1055,8 +1080,8 @@ packages: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} - browserslist@4.23.3: - resolution: {integrity: sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==} + browserslist@4.24.2: + resolution: {integrity: sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true @@ -1097,16 +1122,12 @@ packages: resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} engines: {node: '>=10'} - caniuse-lite@1.0.30001662: - resolution: {integrity: sha512-sgMUVwLmGseH8ZIrm1d51UbrhqMCH3jvS7gF/M6byuHOnKyLOBL7W8yz5V02OHwgLGA36o/AFhWzzh4uc5aqTA==} + caniuse-lite@1.0.30001684: + resolution: {integrity: sha512-G1LRwLIQjBQoyq0ZJGqGIJUXzJ8irpbjHLpVRXDvBEScFJ9b17sgK6vlx0GAJFE21okD7zXl08rRRUfq6HdoEQ==} - cbor@8.1.0: - resolution: {integrity: sha512-DwGjNW9omn6EwP70aXsn7FQJx5kO12tX0bZkaTjzdVFM6/7nhA4t0EENocKGx6D2Bch9PE2KzCUf5SceBdeijg==} - engines: {node: '>=12.19'} - - chalk@2.4.2: - resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} - engines: {node: '>=4'} + cbor@9.0.2: + resolution: {integrity: sha512-JPypkxsB10s9QOWwa6zwPzqE1Md3vqpPc+cai4sAecuCsRyAtAl/pMyhPlMbT/xtPnm2dznJZYRLui57qiRhaQ==} + engines: {node: '>=16'} chalk@4.1.2: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} @@ -1120,8 +1141,8 @@ packages: resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} engines: {node: '>=8'} - ci-info@4.0.0: - resolution: {integrity: sha512-TdHqgGf9odd8SXNuxtUBVx8Nv+qZOejE6qyqiy5NtbYYQOeFa6zmHkxlPzmaLxWWHsU6nJmB7AETdVPi+2NBUg==} + ci-info@4.1.0: + resolution: {integrity: sha512-HutrvTNsF48wnxkzERIXOe5/mlcfFcbfCmwcg6CJnizbSue78AbDt+1cgl26zwn61WFxhcPykPfZrbqjGmBb4A==} engines: {node: '>=8'} cjs-module-lexer@1.4.1: @@ -1149,16 +1170,10 @@ packages: collect-v8-coverage@1.0.2: resolution: {integrity: sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==} - color-convert@1.9.3: - resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} - color-convert@2.0.1: resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} engines: {node: '>=7.0.0'} - color-name@1.1.3: - resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} - color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} @@ -1172,8 +1187,8 @@ packages: convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} - core-js-compat@3.38.1: - resolution: {integrity: sha512-JRH6gfXxGmrzF3tZ57lFx97YARxCXPaMzPo6jELZhv88pBH5VXpQ+y0znKGlFnzuaihqhLbefxSJxWJMPtfDzw==} + core-js-compat@3.39.0: + resolution: {integrity: sha512-VgEUx3VwlExr5no0tXlBt+silBvhTryPwCXRI2Id1PN8WTKu7MreethvddqOubrYxkFdv/RnYrqlv1sFNAUelw==} create-jest@29.7.0: resolution: {integrity: sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==} @@ -1186,8 +1201,8 @@ packages: cross-fetch@3.1.8: resolution: {integrity: sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg==} - cross-spawn@7.0.3: - resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} data-uri-to-buffer@4.0.1: @@ -1254,8 +1269,8 @@ packages: engines: {node: '>=0.10.0'} hasBin: true - electron-to-chromium@1.5.27: - resolution: {integrity: sha512-o37j1vZqCoEgBuWWXLHQgTN/KDKe7zwpiY5CPeq2RvUqOyJw9xnrULzZAEVQ5p4h+zjMk7hgtOoPdnLxr7m/jw==} + electron-to-chromium@1.5.64: + resolution: {integrity: sha512-IXEuxU+5ClW2IGEYFC2T7szbyVgehupCWQe5GNh+H065CD6U6IFN0s4KeAMFGNmQolRU4IV7zGBWSYMmZ8uuqQ==} emittery@0.13.1: resolution: {integrity: sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==} @@ -1317,20 +1332,20 @@ packages: '@typescript-eslint/eslint-plugin': optional: true - eslint-scope@8.0.2: - resolution: {integrity: sha512-6E4xmrTw5wtxnLA5wYL3WDfhZ/1bUBGOXV0zQvVRDOtrR8D0p6W7fs3JweNYhwRYeGvd/1CKX2se0/2s7Q/nJA==} + eslint-scope@8.2.0: + resolution: {integrity: sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} eslint-visitor-keys@3.4.3: resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - eslint-visitor-keys@4.0.0: - resolution: {integrity: sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==} + eslint-visitor-keys@4.2.0: + resolution: {integrity: sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - eslint@9.11.0: - resolution: {integrity: sha512-yVS6XODx+tMFMDFcG4+Hlh+qG7RM6cCJXtQhCKLSsr3XkLvWggHjCqjfh0XsPPnt1c56oaT6PMgW9XWQQjdHXA==} + eslint@9.15.0: + resolution: {integrity: sha512-7CrWySmIibCgT1Os28lUU6upBshZ+GxybLOrmRzi08kS8MBuO8QA7pXEgYgY5W8vK3e74xv0lpjo9DbaGU9Rkw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} hasBin: true peerDependencies: @@ -1339,8 +1354,8 @@ packages: jiti: optional: true - espree@10.1.0: - resolution: {integrity: sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==} + espree@10.3.0: + resolution: {integrity: sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} esprima@4.0.1: @@ -1395,8 +1410,8 @@ packages: fast-levenshtein@2.0.6: resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} - fast-uri@3.0.1: - resolution: {integrity: sha512-MWipKbbYiYI0UC7cl8m/i/IWTqfC8YXsqjzybjddLsFjStroQzsHXkc73JutMvBiXmOvapk+axIl79ig5t55Bw==} + fast-uri@3.0.3: + resolution: {integrity: sha512-aLrHthzCjH5He4Z2H9YZ+v6Ujb9ocRuW6ZzkJQOrTxleEijANq4v1TsaPaVG1PZcuurEzrLcWRyYBYXD5cEiaw==} fastq@1.17.1: resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} @@ -1431,15 +1446,15 @@ packages: resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} engines: {node: '>=16'} - flatted@3.3.1: - resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==} + flatted@3.3.2: + resolution: {integrity: sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==} foreground-child@3.3.0: resolution: {integrity: sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==} engines: {node: '>=14'} - form-data@4.0.0: - resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} + form-data@4.0.1: + resolution: {integrity: sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==} engines: {node: '>= 6'} formdata-polyfill@4.0.10: @@ -1505,8 +1520,8 @@ packages: resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} engines: {node: '>=18'} - globals@15.9.0: - resolution: {integrity: sha512-SmSKyLLKFbSr6rptvP8izbyxJL4ILwqO9Jg23UA0sDlGlu58V59D1//I3vlc0KJphVdUR7vMjHIplYnzBxorQA==} + globals@15.12.0: + resolution: {integrity: sha512-1+gLErljJFhbOVyaetcwJiJ4+eLe45S2E7P5UiZ9xGfeq3ATQf5DOv9G7MH3gGbKQLkzmNh2DxfZwLdw+j6oTQ==} engines: {node: '>=18'} got@11.8.6: @@ -1519,10 +1534,6 @@ packages: graphemer@1.4.0: resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} - has-flag@3.0.0: - resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} - engines: {node: '>=4'} - has-flag@4.0.0: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} @@ -1614,10 +1625,6 @@ packages: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} - is-path-inside@3.0.3: - resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} - engines: {node: '>=8'} - is-stream@2.0.1: resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} engines: {node: '>=8'} @@ -1654,8 +1661,8 @@ packages: resolution: {integrity: sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==} engines: {node: '>=8'} - jackspeak@4.0.1: - resolution: {integrity: sha512-cub8rahkh0Q/bw1+GxP7aeSe29hHHn2V4m29nnDlvCdlgU+3UGxkZp7Z53jLUdpX3jdTO0nJZUDl3xvbWc2Xog==} + jackspeak@4.0.2: + resolution: {integrity: sha512-bZsjR/iRjl1Nk1UkjGpAzLNfQtzuijhn2g+pbZb98HQ1Gk8vM9hfbxeMBP+M2/UUdwj0RqGG3mlvk2MsAqwvEw==} engines: {node: 20 || >=22} jake@10.9.2: @@ -1807,11 +1814,6 @@ packages: resolution: {integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==} hasBin: true - jsesc@2.5.2: - resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} - engines: {node: '>=4'} - hasBin: true - jsesc@3.0.2: resolution: {integrity: sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==} engines: {node: '>=6'} @@ -1882,19 +1884,15 @@ packages: resolution: {integrity: sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==} engines: {node: '>=8'} - lru-cache@11.0.1: - resolution: {integrity: sha512-CgeuL5uom6j/ZVrg7G/+1IXqRY8JXX4Hghfy5YE0EhoYQWvndP1kufu58cmZLNIDKnRhZrXfdS9urVWx98AipQ==} + lru-cache@11.0.2: + resolution: {integrity: sha512-123qHRfJBmo2jXDbo/a5YOQrJoHF/GNQTLzQ5+IdK5pWpceK17yRc6ozlWd25FxvGKQbIUs91fDFkXmDHTKcyA==} engines: {node: 20 || >=22} lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} - lucid-cardano@0.10.10: - resolution: {integrity: sha512-Yp1o8/kbVUgkRpQqllGQCT9I9w70a+uQKSoJdZEHVrEo5MFbT3Vds314Q8ClqgExzN7pj9NHGbiwiow2ik7mUA==} - engines: {node: '>=14'} - - magic-string@0.30.11: - resolution: {integrity: sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==} + magic-string@0.30.13: + resolution: {integrity: sha512-8rYBO+MsWkgjDSOvLomYnzhdwEG51olQ4zL5KXnNJWV5MNmrb4rTZdrtkhxjnD/QyZUqR/Z/XDsUs/4ej2nx0g==} make-dir@4.0.0: resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} @@ -2051,8 +2049,8 @@ packages: resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} engines: {node: '>=6'} - package-json-from-dist@1.0.0: - resolution: {integrity: sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==} + package-json-from-dist@1.0.1: + resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} parent-module@1.0.1: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} @@ -2081,13 +2079,17 @@ packages: resolution: {integrity: sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==} engines: {node: 20 || >=22} - picocolors@1.1.0: - resolution: {integrity: sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==} + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} picomatch@2.3.1: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} + picomatch@4.0.2: + resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} + engines: {node: '>=12'} + pirates@4.0.6: resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} engines: {node: '>= 6'} @@ -2113,8 +2115,8 @@ packages: resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - prisma@5.19.1: - resolution: {integrity: sha512-c5K9MiDaa+VAAyh1OiYk76PXOme9s3E992D7kvvIOhCrNsBQfy2mP2QAQtX0WNj140IgG++12kwZpYB9iIydNQ==} + prisma@5.22.0: + resolution: {integrity: sha512-vtpjW3XuYCSnMsNVBjLMNkTj6OZbudcPPTPYHqX0CJfpcdWciI1dM8uHETwmDxxiqEwCIE6WvXucWUetJgfu/A==} engines: {node: '>=16.13'} hasBin: true @@ -2132,8 +2134,8 @@ packages: pure-rand@6.1.0: resolution: {integrity: sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==} - pvtsutils@1.3.5: - resolution: {integrity: sha512-ARvb14YB9Nm2Xi6nBq1ZX6dAM0FsJnuk+31aUp4TrcZEdKUlSqOqsxJHUPJDNE3qiIp+iUPEIeR6Je/tgV7zsA==} + pvtsutils@1.3.6: + resolution: {integrity: sha512-PLgQXQ6H2FWCaeRak8vvk1GW462lMxB5s3Jm673N82zI4vqtVUPuZdffdZbPDFRoU8kAhItWFtPCWiPpp4/EDg==} pvutils@1.1.3: resolution: {integrity: sha512-pMpnA0qRdFp32b1sJl1wOJNxZLQ2cbQx+k6tjNtZ8CpvVhNqEPRgivZ2WOUev2YMajecdH7ctUPDvEe87nariQ==} @@ -2173,8 +2175,8 @@ packages: resolution: {integrity: sha512-qx+xQGZVsy55CH0a1hiVwHmqjLryfh7wQyF5HO07XJ9f7dQMY/gPQHhlyDkIzJKC+x2fUCpCcUODUUUFrm7SHA==} hasBin: true - remeda@2.14.0: - resolution: {integrity: sha512-OSOhr9gGcb3AshMxlu9YnnUtKSkeYhj+AxWiWGfVh3HolYtJP5IF9vC1j1tq15uI7lxCPVd9qnnp43dOvZ840A==} + remeda@2.17.3: + resolution: {integrity: sha512-xyi2rCQkz2j4BEWbWxPw6JCapv1yBuSwr4Uf9BX00AkesAJaiKvc6Il6thsBidwVZAtNiSaCIXvslkKL0ybz8w==} require-directory@2.1.1: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} @@ -2236,8 +2238,8 @@ packages: esbuild: '>=0.18.0' rollup: ^1.20.0 || ^2.0.0 || ^3.0.0 || ^4.0.0 - rollup@4.22.4: - resolution: {integrity: sha512-vD8HJ5raRcWOyymsR6Z3o6+RzfEPCnVLMFJ6vRslO1jt4LO6dUo5Qnpg7y4RkZFM2DMe3WUirkI5c16onjrc6A==} + rollup@4.27.4: + resolution: {integrity: sha512-RLKxqHEMjh/RGLsDxAEsaLO3mWgyoU6x9w6n1ikAzet4B3gI2/3yP6PWY2p9QzRTh6MfEIXB3MwsOY0Iv3vNrw==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true @@ -2347,10 +2349,6 @@ packages: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} - supports-color@5.5.0: - resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} - engines: {node: '>=4'} - supports-color@7.2.0: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} @@ -2367,16 +2365,9 @@ packages: resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} engines: {node: '>=8'} - text-table@0.2.0: - resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} - tmpl@1.0.5: resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} - to-fast-properties@2.0.0: - resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} - engines: {node: '>=4'} - to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} @@ -2384,8 +2375,8 @@ packages: tr46@0.0.3: resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} - ts-api-utils@1.3.0: - resolution: {integrity: sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==} + ts-api-utils@1.4.1: + resolution: {integrity: sha512-5RU2/lxTA3YUZxju61HO2U6EoZLvBLtmV2mbTvqyu4a/7s7RmJPT+1YekhMVsQhznRWk/czIwDUg+V8Q9ZuG4w==} engines: {node: '>=16'} peerDependencies: typescript: '>=4.2.0' @@ -2432,8 +2423,13 @@ packages: '@swc/wasm': optional: true - tslib@2.7.0: - resolution: {integrity: sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==} + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + tsx@4.19.2: + resolution: {integrity: sha512-pOUl6Vo2LUq/bSa8S5q7b91cgNSjctn9ugq/+Mvow99qW6x/UZYwzxy/3NmqoT66eHYfCVvFvACC58UBPFf28g==} + engines: {node: '>=18.0.0'} + hasBin: true type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} @@ -2455,29 +2451,30 @@ packages: resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} engines: {node: '>=8'} - type-fest@4.26.1: - resolution: {integrity: sha512-yOGpmOAL7CkKe/91I5O3gPICmJNLJ1G4zFYVAsRHg7M64biSnPtRj0WNQt++bRkjYOqjWXrhnUw1utzmVErAdg==} + type-fest@4.28.0: + resolution: {integrity: sha512-jXMwges/FVbFRe5lTMJZVEZCrO9kI9c8k0PA/z7nF3bo0JSCCLysvokFjNPIUK/itEMas10MQM+AiHoHt/T/XA==} engines: {node: '>=16'} - typescript-eslint@8.6.0: - resolution: {integrity: sha512-eEhhlxCEpCd4helh3AO1hk0UP2MvbRi9CtIAJTVPQjuSXOOO2jsEacNi4UdcJzZJbeuVg1gMhtZ8UYb+NFYPrA==} + typescript-eslint@8.15.0: + resolution: {integrity: sha512-wY4FRGl0ZI+ZU4Jo/yjdBu0lVTSML58pu6PgGtJmCufvzfV565pUF6iACQt092uFOd49iLOTX/sEVmHtbSrS+w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: + eslint: ^8.57.0 || ^9.0.0 typescript: '*' peerDependenciesMeta: typescript: optional: true - typescript@5.6.2: - resolution: {integrity: sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==} + typescript@5.7.2: + resolution: {integrity: sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==} engines: {node: '>=14.17'} hasBin: true undici-types@6.19.8: resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} - update-browserslist-db@1.1.0: - resolution: {integrity: sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==} + update-browserslist-db@1.1.1: + resolution: {integrity: sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==} hasBin: true peerDependencies: browserslist: '>= 4.21.0' @@ -2502,8 +2499,8 @@ packages: resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==} engines: {node: '>= 8'} - webcrypto-core@1.8.0: - resolution: {integrity: sha512-kR1UQNH8MD42CYuLzvibfakG5Ew5seG85dMMoAM/1LqvckxaF6pUiidLuraIu4V+YCIFabYecUZAW0TuxAoaqw==} + webcrypto-core@1.8.1: + resolution: {integrity: sha512-P+x1MvlNCXlKbLSOY4cYrdreqPG5hbzkmawbcXLKN/mf6DZW0SdNNkZ+sjwsqVkI4A4Ko2sPZmkZtCKY58w83A==} webidl-conversions@3.0.1: resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} @@ -2566,8 +2563,8 @@ packages: yallist@3.1.1: resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} - yaml@2.5.1: - resolution: {integrity: sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==} + yaml@2.6.1: + resolution: {integrity: sha512-7r0XPzioN/Q9kXBro/XPnA6kznR73DHq+GXh5ON7ZozRO6aMjbmiBuKste2wslTFkC5d1dw0GooOCepZXJ2SAg==} engines: {node: '>= 14'} hasBin: true @@ -2594,25 +2591,26 @@ snapshots: '@jridgewell/gen-mapping': 0.3.5 '@jridgewell/trace-mapping': 0.3.25 - '@babel/code-frame@7.24.7': + '@babel/code-frame@7.26.2': dependencies: - '@babel/highlight': 7.24.7 - picocolors: 1.1.0 + '@babel/helper-validator-identifier': 7.25.9 + js-tokens: 4.0.0 + picocolors: 1.1.1 - '@babel/compat-data@7.25.4': {} + '@babel/compat-data@7.26.2': {} - '@babel/core@7.25.2': + '@babel/core@7.26.0': dependencies: '@ampproject/remapping': 2.3.0 - '@babel/code-frame': 7.24.7 - '@babel/generator': 7.25.6 - '@babel/helper-compilation-targets': 7.25.2 - '@babel/helper-module-transforms': 7.25.2(@babel/core@7.25.2) - '@babel/helpers': 7.25.6 - '@babel/parser': 7.25.6 - '@babel/template': 7.25.0 - '@babel/traverse': 7.25.6 - '@babel/types': 7.25.6 + '@babel/code-frame': 7.26.2 + '@babel/generator': 7.26.2 + '@babel/helper-compilation-targets': 7.25.9 + '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.0) + '@babel/helpers': 7.26.0 + '@babel/parser': 7.26.2 + '@babel/template': 7.25.9 + '@babel/traverse': 7.25.9 + '@babel/types': 7.26.0 convert-source-map: 2.0.0 debug: 4.3.7 gensync: 1.0.0-beta.2 @@ -2621,199 +2619,185 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/generator@7.25.6': + '@babel/generator@7.26.2': dependencies: - '@babel/types': 7.25.6 + '@babel/parser': 7.26.2 + '@babel/types': 7.26.0 '@jridgewell/gen-mapping': 0.3.5 '@jridgewell/trace-mapping': 0.3.25 - jsesc: 2.5.2 + jsesc: 3.0.2 - '@babel/helper-compilation-targets@7.25.2': + '@babel/helper-compilation-targets@7.25.9': dependencies: - '@babel/compat-data': 7.25.4 - '@babel/helper-validator-option': 7.24.8 - browserslist: 4.23.3 + '@babel/compat-data': 7.26.2 + '@babel/helper-validator-option': 7.25.9 + browserslist: 4.24.2 lru-cache: 5.1.1 semver: 6.3.1 - '@babel/helper-module-imports@7.24.7': - dependencies: - '@babel/traverse': 7.25.6 - '@babel/types': 7.25.6 - transitivePeerDependencies: - - supports-color - - '@babel/helper-module-transforms@7.25.2(@babel/core@7.25.2)': + '@babel/helper-module-imports@7.25.9': dependencies: - '@babel/core': 7.25.2 - '@babel/helper-module-imports': 7.24.7 - '@babel/helper-simple-access': 7.24.7 - '@babel/helper-validator-identifier': 7.24.7 - '@babel/traverse': 7.25.6 + '@babel/traverse': 7.25.9 + '@babel/types': 7.26.0 transitivePeerDependencies: - supports-color - '@babel/helper-plugin-utils@7.24.8': {} - - '@babel/helper-simple-access@7.24.7': + '@babel/helper-module-transforms@7.26.0(@babel/core@7.26.0)': dependencies: - '@babel/traverse': 7.25.6 - '@babel/types': 7.25.6 + '@babel/core': 7.26.0 + '@babel/helper-module-imports': 7.25.9 + '@babel/helper-validator-identifier': 7.25.9 + '@babel/traverse': 7.25.9 transitivePeerDependencies: - supports-color - '@babel/helper-string-parser@7.24.8': {} + '@babel/helper-plugin-utils@7.25.9': {} - '@babel/helper-validator-identifier@7.24.7': {} + '@babel/helper-string-parser@7.25.9': {} - '@babel/helper-validator-option@7.24.8': {} + '@babel/helper-validator-identifier@7.25.9': {} - '@babel/helpers@7.25.6': - dependencies: - '@babel/template': 7.25.0 - '@babel/types': 7.25.6 + '@babel/helper-validator-option@7.25.9': {} - '@babel/highlight@7.24.7': + '@babel/helpers@7.26.0': dependencies: - '@babel/helper-validator-identifier': 7.24.7 - chalk: 2.4.2 - js-tokens: 4.0.0 - picocolors: 1.1.0 + '@babel/template': 7.25.9 + '@babel/types': 7.26.0 - '@babel/parser@7.25.6': + '@babel/parser@7.26.2': dependencies: - '@babel/types': 7.25.6 + '@babel/types': 7.26.0 - '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.25.2)': + '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.24.8 + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 - '@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.25.2)': + '@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.24.8 + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 - '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.25.2)': + '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.24.8 + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 - '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.25.2)': + '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.24.8 + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 - '@babel/plugin-syntax-import-attributes@7.25.6(@babel/core@7.25.2)': + '@babel/plugin-syntax-import-attributes@7.26.0(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.24.8 + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 - '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.25.2)': + '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.24.8 + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 - '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.25.2)': + '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.24.8 + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 - '@babel/plugin-syntax-jsx@7.24.7(@babel/core@7.25.2)': + '@babel/plugin-syntax-jsx@7.25.9(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.24.8 + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 - '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.25.2)': + '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.24.8 + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 - '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.25.2)': + '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.24.8 + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 - '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.25.2)': + '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.24.8 + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 - '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.25.2)': + '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.24.8 + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 - '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.25.2)': + '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.24.8 + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 - '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.25.2)': + '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.24.8 + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 - '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.25.2)': + '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.24.8 + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 - '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.25.2)': + '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.24.8 + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 - '@babel/plugin-syntax-typescript@7.25.4(@babel/core@7.25.2)': + '@babel/plugin-syntax-typescript@7.25.9(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.24.8 + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 - '@babel/template@7.25.0': + '@babel/template@7.25.9': dependencies: - '@babel/code-frame': 7.24.7 - '@babel/parser': 7.25.6 - '@babel/types': 7.25.6 + '@babel/code-frame': 7.26.2 + '@babel/parser': 7.26.2 + '@babel/types': 7.26.0 - '@babel/traverse@7.25.6': + '@babel/traverse@7.25.9': dependencies: - '@babel/code-frame': 7.24.7 - '@babel/generator': 7.25.6 - '@babel/parser': 7.25.6 - '@babel/template': 7.25.0 - '@babel/types': 7.25.6 + '@babel/code-frame': 7.26.2 + '@babel/generator': 7.26.2 + '@babel/parser': 7.26.2 + '@babel/template': 7.25.9 + '@babel/types': 7.26.0 debug: 4.3.7 globals: 11.12.0 transitivePeerDependencies: - supports-color - '@babel/types@7.25.6': + '@babel/types@7.26.0': dependencies: - '@babel/helper-string-parser': 7.24.8 - '@babel/helper-validator-identifier': 7.24.7 - to-fast-properties: 2.0.0 + '@babel/helper-string-parser': 7.25.9 + '@babel/helper-validator-identifier': 7.25.9 '@bcoe/v8-coverage@0.2.3': {} - '@blockfrost/blockfrost-js@5.5.0': + '@blockfrost/blockfrost-js@5.7.0': dependencies: - '@blockfrost/openapi': 0.1.60 + '@blockfrost/openapi': 0.1.70-beta.0 '@emurgo/cardano-serialization-lib-nodejs': 11.5.0 '@emurgo/cip14-js': 3.0.1 bottleneck: 2.19.5 - form-data: 4.0.0 + form-data: 4.0.1 got: 11.8.6 json-bigint: 1.0.0 - '@blockfrost/openapi@0.1.60': + '@blockfrost/openapi@0.1.70-beta.0': dependencies: ajv: 8.17.1 - cbor: 8.1.0 - yaml: 2.5.1 + cbor: 9.0.2 + rimraf: 6.0.1 + yaml: 2.6.1 - '@cardano-ogmios/client@6.8.0': + '@cardano-ogmios/client@6.9.0': dependencies: - '@cardano-ogmios/schema': 6.8.0 + '@cardano-ogmios/schema': 6.9.0 '@cardanosolutions/json-bigint': 1.0.1 '@types/json-bigint': 1.0.4 bech32: 2.0.0 @@ -2828,7 +2812,7 @@ snapshots: - encoding - utf-8-validate - '@cardano-ogmios/schema@6.8.0': {} + '@cardano-ogmios/schema@6.9.0': {} '@cardanosolutions/json-bigint@1.0.1': dependencies: @@ -2917,16 +2901,18 @@ snapshots: '@esbuild/win32-x64@0.23.1': optional: true - '@eslint-community/eslint-utils@4.4.0(eslint@9.11.0)': + '@eslint-community/eslint-utils@4.4.1(eslint@9.15.0)': dependencies: - eslint: 9.11.0 + eslint: 9.15.0 eslint-visitor-keys: 3.4.3 - '@eslint-community/regexpp@4.11.1': {} + '@eslint-community/regexpp@4.12.1': {} - '@eslint/compat@1.1.1': {} + '@eslint/compat@1.2.3(eslint@9.15.0)': + optionalDependencies: + eslint: 9.15.0 - '@eslint/config-array@0.18.0': + '@eslint/config-array@0.19.0': dependencies: '@eslint/object-schema': 2.1.4 debug: 4.3.7 @@ -2934,11 +2920,13 @@ snapshots: transitivePeerDependencies: - supports-color - '@eslint/eslintrc@3.1.0': + '@eslint/core@0.9.0': {} + + '@eslint/eslintrc@3.2.0': dependencies: ajv: 6.12.6 debug: 4.3.7 - espree: 10.1.0 + espree: 10.3.0 globals: 14.0.0 ignore: 5.3.2 import-fresh: 3.3.0 @@ -2948,17 +2936,26 @@ snapshots: transitivePeerDependencies: - supports-color - '@eslint/js@9.11.0': {} + '@eslint/js@9.15.0': {} '@eslint/object-schema@2.1.4': {} - '@eslint/plugin-kit@0.2.0': + '@eslint/plugin-kit@0.2.3': dependencies: levn: 0.4.1 + '@humanfs/core@0.19.1': {} + + '@humanfs/node@0.16.6': + dependencies: + '@humanfs/core': 0.19.1 + '@humanwhocodes/retry': 0.3.1 + '@humanwhocodes/module-importer@1.0.1': {} - '@humanwhocodes/retry@0.3.0': {} + '@humanwhocodes/retry@0.3.1': {} + + '@humanwhocodes/retry@0.4.1': {} '@ioredis/commands@1.2.0': {} @@ -2984,27 +2981,27 @@ snapshots: '@jest/console@29.7.0': dependencies: '@jest/types': 29.6.3 - '@types/node': 20.16.6 + '@types/node': 20.17.7 chalk: 4.1.2 jest-message-util: 29.7.0 jest-util: 29.7.0 slash: 3.0.0 - '@jest/core@29.7.0(ts-node@10.9.2(@types/node@20.16.6)(typescript@5.6.2))': + '@jest/core@29.7.0(ts-node@10.9.2(@types/node@20.17.7)(typescript@5.7.2))': dependencies: '@jest/console': 29.7.0 '@jest/reporters': 29.7.0 '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.16.6 + '@types/node': 20.17.7 ansi-escapes: 4.3.2 chalk: 4.1.2 ci-info: 3.9.0 exit: 0.1.2 graceful-fs: 4.2.11 jest-changed-files: 29.7.0 - jest-config: 29.7.0(@types/node@20.16.6)(ts-node@10.9.2(@types/node@20.16.6)(typescript@5.6.2)) + jest-config: 29.7.0(@types/node@20.17.7)(ts-node@10.9.2(@types/node@20.17.7)(typescript@5.7.2)) jest-haste-map: 29.7.0 jest-message-util: 29.7.0 jest-regex-util: 29.6.3 @@ -3029,7 +3026,7 @@ snapshots: dependencies: '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.16.6 + '@types/node': 20.17.7 jest-mock: 29.7.0 '@jest/expect-utils@29.7.0': @@ -3047,7 +3044,7 @@ snapshots: dependencies: '@jest/types': 29.6.3 '@sinonjs/fake-timers': 10.3.0 - '@types/node': 20.16.6 + '@types/node': 20.17.7 jest-message-util: 29.7.0 jest-mock: 29.7.0 jest-util: 29.7.0 @@ -3069,7 +3066,7 @@ snapshots: '@jest/transform': 29.7.0 '@jest/types': 29.6.3 '@jridgewell/trace-mapping': 0.3.25 - '@types/node': 20.16.6 + '@types/node': 20.17.7 chalk: 4.1.2 collect-v8-coverage: 1.0.2 exit: 0.1.2 @@ -3116,7 +3113,7 @@ snapshots: '@jest/transform@29.7.0': dependencies: - '@babel/core': 7.25.2 + '@babel/core': 7.26.0 '@jest/types': 29.6.3 '@jridgewell/trace-mapping': 0.3.25 babel-plugin-istanbul: 6.1.1 @@ -3139,7 +3136,7 @@ snapshots: '@jest/schemas': 29.6.3 '@types/istanbul-lib-coverage': 2.0.6 '@types/istanbul-reports': 3.0.4 - '@types/node': 20.16.6 + '@types/node': 20.17.7 '@types/yargs': 17.0.33 chalk: 4.1.2 @@ -3165,6 +3162,15 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.0 + '@minswap/lucid-cardano@0.10.10-minswap.4': + dependencies: + '@peculiar/webcrypto': 1.5.0 + node-fetch: 3.3.2 + ws: 8.18.0 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + '@minswap/tiny-invariant@1.2.0': {} '@nodelib/fs.scandir@2.1.5': @@ -3182,106 +3188,109 @@ snapshots: '@peculiar/asn1-schema@2.3.13': dependencies: asn1js: 3.0.5 - pvtsutils: 1.3.5 - tslib: 2.7.0 + pvtsutils: 1.3.6 + tslib: 2.8.1 '@peculiar/json-schema@1.1.12': dependencies: - tslib: 2.7.0 + tslib: 2.8.1 '@peculiar/webcrypto@1.5.0': dependencies: '@peculiar/asn1-schema': 2.3.13 '@peculiar/json-schema': 1.1.12 - pvtsutils: 1.3.5 - tslib: 2.7.0 - webcrypto-core: 1.8.0 - - '@pkgjs/parseargs@0.11.0': - optional: true + pvtsutils: 1.3.6 + tslib: 2.8.1 + webcrypto-core: 1.8.1 - '@prisma/client@5.19.1(prisma@5.19.1)': + '@prisma/client@5.22.0(prisma@5.22.0)': optionalDependencies: - prisma: 5.19.1 + prisma: 5.22.0 - '@prisma/debug@5.19.1': {} + '@prisma/debug@5.22.0': {} - '@prisma/engines-version@5.19.1-2.69d742ee20b815d88e17e54db4a2a7a3b30324e3': {} + '@prisma/engines-version@5.22.0-44.605197351a3c8bdd595af2d2a9bc3025bca48ea2': {} - '@prisma/engines@5.19.1': + '@prisma/engines@5.22.0': dependencies: - '@prisma/debug': 5.19.1 - '@prisma/engines-version': 5.19.1-2.69d742ee20b815d88e17e54db4a2a7a3b30324e3 - '@prisma/fetch-engine': 5.19.1 - '@prisma/get-platform': 5.19.1 + '@prisma/debug': 5.22.0 + '@prisma/engines-version': 5.22.0-44.605197351a3c8bdd595af2d2a9bc3025bca48ea2 + '@prisma/fetch-engine': 5.22.0 + '@prisma/get-platform': 5.22.0 - '@prisma/fetch-engine@5.19.1': + '@prisma/fetch-engine@5.22.0': dependencies: - '@prisma/debug': 5.19.1 - '@prisma/engines-version': 5.19.1-2.69d742ee20b815d88e17e54db4a2a7a3b30324e3 - '@prisma/get-platform': 5.19.1 + '@prisma/debug': 5.22.0 + '@prisma/engines-version': 5.22.0-44.605197351a3c8bdd595af2d2a9bc3025bca48ea2 + '@prisma/get-platform': 5.22.0 - '@prisma/get-platform@5.19.1': + '@prisma/get-platform@5.22.0': dependencies: - '@prisma/debug': 5.19.1 + '@prisma/debug': 5.22.0 - '@rollup/pluginutils@5.1.0(rollup@4.22.4)': + '@rollup/pluginutils@5.1.3(rollup@4.27.4)': dependencies: '@types/estree': 1.0.6 estree-walker: 2.0.2 - picomatch: 2.3.1 + picomatch: 4.0.2 optionalDependencies: - rollup: 4.22.4 + rollup: 4.27.4 + + '@rollup/rollup-android-arm-eabi@4.27.4': + optional: true + + '@rollup/rollup-android-arm64@4.27.4': + optional: true - '@rollup/rollup-android-arm-eabi@4.22.4': + '@rollup/rollup-darwin-arm64@4.27.4': optional: true - '@rollup/rollup-android-arm64@4.22.4': + '@rollup/rollup-darwin-x64@4.27.4': optional: true - '@rollup/rollup-darwin-arm64@4.22.4': + '@rollup/rollup-freebsd-arm64@4.27.4': optional: true - '@rollup/rollup-darwin-x64@4.22.4': + '@rollup/rollup-freebsd-x64@4.27.4': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.22.4': + '@rollup/rollup-linux-arm-gnueabihf@4.27.4': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.22.4': + '@rollup/rollup-linux-arm-musleabihf@4.27.4': optional: true - '@rollup/rollup-linux-arm64-gnu@4.22.4': + '@rollup/rollup-linux-arm64-gnu@4.27.4': optional: true - '@rollup/rollup-linux-arm64-musl@4.22.4': + '@rollup/rollup-linux-arm64-musl@4.27.4': optional: true - '@rollup/rollup-linux-powerpc64le-gnu@4.22.4': + '@rollup/rollup-linux-powerpc64le-gnu@4.27.4': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.22.4': + '@rollup/rollup-linux-riscv64-gnu@4.27.4': optional: true - '@rollup/rollup-linux-s390x-gnu@4.22.4': + '@rollup/rollup-linux-s390x-gnu@4.27.4': optional: true '@rollup/rollup-linux-x64-gnu@4.21.2': optional: true - '@rollup/rollup-linux-x64-gnu@4.22.4': + '@rollup/rollup-linux-x64-gnu@4.27.4': optional: true - '@rollup/rollup-linux-x64-musl@4.22.4': + '@rollup/rollup-linux-x64-musl@4.27.4': optional: true - '@rollup/rollup-win32-arm64-msvc@4.22.4': + '@rollup/rollup-win32-arm64-msvc@4.27.4': optional: true - '@rollup/rollup-win32-ia32-msvc@4.22.4': + '@rollup/rollup-win32-ia32-msvc@4.27.4': optional: true - '@rollup/rollup-win32-x64-msvc@4.22.4': + '@rollup/rollup-win32-x64-msvc@4.27.4': optional: true '@sinclair/typebox@0.27.8': {} @@ -3310,24 +3319,24 @@ snapshots: '@types/babel__core@7.20.5': dependencies: - '@babel/parser': 7.25.6 - '@babel/types': 7.25.6 + '@babel/parser': 7.26.2 + '@babel/types': 7.26.0 '@types/babel__generator': 7.6.8 '@types/babel__template': 7.4.4 '@types/babel__traverse': 7.20.6 '@types/babel__generator@7.6.8': dependencies: - '@babel/types': 7.25.6 + '@babel/types': 7.26.0 '@types/babel__template@7.4.4': dependencies: - '@babel/parser': 7.25.6 - '@babel/types': 7.25.6 + '@babel/parser': 7.26.2 + '@babel/types': 7.26.0 '@types/babel__traverse@7.20.6': dependencies: - '@babel/types': 7.25.6 + '@babel/types': 7.26.0 '@types/big.js@6.2.2': {} @@ -3335,7 +3344,7 @@ snapshots: dependencies: '@types/http-cache-semantics': 4.0.4 '@types/keyv': 3.1.4 - '@types/node': 20.16.6 + '@types/node': 20.17.7 '@types/responselike': 1.0.3 '@types/eslint@9.6.1': @@ -3347,13 +3356,11 @@ snapshots: dependencies: '@types/eslint': 9.6.1 - '@types/estree@1.0.5': {} - '@types/estree@1.0.6': {} '@types/graceful-fs@4.1.9': dependencies: - '@types/node': 20.16.6 + '@types/node': 20.17.7 '@types/http-cache-semantics@4.0.4': {} @@ -3367,7 +3374,7 @@ snapshots: dependencies: '@types/istanbul-lib-report': 3.0.3 - '@types/jest@29.5.13': + '@types/jest@29.5.14': dependencies: expect: 29.7.0 pretty-format: 29.7.0 @@ -3378,9 +3385,9 @@ snapshots: '@types/keyv@3.1.4': dependencies: - '@types/node': 20.16.6 + '@types/node': 20.17.7 - '@types/node@20.16.6': + '@types/node@20.17.7': dependencies: undici-types: 6.19.8 @@ -3388,7 +3395,7 @@ snapshots: '@types/responselike@1.0.3': dependencies: - '@types/node': 20.16.6 + '@types/node': 20.17.7 '@types/stack-utils@2.0.3': {} @@ -3398,96 +3405,97 @@ snapshots: dependencies: '@types/yargs-parser': 21.0.3 - '@typescript-eslint/eslint-plugin@8.6.0(@typescript-eslint/parser@8.6.0(eslint@9.11.0)(typescript@5.6.2))(eslint@9.11.0)(typescript@5.6.2)': + '@typescript-eslint/eslint-plugin@8.15.0(@typescript-eslint/parser@8.15.0(eslint@9.15.0)(typescript@5.7.2))(eslint@9.15.0)(typescript@5.7.2)': dependencies: - '@eslint-community/regexpp': 4.11.1 - '@typescript-eslint/parser': 8.6.0(eslint@9.11.0)(typescript@5.6.2) - '@typescript-eslint/scope-manager': 8.6.0 - '@typescript-eslint/type-utils': 8.6.0(eslint@9.11.0)(typescript@5.6.2) - '@typescript-eslint/utils': 8.6.0(eslint@9.11.0)(typescript@5.6.2) - '@typescript-eslint/visitor-keys': 8.6.0 - eslint: 9.11.0 + '@eslint-community/regexpp': 4.12.1 + '@typescript-eslint/parser': 8.15.0(eslint@9.15.0)(typescript@5.7.2) + '@typescript-eslint/scope-manager': 8.15.0 + '@typescript-eslint/type-utils': 8.15.0(eslint@9.15.0)(typescript@5.7.2) + '@typescript-eslint/utils': 8.15.0(eslint@9.15.0)(typescript@5.7.2) + '@typescript-eslint/visitor-keys': 8.15.0 + eslint: 9.15.0 graphemer: 1.4.0 ignore: 5.3.2 natural-compare: 1.4.0 - ts-api-utils: 1.3.0(typescript@5.6.2) + ts-api-utils: 1.4.1(typescript@5.7.2) optionalDependencies: - typescript: 5.6.2 + typescript: 5.7.2 transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.6.0(eslint@9.11.0)(typescript@5.6.2)': + '@typescript-eslint/parser@8.15.0(eslint@9.15.0)(typescript@5.7.2)': dependencies: - '@typescript-eslint/scope-manager': 8.6.0 - '@typescript-eslint/types': 8.6.0 - '@typescript-eslint/typescript-estree': 8.6.0(typescript@5.6.2) - '@typescript-eslint/visitor-keys': 8.6.0 + '@typescript-eslint/scope-manager': 8.15.0 + '@typescript-eslint/types': 8.15.0 + '@typescript-eslint/typescript-estree': 8.15.0(typescript@5.7.2) + '@typescript-eslint/visitor-keys': 8.15.0 debug: 4.3.7 - eslint: 9.11.0 + eslint: 9.15.0 optionalDependencies: - typescript: 5.6.2 + typescript: 5.7.2 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.6.0': + '@typescript-eslint/scope-manager@8.15.0': dependencies: - '@typescript-eslint/types': 8.6.0 - '@typescript-eslint/visitor-keys': 8.6.0 + '@typescript-eslint/types': 8.15.0 + '@typescript-eslint/visitor-keys': 8.15.0 - '@typescript-eslint/type-utils@8.6.0(eslint@9.11.0)(typescript@5.6.2)': + '@typescript-eslint/type-utils@8.15.0(eslint@9.15.0)(typescript@5.7.2)': dependencies: - '@typescript-eslint/typescript-estree': 8.6.0(typescript@5.6.2) - '@typescript-eslint/utils': 8.6.0(eslint@9.11.0)(typescript@5.6.2) + '@typescript-eslint/typescript-estree': 8.15.0(typescript@5.7.2) + '@typescript-eslint/utils': 8.15.0(eslint@9.15.0)(typescript@5.7.2) debug: 4.3.7 - ts-api-utils: 1.3.0(typescript@5.6.2) + eslint: 9.15.0 + ts-api-utils: 1.4.1(typescript@5.7.2) optionalDependencies: - typescript: 5.6.2 + typescript: 5.7.2 transitivePeerDependencies: - - eslint - supports-color - '@typescript-eslint/types@8.6.0': {} + '@typescript-eslint/types@8.15.0': {} - '@typescript-eslint/typescript-estree@8.6.0(typescript@5.6.2)': + '@typescript-eslint/typescript-estree@8.15.0(typescript@5.7.2)': dependencies: - '@typescript-eslint/types': 8.6.0 - '@typescript-eslint/visitor-keys': 8.6.0 + '@typescript-eslint/types': 8.15.0 + '@typescript-eslint/visitor-keys': 8.15.0 debug: 4.3.7 fast-glob: 3.3.2 is-glob: 4.0.3 minimatch: 9.0.5 semver: 7.6.3 - ts-api-utils: 1.3.0(typescript@5.6.2) + ts-api-utils: 1.4.1(typescript@5.7.2) optionalDependencies: - typescript: 5.6.2 + typescript: 5.7.2 transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.6.0(eslint@9.11.0)(typescript@5.6.2)': + '@typescript-eslint/utils@8.15.0(eslint@9.15.0)(typescript@5.7.2)': dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@9.11.0) - '@typescript-eslint/scope-manager': 8.6.0 - '@typescript-eslint/types': 8.6.0 - '@typescript-eslint/typescript-estree': 8.6.0(typescript@5.6.2) - eslint: 9.11.0 + '@eslint-community/eslint-utils': 4.4.1(eslint@9.15.0) + '@typescript-eslint/scope-manager': 8.15.0 + '@typescript-eslint/types': 8.15.0 + '@typescript-eslint/typescript-estree': 8.15.0(typescript@5.7.2) + eslint: 9.15.0 + optionalDependencies: + typescript: 5.7.2 transitivePeerDependencies: - supports-color - - typescript - '@typescript-eslint/visitor-keys@8.6.0': + '@typescript-eslint/visitor-keys@8.15.0': dependencies: - '@typescript-eslint/types': 8.6.0 - eslint-visitor-keys: 3.4.3 + '@typescript-eslint/types': 8.15.0 + eslint-visitor-keys: 4.2.0 - acorn-jsx@5.3.2(acorn@8.12.1): + acorn-jsx@5.3.2(acorn@8.14.0): dependencies: - acorn: 8.12.1 + acorn: 8.14.0 acorn-walk@8.3.4: dependencies: - acorn: 8.12.1 + acorn: 8.14.0 - acorn@8.12.1: {} + acorn@8.14.0: {} ajv@6.12.6: dependencies: @@ -3499,7 +3507,7 @@ snapshots: ajv@8.17.1: dependencies: fast-deep-equal: 3.1.3 - fast-uri: 3.0.1 + fast-uri: 3.0.3 json-schema-traverse: 1.0.0 require-from-string: 2.0.2 @@ -3511,10 +3519,6 @@ snapshots: ansi-regex@6.1.0: {} - ansi-styles@3.2.1: - dependencies: - color-convert: 1.9.3 - ansi-styles@4.3.0: dependencies: color-convert: 2.0.1 @@ -3538,21 +3542,21 @@ snapshots: asn1js@3.0.5: dependencies: - pvtsutils: 1.3.5 + pvtsutils: 1.3.6 pvutils: 1.1.3 - tslib: 2.7.0 + tslib: 2.8.1 async@3.2.6: {} asynckit@0.4.0: {} - babel-jest@29.7.0(@babel/core@7.25.2): + babel-jest@29.7.0(@babel/core@7.26.0): dependencies: - '@babel/core': 7.25.2 + '@babel/core': 7.26.0 '@jest/transform': 29.7.0 '@types/babel__core': 7.20.5 babel-plugin-istanbul: 6.1.1 - babel-preset-jest: 29.6.3(@babel/core@7.25.2) + babel-preset-jest: 29.6.3(@babel/core@7.26.0) chalk: 4.1.2 graceful-fs: 4.2.11 slash: 3.0.0 @@ -3561,7 +3565,7 @@ snapshots: babel-plugin-istanbul@6.1.1: dependencies: - '@babel/helper-plugin-utils': 7.24.8 + '@babel/helper-plugin-utils': 7.25.9 '@istanbuljs/load-nyc-config': 1.1.0 '@istanbuljs/schema': 0.1.3 istanbul-lib-instrument: 5.2.1 @@ -3571,35 +3575,35 @@ snapshots: babel-plugin-jest-hoist@29.6.3: dependencies: - '@babel/template': 7.25.0 - '@babel/types': 7.25.6 + '@babel/template': 7.25.9 + '@babel/types': 7.26.0 '@types/babel__core': 7.20.5 '@types/babel__traverse': 7.20.6 - babel-preset-current-node-syntax@1.1.0(@babel/core@7.25.2): - dependencies: - '@babel/core': 7.25.2 - '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.25.2) - '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.25.2) - '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.25.2) - '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.25.2) - '@babel/plugin-syntax-import-attributes': 7.25.6(@babel/core@7.25.2) - '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.25.2) - '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.25.2) - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.25.2) - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.25.2) - '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.25.2) - '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.25.2) - '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.25.2) - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.25.2) - '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.25.2) - '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.25.2) - - babel-preset-jest@29.6.3(@babel/core@7.25.2): - dependencies: - '@babel/core': 7.25.2 + babel-preset-current-node-syntax@1.1.0(@babel/core@7.26.0): + dependencies: + '@babel/core': 7.26.0 + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.26.0) + '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.26.0) + '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.26.0) + '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.26.0) + '@babel/plugin-syntax-import-attributes': 7.26.0(@babel/core@7.26.0) + '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.26.0) + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.26.0) + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.26.0) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.26.0) + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.26.0) + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.26.0) + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.26.0) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.26.0) + '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.26.0) + '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.26.0) + + babel-preset-jest@29.6.3(@babel/core@7.26.0): + dependencies: + '@babel/core': 7.26.0 babel-plugin-jest-hoist: 29.6.3 - babel-preset-current-node-syntax: 1.1.0(@babel/core@7.25.2) + babel-preset-current-node-syntax: 1.1.0(@babel/core@7.26.0) balanced-match@1.0.2: {} @@ -3635,12 +3639,12 @@ snapshots: dependencies: fill-range: 7.1.1 - browserslist@4.23.3: + browserslist@4.24.2: dependencies: - caniuse-lite: 1.0.30001662 - electron-to-chromium: 1.5.27 + caniuse-lite: 1.0.30001684 + electron-to-chromium: 1.5.64 node-releases: 2.0.18 - update-browserslist-db: 1.1.0(browserslist@4.23.3) + update-browserslist-db: 1.1.1(browserslist@4.24.2) bs-logger@0.2.6: dependencies: @@ -3677,18 +3681,12 @@ snapshots: camelcase@6.3.0: {} - caniuse-lite@1.0.30001662: {} + caniuse-lite@1.0.30001684: {} - cbor@8.1.0: + cbor@9.0.2: dependencies: nofilter: 3.1.0 - chalk@2.4.2: - dependencies: - ansi-styles: 3.2.1 - escape-string-regexp: 1.0.5 - supports-color: 5.5.0 - chalk@4.1.2: dependencies: ansi-styles: 4.3.0 @@ -3698,7 +3696,7 @@ snapshots: ci-info@3.9.0: {} - ci-info@4.0.0: {} + ci-info@4.1.0: {} cjs-module-lexer@1.4.1: {} @@ -3722,16 +3720,10 @@ snapshots: collect-v8-coverage@1.0.2: {} - color-convert@1.9.3: - dependencies: - color-name: 1.1.3 - color-convert@2.0.1: dependencies: color-name: 1.1.4 - color-name@1.1.3: {} - color-name@1.1.4: {} combined-stream@1.0.8: @@ -3742,17 +3734,17 @@ snapshots: convert-source-map@2.0.0: {} - core-js-compat@3.38.1: + core-js-compat@3.39.0: dependencies: - browserslist: 4.23.3 + browserslist: 4.24.2 - create-jest@29.7.0(@types/node@20.16.6)(ts-node@10.9.2(@types/node@20.16.6)(typescript@5.6.2)): + create-jest@29.7.0(@types/node@20.17.7)(ts-node@10.9.2(@types/node@20.17.7)(typescript@5.7.2)): dependencies: '@jest/types': 29.6.3 chalk: 4.1.2 exit: 0.1.2 graceful-fs: 4.2.11 - jest-config: 29.7.0(@types/node@20.16.6)(ts-node@10.9.2(@types/node@20.16.6)(typescript@5.6.2)) + jest-config: 29.7.0(@types/node@20.17.7)(ts-node@10.9.2(@types/node@20.17.7)(typescript@5.7.2)) jest-util: 29.7.0 prompts: 2.4.2 transitivePeerDependencies: @@ -3769,7 +3761,7 @@ snapshots: transitivePeerDependencies: - encoding - cross-spawn@7.0.3: + cross-spawn@7.0.6: dependencies: path-key: 3.1.1 shebang-command: 2.0.0 @@ -3809,7 +3801,7 @@ snapshots: dependencies: jake: 10.9.2 - electron-to-chromium@1.5.27: {} + electron-to-chromium@1.5.64: {} emittery@0.13.1: {} @@ -3862,20 +3854,20 @@ snapshots: escape-string-regexp@4.0.0: {} - eslint-plugin-simple-import-sort@12.1.1(eslint@9.11.0): + eslint-plugin-simple-import-sort@12.1.1(eslint@9.15.0): dependencies: - eslint: 9.11.0 + eslint: 9.15.0 - eslint-plugin-unicorn@55.0.0(eslint@9.11.0): + eslint-plugin-unicorn@55.0.0(eslint@9.15.0): dependencies: - '@babel/helper-validator-identifier': 7.24.7 - '@eslint-community/eslint-utils': 4.4.0(eslint@9.11.0) - ci-info: 4.0.0 + '@babel/helper-validator-identifier': 7.25.9 + '@eslint-community/eslint-utils': 4.4.1(eslint@9.15.0) + ci-info: 4.1.0 clean-regexp: 1.0.0 - core-js-compat: 3.38.1 - eslint: 9.11.0 + core-js-compat: 3.39.0 + eslint: 9.15.0 esquery: 1.6.0 - globals: 15.9.0 + globals: 15.12.0 indent-string: 4.0.0 is-builtin-module: 3.2.1 jsesc: 3.0.2 @@ -3886,40 +3878,43 @@ snapshots: semver: 7.6.3 strip-indent: 3.0.0 - eslint-plugin-unused-imports@4.1.4(@typescript-eslint/eslint-plugin@8.6.0(@typescript-eslint/parser@8.6.0(eslint@9.11.0)(typescript@5.6.2))(eslint@9.11.0)(typescript@5.6.2))(eslint@9.11.0): + eslint-plugin-unused-imports@4.1.4(@typescript-eslint/eslint-plugin@8.15.0(@typescript-eslint/parser@8.15.0(eslint@9.15.0)(typescript@5.7.2))(eslint@9.15.0)(typescript@5.7.2))(eslint@9.15.0): dependencies: - eslint: 9.11.0 + eslint: 9.15.0 optionalDependencies: - '@typescript-eslint/eslint-plugin': 8.6.0(@typescript-eslint/parser@8.6.0(eslint@9.11.0)(typescript@5.6.2))(eslint@9.11.0)(typescript@5.6.2) + '@typescript-eslint/eslint-plugin': 8.15.0(@typescript-eslint/parser@8.15.0(eslint@9.15.0)(typescript@5.7.2))(eslint@9.15.0)(typescript@5.7.2) - eslint-scope@8.0.2: + eslint-scope@8.2.0: dependencies: esrecurse: 4.3.0 estraverse: 5.3.0 eslint-visitor-keys@3.4.3: {} - eslint-visitor-keys@4.0.0: {} + eslint-visitor-keys@4.2.0: {} - eslint@9.11.0: + eslint@9.15.0: dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@9.11.0) - '@eslint-community/regexpp': 4.11.1 - '@eslint/config-array': 0.18.0 - '@eslint/eslintrc': 3.1.0 - '@eslint/js': 9.11.0 - '@eslint/plugin-kit': 0.2.0 + '@eslint-community/eslint-utils': 4.4.1(eslint@9.15.0) + '@eslint-community/regexpp': 4.12.1 + '@eslint/config-array': 0.19.0 + '@eslint/core': 0.9.0 + '@eslint/eslintrc': 3.2.0 + '@eslint/js': 9.15.0 + '@eslint/plugin-kit': 0.2.3 + '@humanfs/node': 0.16.6 '@humanwhocodes/module-importer': 1.0.1 - '@humanwhocodes/retry': 0.3.0 - '@nodelib/fs.walk': 1.2.8 + '@humanwhocodes/retry': 0.4.1 + '@types/estree': 1.0.6 + '@types/json-schema': 7.0.15 ajv: 6.12.6 chalk: 4.1.2 - cross-spawn: 7.0.3 + cross-spawn: 7.0.6 debug: 4.3.7 escape-string-regexp: 4.0.0 - eslint-scope: 8.0.2 - eslint-visitor-keys: 4.0.0 - espree: 10.1.0 + eslint-scope: 8.2.0 + eslint-visitor-keys: 4.2.0 + espree: 10.3.0 esquery: 1.6.0 esutils: 2.0.3 fast-deep-equal: 3.1.3 @@ -3929,22 +3924,19 @@ snapshots: ignore: 5.3.2 imurmurhash: 0.1.4 is-glob: 4.0.3 - is-path-inside: 3.0.3 json-stable-stringify-without-jsonify: 1.0.1 lodash.merge: 4.6.2 minimatch: 3.1.2 natural-compare: 1.4.0 optionator: 0.9.4 - strip-ansi: 6.0.1 - text-table: 0.2.0 transitivePeerDependencies: - supports-color - espree@10.1.0: + espree@10.3.0: dependencies: - acorn: 8.12.1 - acorn-jsx: 5.3.2(acorn@8.12.1) - eslint-visitor-keys: 4.0.0 + acorn: 8.14.0 + acorn-jsx: 5.3.2(acorn@8.14.0) + eslint-visitor-keys: 4.2.0 esprima@4.0.1: {} @@ -3964,7 +3956,7 @@ snapshots: execa@5.1.1: dependencies: - cross-spawn: 7.0.3 + cross-spawn: 7.0.6 get-stream: 6.0.1 human-signals: 2.1.0 is-stream: 2.0.1 @@ -4000,7 +3992,7 @@ snapshots: fast-levenshtein@2.0.6: {} - fast-uri@3.0.1: {} + fast-uri@3.0.3: {} fastq@1.17.1: dependencies: @@ -4039,17 +4031,17 @@ snapshots: flat-cache@4.0.1: dependencies: - flatted: 3.3.1 + flatted: 3.3.2 keyv: 4.5.4 - flatted@3.3.1: {} + flatted@3.3.2: {} foreground-child@3.3.0: dependencies: - cross-spawn: 7.0.3 + cross-spawn: 7.0.6 signal-exit: 4.1.0 - form-data@4.0.0: + form-data@4.0.1: dependencies: asynckit: 0.4.0 combined-stream: 1.0.8 @@ -4093,10 +4085,10 @@ snapshots: glob@11.0.0: dependencies: foreground-child: 3.3.0 - jackspeak: 4.0.1 + jackspeak: 4.0.2 minimatch: 10.0.1 minipass: 7.1.2 - package-json-from-dist: 1.0.0 + package-json-from-dist: 1.0.1 path-scurry: 2.0.0 glob@7.2.3: @@ -4112,7 +4104,7 @@ snapshots: globals@14.0.0: {} - globals@15.9.0: {} + globals@15.12.0: {} got@11.8.6: dependencies: @@ -4132,8 +4124,6 @@ snapshots: graphemer@1.4.0: {} - has-flag@3.0.0: {} - has-flag@4.0.0: {} hasown@2.0.2: @@ -4214,8 +4204,6 @@ snapshots: is-number@7.0.0: {} - is-path-inside@3.0.3: {} - is-stream@2.0.1: {} isexe@2.0.0: {} @@ -4228,8 +4216,8 @@ snapshots: istanbul-lib-instrument@5.2.1: dependencies: - '@babel/core': 7.25.2 - '@babel/parser': 7.25.6 + '@babel/core': 7.26.0 + '@babel/parser': 7.26.2 '@istanbuljs/schema': 0.1.3 istanbul-lib-coverage: 3.2.2 semver: 6.3.1 @@ -4238,8 +4226,8 @@ snapshots: istanbul-lib-instrument@6.0.3: dependencies: - '@babel/core': 7.25.2 - '@babel/parser': 7.25.6 + '@babel/core': 7.26.0 + '@babel/parser': 7.26.2 '@istanbuljs/schema': 0.1.3 istanbul-lib-coverage: 3.2.2 semver: 7.6.3 @@ -4265,11 +4253,9 @@ snapshots: html-escaper: 2.0.2 istanbul-lib-report: 3.0.1 - jackspeak@4.0.1: + jackspeak@4.0.2: dependencies: '@isaacs/cliui': 8.0.2 - optionalDependencies: - '@pkgjs/parseargs': 0.11.0 jake@10.9.2: dependencies: @@ -4290,7 +4276,7 @@ snapshots: '@jest/expect': 29.7.0 '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.16.6 + '@types/node': 20.17.7 chalk: 4.1.2 co: 4.6.0 dedent: 1.5.3 @@ -4310,16 +4296,16 @@ snapshots: - babel-plugin-macros - supports-color - jest-cli@29.7.0(@types/node@20.16.6)(ts-node@10.9.2(@types/node@20.16.6)(typescript@5.6.2)): + jest-cli@29.7.0(@types/node@20.17.7)(ts-node@10.9.2(@types/node@20.17.7)(typescript@5.7.2)): dependencies: - '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@20.16.6)(typescript@5.6.2)) + '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@20.17.7)(typescript@5.7.2)) '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 chalk: 4.1.2 - create-jest: 29.7.0(@types/node@20.16.6)(ts-node@10.9.2(@types/node@20.16.6)(typescript@5.6.2)) + create-jest: 29.7.0(@types/node@20.17.7)(ts-node@10.9.2(@types/node@20.17.7)(typescript@5.7.2)) exit: 0.1.2 import-local: 3.2.0 - jest-config: 29.7.0(@types/node@20.16.6)(ts-node@10.9.2(@types/node@20.16.6)(typescript@5.6.2)) + jest-config: 29.7.0(@types/node@20.17.7)(ts-node@10.9.2(@types/node@20.17.7)(typescript@5.7.2)) jest-util: 29.7.0 jest-validate: 29.7.0 yargs: 17.7.2 @@ -4329,12 +4315,12 @@ snapshots: - supports-color - ts-node - jest-config@29.7.0(@types/node@20.16.6)(ts-node@10.9.2(@types/node@20.16.6)(typescript@5.6.2)): + jest-config@29.7.0(@types/node@20.17.7)(ts-node@10.9.2(@types/node@20.17.7)(typescript@5.7.2)): dependencies: - '@babel/core': 7.25.2 + '@babel/core': 7.26.0 '@jest/test-sequencer': 29.7.0 '@jest/types': 29.6.3 - babel-jest: 29.7.0(@babel/core@7.25.2) + babel-jest: 29.7.0(@babel/core@7.26.0) chalk: 4.1.2 ci-info: 3.9.0 deepmerge: 4.3.1 @@ -4354,8 +4340,8 @@ snapshots: slash: 3.0.0 strip-json-comments: 3.1.1 optionalDependencies: - '@types/node': 20.16.6 - ts-node: 10.9.2(@types/node@20.16.6)(typescript@5.6.2) + '@types/node': 20.17.7 + ts-node: 10.9.2(@types/node@20.17.7)(typescript@5.7.2) transitivePeerDependencies: - babel-plugin-macros - supports-color @@ -4384,7 +4370,7 @@ snapshots: '@jest/environment': 29.7.0 '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.16.6 + '@types/node': 20.17.7 jest-mock: 29.7.0 jest-util: 29.7.0 @@ -4394,7 +4380,7 @@ snapshots: dependencies: '@jest/types': 29.6.3 '@types/graceful-fs': 4.1.9 - '@types/node': 20.16.6 + '@types/node': 20.17.7 anymatch: 3.1.3 fb-watchman: 2.0.2 graceful-fs: 4.2.11 @@ -4420,7 +4406,7 @@ snapshots: jest-message-util@29.7.0: dependencies: - '@babel/code-frame': 7.24.7 + '@babel/code-frame': 7.26.2 '@jest/types': 29.6.3 '@types/stack-utils': 2.0.3 chalk: 4.1.2 @@ -4433,7 +4419,7 @@ snapshots: jest-mock@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 20.16.6 + '@types/node': 20.17.7 jest-util: 29.7.0 jest-pnp-resolver@1.2.3(jest-resolve@29.7.0): @@ -4468,7 +4454,7 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.16.6 + '@types/node': 20.17.7 chalk: 4.1.2 emittery: 0.13.1 graceful-fs: 4.2.11 @@ -4496,7 +4482,7 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.16.6 + '@types/node': 20.17.7 chalk: 4.1.2 cjs-module-lexer: 1.4.1 collect-v8-coverage: 1.0.2 @@ -4516,15 +4502,15 @@ snapshots: jest-snapshot@29.7.0: dependencies: - '@babel/core': 7.25.2 - '@babel/generator': 7.25.6 - '@babel/plugin-syntax-jsx': 7.24.7(@babel/core@7.25.2) - '@babel/plugin-syntax-typescript': 7.25.4(@babel/core@7.25.2) - '@babel/types': 7.25.6 + '@babel/core': 7.26.0 + '@babel/generator': 7.26.2 + '@babel/plugin-syntax-jsx': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-syntax-typescript': 7.25.9(@babel/core@7.26.0) + '@babel/types': 7.26.0 '@jest/expect-utils': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - babel-preset-current-node-syntax: 1.1.0(@babel/core@7.25.2) + babel-preset-current-node-syntax: 1.1.0(@babel/core@7.26.0) chalk: 4.1.2 expect: 29.7.0 graceful-fs: 4.2.11 @@ -4542,7 +4528,7 @@ snapshots: jest-util@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 20.16.6 + '@types/node': 20.17.7 chalk: 4.1.2 ci-info: 3.9.0 graceful-fs: 4.2.11 @@ -4561,7 +4547,7 @@ snapshots: dependencies: '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.16.6 + '@types/node': 20.17.7 ansi-escapes: 4.3.2 chalk: 4.1.2 emittery: 0.13.1 @@ -4570,17 +4556,17 @@ snapshots: jest-worker@29.7.0: dependencies: - '@types/node': 20.16.6 + '@types/node': 20.17.7 jest-util: 29.7.0 merge-stream: 2.0.0 supports-color: 8.1.1 - jest@29.7.0(@types/node@20.16.6)(ts-node@10.9.2(@types/node@20.16.6)(typescript@5.6.2)): + jest@29.7.0(@types/node@20.17.7)(ts-node@10.9.2(@types/node@20.17.7)(typescript@5.7.2)): dependencies: - '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@20.16.6)(typescript@5.6.2)) + '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@20.17.7)(typescript@5.7.2)) '@jest/types': 29.6.3 import-local: 3.2.0 - jest-cli: 29.7.0(@types/node@20.16.6)(ts-node@10.9.2(@types/node@20.16.6)(typescript@5.6.2)) + jest-cli: 29.7.0(@types/node@20.17.7)(ts-node@10.9.2(@types/node@20.17.7)(typescript@5.7.2)) transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -4600,8 +4586,6 @@ snapshots: jsesc@0.5.0: {} - jsesc@2.5.2: {} - jsesc@3.0.2: {} json-bigint@1.0.0: @@ -4653,22 +4637,13 @@ snapshots: lowercase-keys@2.0.0: {} - lru-cache@11.0.1: {} + lru-cache@11.0.2: {} lru-cache@5.1.1: dependencies: yallist: 3.1.1 - lucid-cardano@0.10.10: - dependencies: - '@peculiar/webcrypto': 1.5.0 - node-fetch: 3.3.2 - ws: 8.18.0 - transitivePeerDependencies: - - bufferutil - - utf-8-validate - - magic-string@0.30.11: + magic-string@0.30.13: dependencies: '@jridgewell/sourcemap-codec': 1.5.0 @@ -4801,7 +4776,7 @@ snapshots: p-try@2.2.0: {} - package-json-from-dist@1.0.0: {} + package-json-from-dist@1.0.1: {} parent-module@1.0.1: dependencies: @@ -4809,7 +4784,7 @@ snapshots: parse-json@5.2.0: dependencies: - '@babel/code-frame': 7.24.7 + '@babel/code-frame': 7.26.2 error-ex: 1.3.2 json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 @@ -4824,13 +4799,15 @@ snapshots: path-scurry@2.0.0: dependencies: - lru-cache: 11.0.1 + lru-cache: 11.0.2 minipass: 7.1.2 - picocolors@1.1.0: {} + picocolors@1.1.1: {} picomatch@2.3.1: {} + picomatch@4.0.2: {} + pirates@4.0.6: {} pkg-dir@4.2.0: @@ -4849,9 +4826,9 @@ snapshots: ansi-styles: 5.2.0 react-is: 18.3.1 - prisma@5.19.1: + prisma@5.22.0: dependencies: - '@prisma/engines': 5.19.1 + '@prisma/engines': 5.22.0 optionalDependencies: fsevents: 2.3.3 @@ -4869,9 +4846,9 @@ snapshots: pure-rand@6.1.0: {} - pvtsutils@1.3.5: + pvtsutils@1.3.6: dependencies: - tslib: 2.7.0 + tslib: 2.8.1 pvutils@1.1.3: {} @@ -4906,9 +4883,9 @@ snapshots: dependencies: jsesc: 0.5.0 - remeda@2.14.0: + remeda@2.17.3: dependencies: - type-fest: 4.26.1 + type-fest: 4.28.0 require-directory@2.1.1: {} @@ -4943,47 +4920,49 @@ snapshots: rimraf@6.0.1: dependencies: glob: 11.0.0 - package-json-from-dist: 1.0.0 + package-json-from-dist: 1.0.1 - rollup-plugin-dts@6.1.1(rollup@4.22.4)(typescript@5.6.2): + rollup-plugin-dts@6.1.1(rollup@4.27.4)(typescript@5.7.2): dependencies: - magic-string: 0.30.11 - rollup: 4.22.4 - typescript: 5.6.2 + magic-string: 0.30.13 + rollup: 4.27.4 + typescript: 5.7.2 optionalDependencies: - '@babel/code-frame': 7.24.7 + '@babel/code-frame': 7.26.2 - rollup-plugin-esbuild@6.1.1(esbuild@0.23.1)(rollup@4.22.4): + rollup-plugin-esbuild@6.1.1(esbuild@0.23.1)(rollup@4.27.4): dependencies: - '@rollup/pluginutils': 5.1.0(rollup@4.22.4) + '@rollup/pluginutils': 5.1.3(rollup@4.27.4) debug: 4.3.7 es-module-lexer: 1.5.4 esbuild: 0.23.1 get-tsconfig: 4.8.1 - rollup: 4.22.4 + rollup: 4.27.4 transitivePeerDependencies: - supports-color - rollup@4.22.4: + rollup@4.27.4: dependencies: - '@types/estree': 1.0.5 + '@types/estree': 1.0.6 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.22.4 - '@rollup/rollup-android-arm64': 4.22.4 - '@rollup/rollup-darwin-arm64': 4.22.4 - '@rollup/rollup-darwin-x64': 4.22.4 - '@rollup/rollup-linux-arm-gnueabihf': 4.22.4 - '@rollup/rollup-linux-arm-musleabihf': 4.22.4 - '@rollup/rollup-linux-arm64-gnu': 4.22.4 - '@rollup/rollup-linux-arm64-musl': 4.22.4 - '@rollup/rollup-linux-powerpc64le-gnu': 4.22.4 - '@rollup/rollup-linux-riscv64-gnu': 4.22.4 - '@rollup/rollup-linux-s390x-gnu': 4.22.4 - '@rollup/rollup-linux-x64-gnu': 4.22.4 - '@rollup/rollup-linux-x64-musl': 4.22.4 - '@rollup/rollup-win32-arm64-msvc': 4.22.4 - '@rollup/rollup-win32-ia32-msvc': 4.22.4 - '@rollup/rollup-win32-x64-msvc': 4.22.4 + '@rollup/rollup-android-arm-eabi': 4.27.4 + '@rollup/rollup-android-arm64': 4.27.4 + '@rollup/rollup-darwin-arm64': 4.27.4 + '@rollup/rollup-darwin-x64': 4.27.4 + '@rollup/rollup-freebsd-arm64': 4.27.4 + '@rollup/rollup-freebsd-x64': 4.27.4 + '@rollup/rollup-linux-arm-gnueabihf': 4.27.4 + '@rollup/rollup-linux-arm-musleabihf': 4.27.4 + '@rollup/rollup-linux-arm64-gnu': 4.27.4 + '@rollup/rollup-linux-arm64-musl': 4.27.4 + '@rollup/rollup-linux-powerpc64le-gnu': 4.27.4 + '@rollup/rollup-linux-riscv64-gnu': 4.27.4 + '@rollup/rollup-linux-s390x-gnu': 4.27.4 + '@rollup/rollup-linux-x64-gnu': 4.27.4 + '@rollup/rollup-linux-x64-musl': 4.27.4 + '@rollup/rollup-win32-arm64-msvc': 4.27.4 + '@rollup/rollup-win32-ia32-msvc': 4.27.4 + '@rollup/rollup-win32-x64-msvc': 4.27.4 fsevents: 2.3.3 run-parallel@1.2.0: @@ -5078,10 +5057,6 @@ snapshots: strip-json-comments@3.1.1: {} - supports-color@5.5.0: - dependencies: - has-flag: 3.0.0 - supports-color@7.2.0: dependencies: has-flag: 4.0.0 @@ -5098,63 +5073,66 @@ snapshots: glob: 7.2.3 minimatch: 3.1.2 - text-table@0.2.0: {} - tmpl@1.0.5: {} - to-fast-properties@2.0.0: {} - to-regex-range@5.0.1: dependencies: is-number: 7.0.0 tr46@0.0.3: {} - ts-api-utils@1.3.0(typescript@5.6.2): + ts-api-utils@1.4.1(typescript@5.7.2): dependencies: - typescript: 5.6.2 + typescript: 5.7.2 ts-custom-error@3.3.1: {} - ts-jest@29.2.5(@babel/core@7.25.2)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.25.2))(esbuild@0.23.1)(jest@29.7.0(@types/node@20.16.6)(ts-node@10.9.2(@types/node@20.16.6)(typescript@5.6.2)))(typescript@5.6.2): + ts-jest@29.2.5(@babel/core@7.26.0)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.26.0))(esbuild@0.23.1)(jest@29.7.0(@types/node@20.17.7)(ts-node@10.9.2(@types/node@20.17.7)(typescript@5.7.2)))(typescript@5.7.2): dependencies: bs-logger: 0.2.6 ejs: 3.1.10 fast-json-stable-stringify: 2.1.0 - jest: 29.7.0(@types/node@20.16.6)(ts-node@10.9.2(@types/node@20.16.6)(typescript@5.6.2)) + jest: 29.7.0(@types/node@20.17.7)(ts-node@10.9.2(@types/node@20.17.7)(typescript@5.7.2)) jest-util: 29.7.0 json5: 2.2.3 lodash.memoize: 4.1.2 make-error: 1.3.6 semver: 7.6.3 - typescript: 5.6.2 + typescript: 5.7.2 yargs-parser: 21.1.1 optionalDependencies: - '@babel/core': 7.25.2 + '@babel/core': 7.26.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - babel-jest: 29.7.0(@babel/core@7.25.2) + babel-jest: 29.7.0(@babel/core@7.26.0) esbuild: 0.23.1 - ts-node@10.9.2(@types/node@20.16.6)(typescript@5.6.2): + ts-node@10.9.2(@types/node@20.17.7)(typescript@5.7.2): dependencies: '@cspotcode/source-map-support': 0.8.1 '@tsconfig/node10': 1.0.11 '@tsconfig/node12': 1.0.11 '@tsconfig/node14': 1.0.3 '@tsconfig/node16': 1.0.4 - '@types/node': 20.16.6 - acorn: 8.12.1 + '@types/node': 20.17.7 + acorn: 8.14.0 acorn-walk: 8.3.4 arg: 4.1.3 create-require: 1.1.1 diff: 4.0.2 make-error: 1.3.6 - typescript: 5.6.2 + typescript: 5.7.2 v8-compile-cache-lib: 3.0.1 yn: 3.1.1 - tslib@2.7.0: {} + tslib@2.8.1: {} + + tsx@4.19.2: + dependencies: + esbuild: 0.23.1 + get-tsconfig: 4.8.1 + optionalDependencies: + fsevents: 2.3.3 type-check@0.4.0: dependencies: @@ -5168,28 +5146,28 @@ snapshots: type-fest@0.8.1: {} - type-fest@4.26.1: {} + type-fest@4.28.0: {} - typescript-eslint@8.6.0(eslint@9.11.0)(typescript@5.6.2): + typescript-eslint@8.15.0(eslint@9.15.0)(typescript@5.7.2): dependencies: - '@typescript-eslint/eslint-plugin': 8.6.0(@typescript-eslint/parser@8.6.0(eslint@9.11.0)(typescript@5.6.2))(eslint@9.11.0)(typescript@5.6.2) - '@typescript-eslint/parser': 8.6.0(eslint@9.11.0)(typescript@5.6.2) - '@typescript-eslint/utils': 8.6.0(eslint@9.11.0)(typescript@5.6.2) + '@typescript-eslint/eslint-plugin': 8.15.0(@typescript-eslint/parser@8.15.0(eslint@9.15.0)(typescript@5.7.2))(eslint@9.15.0)(typescript@5.7.2) + '@typescript-eslint/parser': 8.15.0(eslint@9.15.0)(typescript@5.7.2) + '@typescript-eslint/utils': 8.15.0(eslint@9.15.0)(typescript@5.7.2) + eslint: 9.15.0 optionalDependencies: - typescript: 5.6.2 + typescript: 5.7.2 transitivePeerDependencies: - - eslint - supports-color - typescript@5.6.2: {} + typescript@5.7.2: {} undici-types@6.19.8: {} - update-browserslist-db@1.1.0(browserslist@4.23.3): + update-browserslist-db@1.1.1(browserslist@4.24.2): dependencies: - browserslist: 4.23.3 + browserslist: 4.24.2 escalade: 3.2.0 - picocolors: 1.1.0 + picocolors: 1.1.1 uri-js@4.4.1: dependencies: @@ -5214,13 +5192,13 @@ snapshots: web-streams-polyfill@3.3.3: {} - webcrypto-core@1.8.0: + webcrypto-core@1.8.1: dependencies: '@peculiar/asn1-schema': 2.3.13 '@peculiar/json-schema': 1.1.12 asn1js: 3.0.5 - pvtsutils: 1.3.5 - tslib: 2.7.0 + pvtsutils: 1.3.6 + tslib: 2.8.1 webidl-conversions@3.0.1: {} @@ -5262,7 +5240,7 @@ snapshots: yallist@3.1.1: {} - yaml@2.5.1: {} + yaml@2.6.1: {} yargs-parser@21.1.1: {} diff --git a/src/adapter.ts b/src/adapter.ts index 58954bb..9fabb77 100644 --- a/src/adapter.ts +++ b/src/adapter.ts @@ -4,16 +4,17 @@ import { Responses, } from "@blockfrost/blockfrost-js"; import { PaginationOptions } from "@blockfrost/blockfrost-js/lib/types"; -import invariant from "@minswap/tiny-invariant"; -import * as Prisma from "@prisma/client"; -import Big from "big.js"; -import JSONBig from "json-bigint"; import { + Address, C, fromHex, SLOT_CONFIG_NETWORK, slotToBeginUnixTime, -} from "lucid-cardano"; +} from "@minswap/lucid-cardano"; +import invariant from "@minswap/tiny-invariant"; +import * as Prisma from "@prisma/client"; +import Big from "big.js"; +import JSONBig from "json-bigint"; import { StableswapCalculation } from "./calculate"; import { PostgresRepositoryReader } from "./syncer/repository/postgres-repository"; @@ -21,10 +22,13 @@ import { Asset } from "./types/asset"; import { DexV1Constant, DexV2Constant, + LbeV2Constant, StableswapConstant, } from "./types/constants"; import { FactoryV2 } from "./types/factory"; +import { LbeV2Types } from "./types/lbe-v2"; import { NetworkEnvironment, NetworkId } from "./types/network"; +import { OrderV2 } from "./types/order"; import { PoolV1, PoolV2, StablePool } from "./types/pool"; import { checkValidPoolOutput, @@ -90,6 +94,8 @@ interface Adapter { getDatumByDatumHash(datumHash: string): Promise; + currentSlot(): Promise; + /** * Get pool state in a transaction. * @param {Object} params - The parameters. @@ -179,6 +185,58 @@ interface Adapter { * @returns {[string, string]} - Returns price of @assetA agains @assetB */ getStablePoolPrice(params: GetStablePoolPriceParams): Big; + + getAllLbeV2Factories(): Promise<{ + factories: LbeV2Types.FactoryState[]; + errors: unknown[]; + }>; + + getLbeV2Factory( + baseAsset: Asset, + raiseAsset: Asset + ): Promise; + + getLbeV2HeadAndTailFactory(lbeId: string): Promise<{ + head: LbeV2Types.FactoryState; + tail: LbeV2Types.FactoryState; + } | null>; + + getAllLbeV2Treasuries(): Promise<{ + treasuries: LbeV2Types.TreasuryState[]; + errors: unknown[]; + }>; + + getLbeV2TreasuryByLbeId( + lbeId: string + ): Promise; + + getAllLbeV2Managers(): Promise<{ + managers: LbeV2Types.ManagerState[]; + errors: unknown[]; + }>; + + getLbeV2ManagerByLbeId( + lbeId: string + ): Promise; + + getAllLbeV2Sellers(): Promise<{ + sellers: LbeV2Types.SellerState[]; + errors: unknown[]; + }>; + + getLbeV2SellerByLbeId(lbeId: string): Promise; + + getAllLbeV2Orders(): Promise<{ + orders: LbeV2Types.OrderState[]; + errors: unknown[]; + }>; + + getLbeV2OrdersByLbeId(lbeId: string): Promise; + + getLbeV2OrdersByLbeIdAndOwner( + lbeId: string, + owner: Address + ): Promise; } export class BlockfrostAdapter implements Adapter { @@ -210,6 +268,12 @@ export class BlockfrostAdapter implements Adapter { return scriptsDatum.cbor; } + public async currentSlot(): Promise { + const latestBlock = await this.blockFrostApi.blocksLatest(); + return latestBlock.slot ?? 0; + } + + // MARK: DEX V1 public async getV1PoolInTx({ txHash, }: GetPoolInTxParams): Promise { @@ -324,6 +388,7 @@ export class BlockfrostAdapter implements Adapter { return [priceAB, priceBA]; } + // MARK: DEX V2 public async getAllV2Pools(): Promise<{ pools: PoolV2.State[]; errors: unknown[]; @@ -507,6 +572,57 @@ export class BlockfrostAdapter implements Adapter { return null; } + public async getAllV2Orders(): Promise<{ + orders: OrderV2.State[]; + errors: unknown[]; + }> { + const v2Config = DexV2Constant.CONFIG[this.networkId]; + const utxos = await this.blockFrostApi.addressesUtxosAll( + v2Config.orderScriptHashBech32 + ); + + const orders: OrderV2.State[] = []; + const errors: unknown[] = []; + for (const utxo of utxos) { + try { + let order: OrderV2.State | undefined = undefined; + if (utxo.inline_datum !== null) { + order = new OrderV2.State( + this.networkId, + utxo.address, + { txHash: utxo.tx_hash, index: utxo.output_index }, + utxo.amount, + utxo.inline_datum + ); + } else if (utxo.data_hash !== null) { + const orderDatum = await this.blockFrostApi.scriptsDatumCbor( + utxo.data_hash + ); + order = new OrderV2.State( + this.networkId, + utxo.address, + { txHash: utxo.tx_hash, index: utxo.output_index }, + utxo.amount, + orderDatum.cbor + ); + } + + if (order === undefined) { + throw new Error(`Cannot find datum of Order V2, tx: ${utxo.tx_hash}`); + } + + orders.push(order); + } catch (err) { + errors.push(err); + } + } + return { + orders: orders, + errors: errors, + }; + } + + // MARK: STABLESWAP private async parseStablePoolState( utxo: Responses["address_utxo_content"][0] ): Promise { @@ -622,6 +738,298 @@ export class BlockfrostAdapter implements Adapter { return Big(priceNum.toString()).div(priceDen.toString()); } + + // MARK: LBE V2 + public async getAllLbeV2Factories(): Promise<{ + factories: LbeV2Types.FactoryState[]; + errors: unknown[]; + }> { + const config = LbeV2Constant.CONFIG[this.networkId]; + const utxos = await this.blockFrostApi.addressesUtxosAssetAll( + config.factoryHashBech32, + config.factoryAsset + ); + + const factories: LbeV2Types.FactoryState[] = []; + const errors: unknown[] = []; + for (const utxo of utxos) { + try { + if (!utxo.inline_datum) { + throw new Error( + `Cannot find datum of LBE V2 Factory, tx: ${utxo.tx_hash}` + ); + } + + const factory = new LbeV2Types.FactoryState( + this.networkId, + utxo.address, + { txHash: utxo.tx_hash, index: utxo.output_index }, + utxo.amount, + utxo.inline_datum + ); + factories.push(factory); + } catch (err) { + errors.push(err); + } + } + return { + factories: factories, + errors: errors, + }; + } + + public async getLbeV2Factory( + baseAsset: Asset, + raiseAsset: Asset + ): Promise { + const factoryIdent = PoolV2.computeLPAssetName(baseAsset, raiseAsset); + const { factories: allFactories } = await this.getAllLbeV2Factories(); + for (const factory of allFactories) { + if ( + StringUtils.compare(factory.head, factoryIdent) < 0 && + StringUtils.compare(factoryIdent, factory.tail) < 0 + ) { + return factory; + } + } + + return null; + } + + public async getLbeV2HeadAndTailFactory(lbeId: string): Promise<{ + head: LbeV2Types.FactoryState; + tail: LbeV2Types.FactoryState; + } | null> { + const { factories: allFactories } = await this.getAllLbeV2Factories(); + let head: LbeV2Types.FactoryState | undefined = undefined; + let tail: LbeV2Types.FactoryState | undefined = undefined; + for (const factory of allFactories) { + if (factory.head === lbeId) { + tail = factory; + } + if (factory.tail === lbeId) { + head = factory; + } + } + if (head === undefined || tail === undefined) { + return null; + } + return { head, tail }; + } + + public async getAllLbeV2Treasuries(): Promise<{ + treasuries: LbeV2Types.TreasuryState[]; + errors: unknown[]; + }> { + const config = LbeV2Constant.CONFIG[this.networkId]; + const utxos = await this.blockFrostApi.addressesUtxosAssetAll( + config.treasuryHashBech32, + config.treasuryAsset + ); + + const treasuries: LbeV2Types.TreasuryState[] = []; + const errors: unknown[] = []; + for (const utxo of utxos) { + try { + if (!utxo.inline_datum) { + throw new Error( + `Cannot find datum of LBE V2 Treasury, tx: ${utxo.tx_hash}` + ); + } + + const treasury = new LbeV2Types.TreasuryState( + this.networkId, + utxo.address, + { txHash: utxo.tx_hash, index: utxo.output_index }, + utxo.amount, + utxo.inline_datum + ); + treasuries.push(treasury); + } catch (err) { + errors.push(err); + } + } + return { + treasuries: treasuries, + errors: errors, + }; + } + + public async getLbeV2TreasuryByLbeId( + lbeId: string + ): Promise { + const { treasuries: allTreasuries } = await this.getAllLbeV2Treasuries(); + for (const treasury of allTreasuries) { + if (treasury.lbeId === lbeId) { + return treasury; + } + } + return null; + } + + public async getAllLbeV2Managers(): Promise<{ + managers: LbeV2Types.ManagerState[]; + errors: unknown[]; + }> { + const config = LbeV2Constant.CONFIG[this.networkId]; + const utxos = await this.blockFrostApi.addressesUtxosAssetAll( + config.managerHashBech32, + config.managerAsset + ); + + const managers: LbeV2Types.ManagerState[] = []; + const errors: unknown[] = []; + for (const utxo of utxos) { + try { + if (!utxo.inline_datum) { + throw new Error( + `Cannot find datum of Lbe V2 Manager, tx: ${utxo.tx_hash}` + ); + } + + const manager = new LbeV2Types.ManagerState( + this.networkId, + utxo.address, + { txHash: utxo.tx_hash, index: utxo.output_index }, + utxo.amount, + utxo.inline_datum + ); + managers.push(manager); + } catch (err) { + errors.push(err); + } + } + return { + managers: managers, + errors: errors, + }; + } + + public async getLbeV2ManagerByLbeId( + lbeId: string + ): Promise { + const { managers } = await this.getAllLbeV2Managers(); + for (const manager of managers) { + if (manager.lbeId === lbeId) { + return manager; + } + } + return null; + } + + public async getAllLbeV2Sellers(): Promise<{ + sellers: LbeV2Types.SellerState[]; + errors: unknown[]; + }> { + const config = LbeV2Constant.CONFIG[this.networkId]; + const utxos = await this.blockFrostApi.addressesUtxosAssetAll( + config.sellerHashBech32, + config.sellerAsset + ); + + const sellers: LbeV2Types.SellerState[] = []; + const errors: unknown[] = []; + for (const utxo of utxos) { + try { + if (!utxo.inline_datum) { + throw new Error( + `Cannot find datum of Lbe V2 Seller, tx: ${utxo.tx_hash}` + ); + } + + const seller = new LbeV2Types.SellerState( + this.networkId, + utxo.address, + { txHash: utxo.tx_hash, index: utxo.output_index }, + utxo.amount, + utxo.inline_datum + ); + sellers.push(seller); + } catch (err) { + errors.push(err); + } + } + return { + sellers: sellers, + errors: errors, + }; + } + + public async getLbeV2SellerByLbeId( + lbeId: string + ): Promise { + const { sellers } = await this.getAllLbeV2Sellers(); + for (const seller of sellers) { + if (seller.lbeId === lbeId) { + return seller; + } + } + return null; + } + + public async getAllLbeV2Orders(): Promise<{ + orders: LbeV2Types.OrderState[]; + errors: unknown[]; + }> { + const config = LbeV2Constant.CONFIG[this.networkId]; + const utxos = await this.blockFrostApi.addressesUtxosAssetAll( + config.orderHashBech32, + config.orderAsset + ); + const orders: LbeV2Types.OrderState[] = []; + const errors: unknown[] = []; + for (const utxo of utxos) { + try { + if (!utxo.inline_datum) { + throw new Error( + `Cannot find datum of Lbe V2 Order, tx: ${utxo.tx_hash}` + ); + } + + const order = new LbeV2Types.OrderState( + this.networkId, + utxo.address, + { txHash: utxo.tx_hash, index: utxo.output_index }, + utxo.amount, + utxo.inline_datum + ); + orders.push(order); + } catch (err) { + errors.push(err); + } + } + return { + orders: orders, + errors: errors, + }; + } + + public async getLbeV2OrdersByLbeId( + lbeId: string + ): Promise { + const { orders: allOrders } = await this.getAllLbeV2Orders(); + const orders: LbeV2Types.OrderState[] = []; + for (const order of allOrders) { + if (order.lbeId === lbeId) { + orders.push(order); + } + } + return orders; + } + + public async getLbeV2OrdersByLbeIdAndOwner( + lbeId: string, + owner: Address + ): Promise { + const { orders: allOrders } = await this.getAllLbeV2Orders(); + const orders: LbeV2Types.OrderState[] = []; + for (const order of allOrders) { + if (order.lbeId === lbeId && order.owner === owner) { + orders.push(order); + } + } + return orders; + } } export type MinswapAdapterConstructor = { diff --git a/src/batcher-fee-reduction/calculate.ts b/src/batcher-fee-reduction/calculate.ts index b342f89..41ffc6a 100644 --- a/src/batcher-fee-reduction/calculate.ts +++ b/src/batcher-fee-reduction/calculate.ts @@ -1,5 +1,5 @@ +import { Assets, UTxO } from "@minswap/lucid-cardano"; import BigNumber from "bignumber.js"; -import { Assets, UTxO } from "lucid-cardano"; import { NetworkEnvironment } from "../types/network"; import { diff --git a/src/calculate.ts b/src/calculate.ts index 56fe0e5..7db51c4 100644 --- a/src/calculate.ts +++ b/src/calculate.ts @@ -1,3 +1,4 @@ +import { UTxO } from "@minswap/lucid-cardano"; import invariant from "@minswap/tiny-invariant"; import Big from "big.js"; import { zipWith } from "remeda"; @@ -1082,3 +1083,17 @@ function gcdFunction(a: bigint, b: bigint): bigint { } return a; } + +export function compareUtxo(s1: UTxO, s2: UTxO): number { + if (s1.txHash === s2.txHash) { + return s1.outputIndex - s2.outputIndex; + } + + if (s1.txHash < s2.txHash) { + return -1; + } + if (s1.txHash === s2.txHash) { + return 0; + } + return 1; +} diff --git a/src/dex-v2.ts b/src/dex-v2.ts index 2ba7aa5..a94f05c 100644 --- a/src/dex-v2.ts +++ b/src/dex-v2.ts @@ -1,4 +1,3 @@ -import invariant from "@minswap/tiny-invariant"; import { Address, Assets, @@ -9,12 +8,15 @@ import { OutRef, Tx, TxComplete, + UnixTime, UTxO, -} from "lucid-cardano"; +} from "@minswap/lucid-cardano"; +import invariant from "@minswap/tiny-invariant"; import { Asset, BlockfrostAdapter, + compareUtxo, DexV2Calculation, DexV2Constant, FIXED_DEPOSIT_ADA, @@ -190,6 +192,12 @@ export type CancelBulkOrdersOptions = { AuthorizationMethodType?: OrderV2.AuthorizationMethodType; }; +export type CancelExpiredOrderOptions = { + orderUtxos: UTxO[]; + currentSlot: UnixTime; + extraDatumMap: Record; +}; + export class DexV2 { private readonly lucid: Lucid; private readonly networkId: NetworkId; @@ -694,17 +702,6 @@ export class DexV2 { ); } - private getOrderScriptHash(): string | undefined { - const orderAddress = - DexV2Constant.CONFIG[this.networkId].orderEnterpriseAddress; - const addrDetails = this.lucid.utils.getAddressDetails(orderAddress); - invariant( - addrDetails.paymentCredential?.type === "Script", - "order address should be a script address" - ); - return addrDetails.paymentCredential.hash; - } - private getOrderMetadata(orderOption: OrderOptions): string { switch (orderOption.type) { case OrderV2.StepType.SWAP_EXACT_IN: { @@ -940,7 +937,6 @@ export class DexV2 { orderOutRefs, composeTx, }: CancelBulkOrdersOptions): Promise { - const v2OrderScriptHash = this.getOrderScriptHash(); const orderUtxos = await this.lucid.utxosByOutRef(orderOutRefs); if (orderUtxos.length === 0) { throw new Error("Order Utxos are empty"); @@ -962,7 +958,8 @@ export class DexV2 { this.lucid.utils.getAddressDetails(orderAddr).paymentCredential; invariant( orderScriptPaymentCred?.type === "Script" && - orderScriptPaymentCred.hash === v2OrderScriptHash, + orderScriptPaymentCred.hash === + DexV2Constant.CONFIG[this.networkId].orderScriptHash, `Utxo is not belonged Minswap's order address, utxo: ${utxo.txHash}` ); let datum: OrderV2.Datum; @@ -1003,4 +1000,109 @@ export class DexV2 { } return lucidTx.complete(); } + + async cancelExpiredOrders({ + orderUtxos, + currentSlot, + extraDatumMap, + }: CancelExpiredOrderOptions): Promise { + const refScript = await this.lucid.utxosByOutRef([ + DexV2Constant.DEPLOYED_SCRIPTS[this.networkId].order, + DexV2Constant.DEPLOYED_SCRIPTS[this.networkId].expiredOrderCancellation, + ]); + const currentTime = this.lucid.utils.slotToUnixTime(currentSlot); + invariant( + refScript.length === 2, + "cannot find deployed script for V2 Order or Expired Order Cancellation" + ); + const sortedOrderUtxos = [...orderUtxos].sort(compareUtxo); + + const lucidTx = this.lucid.newTx().readFrom(refScript); + lucidTx.collectFrom( + sortedOrderUtxos, + Data.to(new Constr(OrderV2.Redeemer.CANCEL_EXPIRED_ORDER_BY_ANYONE, [])) + ); + for (const orderUtxo of sortedOrderUtxos) { + const orderAddr = orderUtxo.address; + const orderScriptPaymentCred = + this.lucid.utils.getAddressDetails(orderAddr).paymentCredential; + invariant( + orderScriptPaymentCred?.type === "Script" && + orderScriptPaymentCred.hash === + DexV2Constant.CONFIG[this.networkId].orderScriptHash, + `Utxo is not belonged Minswap's order address, utxo: ${orderUtxo.txHash}` + ); + let datum: OrderV2.Datum; + if (orderUtxo.datum) { + const rawDatum = orderUtxo.datum; + datum = OrderV2.Datum.fromPlutusData( + this.networkId, + Data.from(rawDatum) + ); + } else if (orderUtxo.datumHash) { + const rawDatum = await this.lucid.datumOf(orderUtxo); + datum = OrderV2.Datum.fromPlutusData( + this.networkId, + rawDatum as Constr + ); + } else { + throw new Error( + "Utxo without Datum Hash or Inline Datum can not be spent" + ); + } + const expiryOptions = datum.expiredOptions; + invariant(expiryOptions !== undefined, "Order must have expiry options"); + invariant( + expiryOptions.maxCancellationTip >= DexV2Constant.DEFAULT_CANCEL_TIPS, + "Cancel tip is too low" + ); + invariant( + expiryOptions.expiredTime < BigInt(currentTime), + "Order is not expired" + ); + const refundDatum = datum.refundReceiverDatum; + const outAssets = { ...orderUtxo.assets }; + outAssets["lovelace"] -= expiryOptions.maxCancellationTip; + switch (refundDatum.type) { + case OrderV2.ExtraDatumType.NO_DATUM: { + lucidTx.payToAddress(datum.refundReceiver, outAssets); + break; + } + case OrderV2.ExtraDatumType.DATUM_HASH: { + lucidTx.payToAddressWithData( + datum.refundReceiver, + refundDatum.hash in extraDatumMap + ? { asHash: extraDatumMap[refundDatum.hash] } + : { hash: refundDatum.hash }, + outAssets + ); + break; + } + case OrderV2.ExtraDatumType.INLINE_DATUM: { + invariant( + refundDatum.hash in extraDatumMap, + `Can not find refund datum of order ${orderUtxo.txHash}#${orderUtxo.outputIndex}` + ); + lucidTx.payToAddressWithData( + datum.refundReceiver, + { inline: extraDatumMap[refundDatum.hash] }, + outAssets + ); + break; + } + } + } + lucidTx + .withdraw( + DexV2Constant.CONFIG[this.networkId].expiredOrderCancelAddress, + 0n, + Data.to(0n) + ) + .validFrom(currentTime) + .validTo(currentTime + 3 * 60 * 60 * 1000) + .attachMetadata(674, { + msg: [MetadataMessage.CANCEL_ORDERS_AUTOMATICALLY], + }); + return await lucidTx.complete(); + } } diff --git a/src/dex.ts b/src/dex.ts index b9945ed..0314996 100644 --- a/src/dex.ts +++ b/src/dex.ts @@ -1,4 +1,3 @@ -import invariant from "@minswap/tiny-invariant"; import { Address, Assets, @@ -8,7 +7,8 @@ import { SpendingValidator, TxComplete, UTxO, -} from "lucid-cardano"; +} from "@minswap/lucid-cardano"; +import invariant from "@minswap/tiny-invariant"; import { BatcherFee } from "./batcher-fee-reduction/calculate"; import { DexVersion } from "./batcher-fee-reduction/configs.internal"; diff --git a/src/expired-order-monitor.ts b/src/expired-order-monitor.ts new file mode 100644 index 0000000..98ec277 --- /dev/null +++ b/src/expired-order-monitor.ts @@ -0,0 +1,119 @@ +import { Lucid } from "@minswap/lucid-cardano"; + +import { BlockfrostAdapter, DexV2, DexV2Constant, OrderV2 } from "."; +import { runRecurringJob } from "./utils/job"; + +type DexV2WorkerConstructor = { + lucid: Lucid; + blockfrostAdapter: BlockfrostAdapter; + privateKey: string; +}; + +export class ExpiredOrderMonitor { + private readonly lucid: Lucid; + private readonly blockfrostAdapter: BlockfrostAdapter; + private readonly privateKey: string; + + constructor({ + lucid, + blockfrostAdapter, + privateKey, + }: DexV2WorkerConstructor) { + this.lucid = lucid; + this.blockfrostAdapter = blockfrostAdapter; + this.privateKey = privateKey; + } + + async start(): Promise { + await runRecurringJob({ + name: "lbe v2 batcher", + interval: 1000 * 30, // 30s + job: () => this.runWorker(), + }); + } + + async runWorker(): Promise { + console.info("start run dex v2 worker"); + const { orders: allOrders } = await this.blockfrostAdapter.getAllV2Orders(); + const currentSlot = await this.blockfrostAdapter.currentSlot(); + const currentTime = this.lucid.utils.slotToUnixTime(currentSlot); + const mapDatum: Record = {}; + const orders: OrderV2.State[] = []; + for (const order of allOrders) { + const orderDatum = order.datum; + const expiredOptions = orderDatum.expiredOptions; + if (expiredOptions === undefined) { + continue; + } + if (expiredOptions.expiredTime >= BigInt(currentTime)) { + continue; + } + if ( + expiredOptions.maxCancellationTip < DexV2Constant.DEFAULT_CANCEL_TIPS + ) { + continue; + } + const receiverDatum = orderDatum.refundReceiverDatum; + let rawDatum: string | undefined = undefined; + if ( + receiverDatum.type === OrderV2.ExtraDatumType.INLINE_DATUM || + receiverDatum.type === OrderV2.ExtraDatumType.DATUM_HASH + ) { + try { + rawDatum = await this.blockfrostAdapter.getDatumByDatumHash( + receiverDatum.hash + ); + mapDatum[receiverDatum.hash] = rawDatum; + // eslint-disable-next-line unused-imports/no-unused-vars + } catch (_err) { + if (receiverDatum.type === OrderV2.ExtraDatumType.INLINE_DATUM) { + // if receiver Datum type is INLINE_DATUM, skip this order. + continue; + } + } + } + orders.push(order); + + // CANCEL MAX 20 Orders + if (orders.length === 20) { + break; + } + } + + if (orders.length === 0) { + console.info(`SKIP | No orders.`); + return; + } + const orderUtxos = await this.lucid.utxosByOutRef( + orders.map((order) => ({ + txHash: order.txIn.txHash, + outputIndex: order.txIn.index, + })) + ); + if (orderUtxos.length === 0) { + console.info(`SKIP | Can not find any order utxos.`); + return; + } + try { + const txComplete = await new DexV2( + this.lucid, + this.blockfrostAdapter + ).cancelExpiredOrders({ + orderUtxos: orderUtxos, + currentSlot, + extraDatumMap: mapDatum, + }); + const signedTx = await txComplete + .signWithPrivateKey(this.privateKey) + .complete(); + + const txId = await signedTx.submit(); + console.info(`Transaction submitted successfully: ${txId}`); + } catch (_err) { + console.error( + `Error when the worker runs: orders ${orders.map((order) => `${order.txIn.txHash}#${order.txIn.index}`).join(", ")}`, + _err + ); + } + } +} diff --git a/src/lbe-v2-worker/worker.ts b/src/lbe-v2-worker/worker.ts new file mode 100644 index 0000000..3624edc --- /dev/null +++ b/src/lbe-v2-worker/worker.ts @@ -0,0 +1,511 @@ +import { Data, Lucid, UnixTime, UTxO } from "@minswap/lucid-cardano"; +import invariant from "@minswap/tiny-invariant"; + +import { BlockfrostAdapter, LbeV2Constant, PoolV2 } from ".."; +import { LbeV2 } from "../lbe-v2/lbe-v2"; +import { LbeV2Types } from "../types/lbe-v2"; +import { NetworkEnvironment, NetworkId } from "../types/network"; +import { runRecurringJob } from "../utils/job"; + +type LbeV2WorkerConstructor = { + networkEnv: NetworkEnvironment; + networkId: NetworkId; + lucid: Lucid; + blockfrostAdapter: BlockfrostAdapter; + privateKey: string; +}; + +export type LbeV2EventData = { + treasuryUtxo: UTxO; + managerUtxo?: UTxO; + sellerUtxos: UTxO[]; + collectedOrderUtxos: UTxO[]; + uncollectedOrderUtxos: UTxO[]; +}; + +export class LbeV2Worker { + private readonly networkEnv: NetworkEnvironment; + private readonly networkId: NetworkId; + private readonly lucid: Lucid; + private readonly blockfrostAdapter: BlockfrostAdapter; + private readonly privateKey: string; + + constructor({ + networkEnv, + networkId, + lucid, + blockfrostAdapter, + privateKey, + }: LbeV2WorkerConstructor) { + this.networkEnv = networkEnv; + this.networkId = networkId; + this.lucid = lucid; + this.blockfrostAdapter = blockfrostAdapter; + this.privateKey = privateKey; + } + + async start(): Promise { + await runRecurringJob({ + name: "lbe v2 batcher", + interval: 1000 * 30, // 30s + job: () => this.runWorker(), + }); + } + + async getData(): Promise { + const { treasuries: allTreasuries } = + await this.blockfrostAdapter.getAllLbeV2Treasuries(); + const treasuryUtxos = await this.lucid.utxosByOutRef( + allTreasuries.map((treasury) => ({ + txHash: treasury.txIn.txHash, + outputIndex: treasury.txIn.index, + })) + ); + + const { managers: allManagers } = + await this.blockfrostAdapter.getAllLbeV2Managers(); + const managerUtxos = await this.lucid.utxosByOutRef( + allManagers.map((manager) => ({ + txHash: manager.txIn.txHash, + outputIndex: manager.txIn.index, + })) + ); + + const { sellers: allSellers } = + await this.blockfrostAdapter.getAllLbeV2Sellers(); + const sellerUtxos = await this.lucid.utxosByOutRef( + allSellers.map((seller) => ({ + txHash: seller.txIn.txHash, + outputIndex: seller.txIn.index, + })) + ); + + const { orders: allOrders } = + await this.blockfrostAdapter.getAllLbeV2Orders(); + const orderUtxos = await this.lucid.utxosByOutRef( + allOrders.map((order) => ({ + txHash: order.txIn.txHash, + outputIndex: order.txIn.index, + })) + ); + + const mapEventData: Record = {}; + for (const treasuryUtxo of treasuryUtxos) { + const rawTreasuryDatum = treasuryUtxo.datum; + invariant(rawTreasuryDatum, "Treasury utxo must have inline datum"); + const treasuryDatum = LbeV2Types.TreasuryDatum.fromPlutusData( + this.networkId, + Data.from(rawTreasuryDatum) + ); + const lbeId = PoolV2.computeLPAssetName( + treasuryDatum.baseAsset, + treasuryDatum.raiseAsset + ); + + mapEventData[lbeId] = { + treasuryUtxo: treasuryUtxo, + sellerUtxos: [], + collectedOrderUtxos: [], + uncollectedOrderUtxos: [], + }; + } + + for (const managerUtxo of managerUtxos) { + const rawManagerDatum = managerUtxo.datum; + invariant(rawManagerDatum, "Manager utxo must have inline datum"); + const managerDatum = LbeV2Types.ManagerDatum.fromPlutusData( + Data.from(rawManagerDatum) + ); + const lbeId = PoolV2.computeLPAssetName( + managerDatum.baseAsset, + managerDatum.raiseAsset + ); + + mapEventData[lbeId].managerUtxo = managerUtxo; + } + + for (const sellerUtxo of sellerUtxos) { + const rawDatum = sellerUtxo.datum; + invariant(rawDatum, "Seller utxo must have inline datum"); + const datum = LbeV2Types.SellerDatum.fromPlutusData( + Data.from(rawDatum), + this.networkId + ); + const lbeId = PoolV2.computeLPAssetName( + datum.baseAsset, + datum.raiseAsset + ); + + mapEventData[lbeId].sellerUtxos.push(sellerUtxo); + } + + for (const orderUtxo of orderUtxos) { + const rawDatum = orderUtxo.datum; + invariant(rawDatum, "Order utxo must have inline datum"); + const datum = LbeV2Types.OrderDatum.fromPlutusData( + Data.from(rawDatum), + this.networkId + ); + const lbeId = PoolV2.computeLPAssetName( + datum.baseAsset, + datum.raiseAsset + ); + if (datum.isCollected === true) { + mapEventData[lbeId].collectedOrderUtxos.push(orderUtxo); + } else { + mapEventData[lbeId].uncollectedOrderUtxos.push(orderUtxo); + } + } + + return Object.values(mapEventData); + } + + async countingSellers( + eventData: LbeV2EventData, + currentTime: UnixTime + ): Promise { + const { treasuryUtxo, managerUtxo, sellerUtxos } = eventData; + invariant(managerUtxo, "collectSellers: can not find manager"); + const txComplete = await new LbeV2(this.lucid).countingSellers({ + treasuryUtxo: treasuryUtxo, + managerUtxo: managerUtxo, + sellerUtxos: sellerUtxos.slice(0, LbeV2Constant.MINIMUM_SELLER_COLLECTED), + currentSlot: this.lucid.utils.unixTimeToSlot(currentTime), + }); + + const signedTx = await txComplete + .signWithPrivateKey(this.privateKey) + .complete(); + + const txId = await signedTx.submit(); + console.info(`Counting seller transaction submitted successfully: ${txId}`); + } + + async collectManager( + eventData: LbeV2EventData, + currentTime: UnixTime + ): Promise { + const { treasuryUtxo, managerUtxo } = eventData; + invariant(managerUtxo, "collectManager: can not find manager"); + const txComplete = await new LbeV2(this.lucid).collectManager({ + treasuryUtxo: treasuryUtxo, + managerUtxo: managerUtxo, + currentSlot: this.lucid.utils.unixTimeToSlot(currentTime), + }); + + const signedTx = await txComplete + .signWithPrivateKey(this.privateKey) + .complete(); + + const txId = await signedTx.submit(); + console.info(`Collect manager transaction submitted successfully: ${txId}`); + } + + async collectOrders( + eventData: LbeV2EventData, + currentTime: UnixTime + ): Promise { + const { treasuryUtxo, uncollectedOrderUtxos } = eventData; + const txComplete = await new LbeV2(this.lucid).collectOrders({ + treasuryUtxo: treasuryUtxo, + orderUtxos: uncollectedOrderUtxos, + currentSlot: this.lucid.utils.unixTimeToSlot(currentTime), + }); + + const signedTx = await txComplete + .signWithPrivateKey(this.privateKey) + .complete(); + + const txId = await signedTx.submit(); + console.info(`Collect orders transaction submitted successfully: ${txId}`); + } + + async createAmmPoolOrCancelEvent( + eventData: LbeV2EventData, + currentTime: UnixTime + ): Promise { + const { treasuryUtxo } = eventData; + const rawTreasuryDatum = eventData.treasuryUtxo.datum; + invariant(rawTreasuryDatum, "Treasury utxo must have inline datum"); + const treasuryDatum = LbeV2Types.TreasuryDatum.fromPlutusData( + this.networkId, + Data.from(rawTreasuryDatum) + ); + + if (treasuryDatum.collectedFund < (treasuryDatum.minimumRaise ?? 1n)) { + const txComplete = await new LbeV2(this.lucid).cancelEvent({ + treasuryUtxo: treasuryUtxo, + cancelData: { reason: LbeV2Types.CancelReason.NOT_REACH_MINIMUM }, + currentSlot: this.lucid.utils.unixTimeToSlot(currentTime), + }); + + const signedTx = await txComplete + .signWithPrivateKey(this.privateKey) + .complete(); + + const txId = await signedTx.submit(); + console.info( + `Cancel event by not reach min raise transaction submitted successfully: ${txId}` + ); + return; + } + + const ammFactory = await this.blockfrostAdapter.getFactoryV2ByPair( + treasuryDatum.baseAsset, + treasuryDatum.raiseAsset + ); + if (ammFactory === null) { + const poolV2 = await this.blockfrostAdapter.getV2PoolByPair( + treasuryDatum.baseAsset, + treasuryDatum.raiseAsset + ); + invariant(poolV2 !== null, "Can not find pool"); + + const ammPoolUtxos = await this.lucid.utxosByOutRef([ + { txHash: poolV2.txIn.txHash, outputIndex: poolV2.txIn.index }, + ]); + invariant(ammPoolUtxos.length === 1, "Can not find amm pool Utxo"); + + const txComplete = await new LbeV2(this.lucid).cancelEvent({ + treasuryUtxo: treasuryUtxo, + cancelData: { + reason: LbeV2Types.CancelReason.CREATED_POOL, + ammPoolUtxo: ammPoolUtxos[0], + }, + currentSlot: this.lucid.utils.unixTimeToSlot(currentTime), + }); + const signedTx = await txComplete + .signWithPrivateKey(this.privateKey) + .complete(); + + const txId = await signedTx.submit(); + console.info( + `Cancel event by created pool transaction submitted successfully: ${txId}` + ); + } else { + const ammFactoryUtxos = await this.lucid.utxosByOutRef([ + { txHash: ammFactory.txIn.txHash, outputIndex: ammFactory.txIn.index }, + ]); + invariant(ammFactoryUtxos.length === 1, "Can not find amm factory Utxo"); + + const txComplete = await new LbeV2(this.lucid).createAmmPool({ + treasuryUtxo: treasuryUtxo, + ammFactoryUtxo: ammFactoryUtxos[0], + currentSlot: this.lucid.utils.unixTimeToSlot(currentTime), + }); + + const signedTx = await txComplete + .signWithPrivateKey(this.privateKey) + .complete(); + + const txId = await signedTx.submit(); + console.info( + `Create AMM Pool transaction submitted successfully: ${txId}` + ); + } + } + + async redeemOrders( + eventData: LbeV2EventData, + currentTime: UnixTime + ): Promise { + const { treasuryUtxo, collectedOrderUtxos } = eventData; + + const txComplete = await new LbeV2(this.lucid).redeemOrders({ + treasuryUtxo: treasuryUtxo, + orderUtxos: collectedOrderUtxos, + currentSlot: this.lucid.utils.unixTimeToSlot(currentTime), + }); + + const signedTx = await txComplete + .signWithPrivateKey(this.privateKey) + .complete(); + + const txId = await signedTx.submit(); + console.info(`Redeem Orders transaction submitted successfully: ${txId}`); + } + + async refundOrders( + eventData: LbeV2EventData, + currentTime: UnixTime + ): Promise { + const { treasuryUtxo, collectedOrderUtxos } = eventData; + + const txComplete = await new LbeV2(this.lucid).refundOrders({ + treasuryUtxo: treasuryUtxo, + orderUtxos: collectedOrderUtxos, + currentSlot: this.lucid.utils.unixTimeToSlot(currentTime), + }); + + const signedTx = await txComplete + .signWithPrivateKey(this.privateKey) + .complete(); + + const txId = await signedTx.submit(); + console.info(`Refund Orders transaction submitted successfully: ${txId}`); + } + + async handleEvent( + eventData: LbeV2EventData, + currentTime: UnixTime + ): Promise<"skip" | "success"> { + // FIND PHASE OF BATCHER + const checkPhaseAndHandle: { + checkFn: ( + treasuryDatum: LbeV2Types.TreasuryDatum, + managerDatum: LbeV2Types.ManagerDatum | undefined + ) => boolean; + handleFn: ( + eventData: LbeV2EventData, + currentTime: UnixTime + ) => Promise; + }[] = [ + // COUNTING SELLER + { + checkFn: (treasuryDatum, managerDatum) => { + const { isManagerCollected } = treasuryDatum; + if (isManagerCollected) { + return false; + } + invariant(managerDatum, "can not find manager datum"); + return managerDatum.sellerCount > 0n; + }, + handleFn: this.countingSellers.bind(this), + }, + // COLLECT MANAGER + { + checkFn: (treasuryDatum, managerDatum) => { + const { isManagerCollected } = treasuryDatum; + if (isManagerCollected) { + return false; + } + invariant(managerDatum, "can not find manager datum"); + return true; + }, + handleFn: this.collectManager.bind(this), + }, + // COLLECT COLLECT ORDER + { + checkFn: (treasuryDatum, _) => { + const { reserveRaise, totalPenalty, collectedFund } = treasuryDatum; + return reserveRaise + totalPenalty > collectedFund; + }, + handleFn: this.collectOrders.bind(this), + }, + // CREATE POOL OR CANCEL EVENT + { + checkFn: (treasuryDatum, _) => { + const { + reserveRaise, + totalPenalty, + collectedFund, + isCancelled, + totalLiquidity, + } = treasuryDatum; + + return ( + reserveRaise + totalPenalty === collectedFund && + isCancelled === false && + totalLiquidity === 0n + ); + }, + handleFn: this.createAmmPoolOrCancelEvent.bind(this), + }, + // REDEEM ORDERS + { + checkFn: (treasuryDatum, _) => { + const { totalLiquidity, collectedFund } = treasuryDatum; + return totalLiquidity > 0n && collectedFund > 0n; + }, + handleFn: this.redeemOrders.bind(this), + }, + // REFUND ORDERS + { + checkFn: (treasuryDatum, _) => { + const { reserveRaise, totalPenalty, collectedFund, isCancelled } = + treasuryDatum; + + return ( + reserveRaise + totalPenalty === collectedFund && + isCancelled === true && + collectedFund > 0n + ); + }, + handleFn: this.refundOrders.bind(this), + }, + ]; + + const rawTreasuryDatum = eventData.treasuryUtxo.datum; + invariant(rawTreasuryDatum, "Treasury utxo must have inline datum"); + const treasuryDatum = LbeV2Types.TreasuryDatum.fromPlutusData( + this.networkId, + Data.from(rawTreasuryDatum) + ); + const { + endTime, + isCancelled, + totalPenalty, + reserveRaise, + isManagerCollected, + totalLiquidity, + collectedFund, + } = treasuryDatum; + if ( + // NOT ENCOUNTER PHASE YET + (currentTime <= Number(endTime) && isCancelled === false) || + // CANCELLED EVENT, waiting for owner closing it. + (isCancelled === true && + totalPenalty + reserveRaise === 0n && + isManagerCollected === true) || + // FINISH EVENT + (totalLiquidity > 0n && collectedFund === 0n) + ) { + return "skip"; + } + + let managerDatum = undefined; + if (eventData.managerUtxo !== undefined) { + const rawManagerDatum = eventData.managerUtxo.datum; + invariant(rawManagerDatum, "Treasury utxo must have inline datum"); + managerDatum = LbeV2Types.ManagerDatum.fromPlutusData( + Data.from(rawManagerDatum) + ); + } + + for (const { checkFn, handleFn } of checkPhaseAndHandle) { + if (checkFn(treasuryDatum, managerDatum)) { + await handleFn(eventData, currentTime); + return "success"; + } + } + return "success"; + } + + async runWorker(): Promise { + const eventsData = await this.getData(); + const currentSlot = await this.blockfrostAdapter.currentSlot(); + const currentTime = this.lucid.utils.slotToUnixTime(currentSlot); + + for (const eventData of eventsData) { + try { + const handleEventResult = await this.handleEvent( + eventData, + currentTime + ); + if (handleEventResult === "success") { + return; + } + } catch (err) { + const rawTreasuryDatum = eventData.treasuryUtxo.datum; + invariant(rawTreasuryDatum, "Treasury utxo must have inline datum"); + const treasuryDatum = LbeV2Types.TreasuryDatum.fromPlutusData( + this.networkId, + Data.from(rawTreasuryDatum) + ); + console.error( + `Fail to run worker for LBE ${PoolV2.computeLPAssetName(treasuryDatum.baseAsset, treasuryDatum.raiseAsset)}: ${err}` + ); + } + } + } +} diff --git a/src/lbe-v2/lbe-v2.ts b/src/lbe-v2/lbe-v2.ts new file mode 100644 index 0000000..e365053 --- /dev/null +++ b/src/lbe-v2/lbe-v2.ts @@ -0,0 +1,1872 @@ +import { + Address, + Assets, + Constr, + Data, + Lucid, + Tx, + TxComplete, + UTxO, +} from "@minswap/lucid-cardano"; +import invariant from "@minswap/tiny-invariant"; +import JSONBig from "json-bigint"; + +import { + compareUtxo, + DexV2Calculation, + DexV2Constant, + LbeV2Constant, + MetadataMessage, + PoolV2, +} from ".."; +import { Asset } from "../types/asset"; +import { RedeemerWrapper } from "../types/common"; +import { FactoryV2 } from "../types/factory"; +import { LbeV2Types } from "../types/lbe-v2"; +import { NetworkEnvironment, NetworkId } from "../types/network"; +import { lucidToNetworkEnv } from "../utils/network.internal"; +import { + AddSellersOptions, + CalculationRedeemAmountParams, + CloseEventOptions, + CollectManagerOptions, + CollectOrdersOptions, + CountingSellersOptions, + CreateAmmPoolTxOptions, + LbeV2CancelEventOptions, + LbeV2CreateEventOptions, + LbeV2DepositOrWithdrawOptions, + LbeV2UpdateEventOptions, + RedeemOrdersOptions, + RefundOrdersOptions, +} from "./type"; +import { + validateAddSeller, + validateCancelEvent, + validateCloseEvent, + validateCollectManager, + validateCollectOrders, + validateCountingSeller, + validateCreateAmmPool, + validateCreateEvent, + validateDepositOrWithdrawOrder, + validateRedeemOrders, + validateRefundOrders, + validateUpdateEvent, +} from "./validation"; + +const THREE_HOUR_IN_MS = 3 * 60 * 60 * 1000; + +export class LbeV2 { + private readonly lucid: Lucid; + private readonly networkId: NetworkId; + private readonly networkEnv: NetworkEnvironment; + + constructor(lucid: Lucid) { + this.lucid = lucid; + this.networkId = + lucid.network === "Mainnet" ? NetworkId.MAINNET : NetworkId.TESTNET; + this.networkEnv = lucidToNetworkEnv(lucid.network); + } + + async createEvent(options: LbeV2CreateEventOptions): Promise { + validateCreateEvent(options, this.lucid, this.networkId); + const { lbeV2Parameters, factoryUtxo, projectDetails, currentSlot } = + options; + const sellerCount: number = + options.sellerCount ?? Number(LbeV2Constant.DEFAULT_SELLER_COUNT); + const config = LbeV2Constant.CONFIG[this.networkId]; + const deployed = LbeV2Constant.DEPLOYED_SCRIPTS[this.networkId]; + + const datum = factoryUtxo.datum; + invariant(datum, "Factory utxo must have inline datum"); + const factory = LbeV2Types.FactoryDatum.fromPlutusData(Data.from(datum)); + const { baseAsset, raiseAsset, owner } = lbeV2Parameters; + const lbeV2Id = PoolV2.computeLPAssetName(baseAsset, raiseAsset); + + const treasuryDatum: LbeV2Types.TreasuryDatum = + LbeV2Types.LbeV2Parameters.toLbeV2TreasuryDatum( + this.networkId, + lbeV2Parameters + ); + + const lucidTx = this.lucid.newTx(); + + // READ FROM + const factoryRefs = await this.lucid.utxosByOutRef([deployed.factory]); + invariant( + factoryRefs.length === 1, + "cannot find deployed script for LbeV2 Factory" + ); + lucidTx.readFrom(factoryRefs); + + // SPENT + const redeemer: LbeV2Types.FactoryRedeemer = { + type: LbeV2Types.FactoryRedeemerType.CREATE_TREASURY, + baseAsset: baseAsset, + raiseAsset: raiseAsset, + }; + lucidTx.collectFrom( + [factoryUtxo], + Data.to( + RedeemerWrapper.toPlutusData( + LbeV2Types.FactoryRedeemer.toPlutusData(redeemer) + ) + ) + ); + + // MINT + const mintAssets: Assets = {}; + mintAssets[config.factoryAsset] = 1n; + mintAssets[config.treasuryAsset] = 1n; + mintAssets[config.managerAsset] = 1n; + mintAssets[config.sellerAsset] = BigInt(sellerCount); + lucidTx.mintAssets( + mintAssets, + Data.to(LbeV2Types.FactoryRedeemer.toPlutusData(redeemer)) + ); + + // VALID TIME RANGE + const currentTime = this.lucid.utils.slotToUnixTime(currentSlot); + lucidTx + .validFrom(currentTime) + .validTo( + Math.min( + Number(lbeV2Parameters.startTime) - 1, + currentTime + THREE_HOUR_IN_MS + ) + ); + + // PAY TO + lucidTx + .payToContract( + config.factoryAddress, + { + inline: Data.to( + LbeV2Types.FactoryDatum.toPlutusData({ + head: factory.head, + tail: lbeV2Id, + }) + ), + }, + { + [config.factoryAsset]: 1n, + } + ) + .payToContract( + config.factoryAddress, + { + inline: Data.to( + LbeV2Types.FactoryDatum.toPlutusData({ + head: lbeV2Id, + tail: factory.tail, + }) + ), + }, + { + [config.factoryAsset]: 1n, + } + ) + .payToContract( + config.treasuryAddress, + { + inline: Data.to(LbeV2Types.TreasuryDatum.toPlutusData(treasuryDatum)), + }, + { + [config.treasuryAsset]: 1n, + lovelace: + LbeV2Constant.TREASURY_MIN_ADA + + LbeV2Constant.CREATE_POOL_COMMISSION, + [Asset.toString(baseAsset)]: lbeV2Parameters.reserveBase, + } + ) + .payToContract( + config.managerAddress, + { + inline: Data.to( + LbeV2Types.ManagerDatum.toPlutusData({ + factoryPolicyId: config.factoryHash, + baseAsset: baseAsset, + raiseAsset: raiseAsset, + sellerCount: BigInt(sellerCount), + reserveRaise: 0n, + totalPenalty: 0n, + }) + ), + }, + { + [config.managerAsset]: 1n, + lovelace: LbeV2Constant.MANAGER_MIN_ADA, + } + ); + for (let i = 0; i < sellerCount; ++i) { + lucidTx.payToContract( + config.sellerAddress, + { + inline: Data.to( + LbeV2Types.SellerDatum.toPlutusData({ + factoryPolicyId: config.factoryHash, + owner: owner, + baseAsset: baseAsset, + raiseAsset: raiseAsset, + amount: 0n, + penaltyAmount: 0n, + }) + ), + }, + { + [config.sellerAsset]: 1n, + lovelace: LbeV2Constant.SELLER_MIN_ADA, + } + ); + } + + // SIGN by OWNER + const ownerPaymentCredential = + this.lucid.utils.getAddressDetails(owner).paymentCredential; + invariant( + ownerPaymentCredential && ownerPaymentCredential?.type === "Key", + "owner payment credential must be public key" + ); + lucidTx.addSigner(owner); + + // METADATA / EXTRA METADATA + const extraData: string[] | null = + JSONBig.stringify(projectDetails).match(/.{1,64}/g); + invariant(extraData, "cannot parse LbeV2 Project Details"); + lucidTx.attachMetadata(674, { + msg: [MetadataMessage.CREATE_EVENT], + extraData: extraData ?? [], + }); + return lucidTx.complete(); + } + + async updateEvent(options: LbeV2UpdateEventOptions): Promise { + validateUpdateEvent(options, this.lucid, this.networkId); + + const { + owner, + treasuryUtxo, + lbeV2Parameters, + currentSlot, + projectDetails, + } = options; + const config = LbeV2Constant.CONFIG[this.networkId]; + const currentTime = this.lucid.utils.slotToUnixTime(currentSlot); + + const datum = treasuryUtxo.datum; + invariant(datum, "Treasury utxo must have inline datum"); + const treasuryDatum = LbeV2Types.TreasuryDatum.fromPlutusData( + this.networkId, + Data.from(datum) + ); + + const newTreasuryDatum: LbeV2Types.TreasuryDatum = + LbeV2Types.LbeV2Parameters.toLbeV2TreasuryDatum( + this.networkId, + lbeV2Parameters + ); + const lucidTx = this.lucid.newTx(); + + // READ FROM + const treasuryRefs = await this.lucid.utxosByOutRef([ + LbeV2Constant.DEPLOYED_SCRIPTS[this.networkId].treasury, + ]); + invariant( + treasuryRefs.length === 1, + "cannot find deployed script for LbeV2 Factory" + ); + lucidTx.readFrom(treasuryRefs); + + // COLLECT FROM + lucidTx.collectFrom( + [treasuryUtxo], + Data.to( + LbeV2Types.TreasuryRedeemer.toPlutusData({ + type: LbeV2Types.TreasuryRedeemerType.UPDATE_LBE, + }) + ) + ); + + // PAY TO + lucidTx.payToContract( + config.treasuryAddress, + { + inline: Data.to( + LbeV2Types.TreasuryDatum.toPlutusData(newTreasuryDatum) + ), + }, + { + [config.treasuryAsset]: 1n, + lovelace: + LbeV2Constant.TREASURY_MIN_ADA + LbeV2Constant.CREATE_POOL_COMMISSION, + [Asset.toString(newTreasuryDatum.baseAsset)]: + lbeV2Parameters.reserveBase, + } + ); + + // SIGNER + lucidTx.addSigner(owner); + + // TIME RANGE + lucidTx + .validFrom(currentTime) + .validTo( + Math.min( + Number(treasuryDatum.startTime) - 1000, + Number(lbeV2Parameters.startTime) - 1000, + currentTime + THREE_HOUR_IN_MS + ) + ); + + // METADATA + const extraData: string[] | null = + projectDetails !== undefined + ? JSONBig.stringify(projectDetails).match(/.{1,64}/g) + : null; + invariant(extraData, "cannot parse LbeV2 Project Details"); + lucidTx.attachMetadata(674, { + msg: [MetadataMessage.UPDATE_EVENT], + extraData: extraData ?? [], + }); + + return await lucidTx.complete(); + } + + async cancelEvent(options: LbeV2CancelEventOptions): Promise { + validateCancelEvent(options, this.lucid, this.networkId); + const { treasuryUtxo, cancelData, currentSlot } = options; + const currentTime = this.lucid.utils.slotToUnixTime(currentSlot); + const config = LbeV2Constant.CONFIG[this.networkId]; + + const datum = treasuryUtxo.datum; + invariant(datum, "Treasury utxo must have inline datum"); + const treasuryDatum = LbeV2Types.TreasuryDatum.fromPlutusData( + this.networkId, + Data.from(datum) + ); + const { revocable, startTime, endTime, owner } = treasuryDatum; + + const lucidTx = this.lucid.newTx(); + // READ FROM + const treasuryRefs = await this.lucid.utxosByOutRef([ + LbeV2Constant.DEPLOYED_SCRIPTS[this.networkId].treasury, + ]); + invariant( + treasuryRefs.length === 1, + "cannot find deployed script for LbeV2 Factory" + ); + lucidTx.readFrom(treasuryRefs); + + // COLLECT FROM + const treasuryRedeemer = { + type: LbeV2Types.TreasuryRedeemerType.CANCEL_LBE, + reason: cancelData.reason, + }; + lucidTx.collectFrom( + [treasuryUtxo], + Data.to(LbeV2Types.TreasuryRedeemer.toPlutusData(treasuryRedeemer)) + ); + + // PAY TO + const newTreasuryDatum: LbeV2Types.TreasuryDatum = { + ...treasuryDatum, + isCancelled: true, + }; + lucidTx.payToContract( + config.treasuryAddress, + { + inline: Data.to( + LbeV2Types.TreasuryDatum.toPlutusData(newTreasuryDatum) + ), + }, + treasuryUtxo.assets + ); + + // CONDITION DEPEND ON REASON + let validTo = currentTime + THREE_HOUR_IN_MS; + switch (cancelData.reason) { + case LbeV2Types.CancelReason.BY_OWNER: { + validTo = Math.min( + validTo, + Number(revocable ? endTime : startTime) - 1000 + ); + lucidTx.addSigner(owner).attachMetadata(674, { + msg: [MetadataMessage.CANCEL_EVENT_BY_OWNER], + }); + break; + } + case LbeV2Types.CancelReason.CREATED_POOL: { + lucidTx.readFrom([cancelData.ammPoolUtxo]).attachMetadata(674, { + msg: [MetadataMessage.CANCEL_EVENT_BY_WORKER], + }); + break; + } + case LbeV2Types.CancelReason.NOT_REACH_MINIMUM: { + lucidTx.attachMetadata(674, { + msg: [MetadataMessage.CANCEL_EVENT_BY_WORKER], + }); + break; + } + } + + lucidTx.validTo(validTo); + return lucidTx.complete(); + } + + calculatePenaltyAmount(options: { + time: bigint; + totalInputAmount: bigint; + totalOutputAmount: bigint; + penaltyConfig?: LbeV2Types.PenaltyConfig; + }): bigint { + const { penaltyConfig, time, totalInputAmount, totalOutputAmount } = + options; + if (penaltyConfig !== undefined) { + const { penaltyStartTime, percent } = penaltyConfig; + if (time < penaltyStartTime) { + return 0n; + } + if (totalInputAmount > totalOutputAmount) { + const withdrawAmount = totalInputAmount - totalOutputAmount; + // calculate totalInputAmount + return (withdrawAmount * percent) / 100n; + } + return 0n; + } + return 0n; + } + + async depositOrWithdrawOrder( + options: LbeV2DepositOrWithdrawOptions + ): Promise { + validateDepositOrWithdrawOrder(options, this.lucid, this.networkId); + const { + treasuryUtxo, + sellerUtxo, + existingOrderUtxos: orderUtxos, + currentSlot, + owner, + action, + } = options; + const config = LbeV2Constant.CONFIG[this.networkId]; + + const currentTime = this.lucid.utils.slotToUnixTime(currentSlot); + + const rawTreasuryDatum = treasuryUtxo.datum; + invariant(rawTreasuryDatum, "Treasury utxo must have inline datum"); + const treasuryDatum = LbeV2Types.TreasuryDatum.fromPlutusData( + this.networkId, + Data.from(rawTreasuryDatum) + ); + + const rawSellerDatum = sellerUtxo.datum; + invariant(rawSellerDatum, "Seller utxo must have inline datum"); + const sellerDatum = LbeV2Types.SellerDatum.fromPlutusData( + Data.from(rawSellerDatum), + this.networkId + ); + + const orderDatums = orderUtxos.map((utxo) => { + const rawOrderDatum = utxo.datum; + invariant(rawOrderDatum, "Factory utxo must have inline datum"); + return LbeV2Types.OrderDatum.fromPlutusData( + Data.from(rawOrderDatum), + this.networkId + ); + }); + + let currentAmount = 0n; + let totalInputPenalty = 0n; + for (const orderDatum of orderDatums) { + currentAmount += orderDatum.amount; + totalInputPenalty += orderDatum.penaltyAmount; + } + let newAmount: bigint; + if (action.type === "deposit") { + newAmount = currentAmount + action.additionalAmount; + } else { + newAmount = currentAmount - action.withdrawalAmount; + } + + const validTo = Math.min( + Number(treasuryDatum.endTime), + currentTime + THREE_HOUR_IN_MS + ); + const txPenaltyAmount = this.calculatePenaltyAmount({ + penaltyConfig: treasuryDatum.penaltyConfig, + time: BigInt(validTo), + totalInputAmount: currentAmount, + totalOutputAmount: newAmount, + }); + const newPenaltyAmount = totalInputPenalty + txPenaltyAmount; + + const lucidTx = this.lucid.newTx(); + + // READ FROM + const sellerRefs = await this.lucid.utxosByOutRef([ + LbeV2Constant.DEPLOYED_SCRIPTS[this.networkId].seller, + ]); + invariant( + sellerRefs.length === 1, + "cannot find deployed script for LbeV2 Seller" + ); + lucidTx.readFrom(sellerRefs).readFrom([treasuryUtxo]); + + if (orderUtxos.length !== 0) { + const orderRefs = await this.lucid.utxosByOutRef([ + LbeV2Constant.DEPLOYED_SCRIPTS[this.networkId].order, + ]); + invariant( + orderRefs.length === 1, + "cannot find deployed script for LbeV2 Order" + ); + lucidTx.readFrom(orderRefs); + } + + // COLLECT FROM + lucidTx.collectFrom( + [sellerUtxo], + Data.to( + LbeV2Types.SellerRedeemer.toPlutusData( + LbeV2Types.SellerRedeemer.USING_SELLER + ) + ) + ); + lucidTx.collectFrom( + orderUtxos, + Data.to( + LbeV2Types.OrderRedeemer.toPlutusData( + LbeV2Types.OrderRedeemer.UPDATE_ORDER + ) + ) + ); + + // ADD SIGNER + for (const orderDatum of orderDatums) { + lucidTx.addSigner(orderDatum.owner); + } + + // MINT + let orderTokenMintAmount = 0n; + if (newAmount + newPenaltyAmount > 0n) { + orderTokenMintAmount += 1n; + } + if (orderUtxos.length > 0) { + orderTokenMintAmount -= BigInt(orderUtxos.length); + } + if (orderTokenMintAmount !== 0n) { + 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).mintAssets( + { [config.orderAsset]: orderTokenMintAmount }, + Data.to( + LbeV2Types.FactoryRedeemer.toPlutusData({ + type: LbeV2Types.FactoryRedeemerType.MINT_ORDER, + }) + ) + ); + } + + // PAY TO + const newSellerDatum = { + ...sellerDatum, + amount: sellerDatum.amount + newAmount - currentAmount, + penaltyAmount: sellerDatum.penaltyAmount + txPenaltyAmount, + }; + + const newSellerAssets: Assets = { + ...sellerUtxo.assets, + }; + if (orderUtxos.length === 0 && newAmount > 0n) { + newSellerAssets.lovelace = + newSellerAssets.lovelace + LbeV2Constant.SELLER_COMMISSION; + } + lucidTx.payToContract( + config.sellerAddress, + { inline: Data.to(LbeV2Types.SellerDatum.toPlutusData(newSellerDatum)) }, + newSellerAssets + ); + + if (newAmount + newPenaltyAmount > 0n) { + const newOrderDatum: LbeV2Types.OrderDatum = { + factoryPolicyId: config.factoryHash, + baseAsset: treasuryDatum.baseAsset, + raiseAsset: treasuryDatum.raiseAsset, + owner: owner, + amount: newAmount, + isCollected: false, + penaltyAmount: newPenaltyAmount, + }; + const orderAssets: Assets = { + lovelace: + LbeV2Constant.ORDER_MIN_ADA + LbeV2Constant.ORDER_COMMISSION * 2n, + [config.orderAsset]: 1n, + }; + const raiseAsset = Asset.toString(treasuryDatum.raiseAsset); + if (raiseAsset in orderAssets) { + orderAssets[raiseAsset] += newAmount + newPenaltyAmount; + } else { + orderAssets[raiseAsset] = newAmount + newPenaltyAmount; + } + console.log(orderAssets); + lucidTx.payToContract( + config.orderAddress, + { inline: Data.to(LbeV2Types.OrderDatum.toPlutusData(newOrderDatum)) }, + orderAssets + ); + } + + // VALID TIME + lucidTx.validFrom(currentTime).validTo(validTo); + + // METADATA + if (action.type === "deposit") { + lucidTx.attachMetadata(674, { + msg: [MetadataMessage.LBE_V2_DEPOSIT_ORDER_EVENT], + }); + } else { + lucidTx.attachMetadata(674, { + msg: [MetadataMessage.LBE_V2_WITHDRAW_ORDER_EVENT], + }); + } + + return lucidTx.complete(); + } + + async closeEventTx(options: CloseEventOptions): Promise { + validateCloseEvent(options, this.networkId); + const { treasuryUtxo, headFactoryUtxo, tailFactoryUtxo, 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 rawHeadFactoryDatum = headFactoryUtxo.datum; + invariant(rawHeadFactoryDatum, "Treasury utxo must have inline datum"); + const headFactoryDatum = LbeV2Types.FactoryDatum.fromPlutusData( + Data.from(rawHeadFactoryDatum) + ); + + const rawTailFactoryDatum = tailFactoryUtxo.datum; + invariant(rawTailFactoryDatum, "Treasury utxo must have inline datum"); + const tailFactoryDatum = LbeV2Types.FactoryDatum.fromPlutusData( + Data.from(rawTailFactoryDatum) + ); + + 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 treasuryRefs = await this.lucid.utxosByOutRef([ + LbeV2Constant.DEPLOYED_SCRIPTS[this.networkId].treasury, + ]); + invariant( + treasuryRefs.length === 1, + "cannot find deployed script for LbeV2 Treasury" + ); + lucidTx.readFrom(treasuryRefs); + + // COLLECT FROM + lucidTx + .collectFrom( + [treasuryUtxo], + Data.to( + LbeV2Types.TreasuryRedeemer.toPlutusData({ + type: LbeV2Types.TreasuryRedeemerType.CLOSE_EVENT, + }) + ) + ) + .collectFrom( + [headFactoryUtxo, tailFactoryUtxo], + Data.to( + RedeemerWrapper.toPlutusData( + LbeV2Types.FactoryRedeemer.toPlutusData({ + type: LbeV2Types.FactoryRedeemerType.CLOSE_TREASURY, + baseAsset: treasuryDatum.baseAsset, + raiseAsset: treasuryDatum.raiseAsset, + }) + ) + ) + ); + + // MINT + lucidTx.mintAssets( + { + [config.factoryAsset]: -1n, + [config.treasuryAsset]: -1n, + }, + Data.to( + LbeV2Types.FactoryRedeemer.toPlutusData({ + type: LbeV2Types.FactoryRedeemerType.CLOSE_TREASURY, + baseAsset: treasuryDatum.baseAsset, + raiseAsset: treasuryDatum.raiseAsset, + }) + ) + ); + + // PAY TO + lucidTx.payToContract( + config.factoryAddress, + { + inline: Data.to( + LbeV2Types.FactoryDatum.toPlutusData({ + head: headFactoryDatum.head, + tail: tailFactoryDatum.tail, + }) + ), + }, + { + [config.factoryAsset]: 1n, + } + ); + + // ADD SIGNER + lucidTx.addSigner(treasuryDatum.owner); + + // VALID TIME + lucidTx.validFrom(currentTime).validTo(currentTime + THREE_HOUR_IN_MS); + + // METADATA + lucidTx.attachMetadata(674, { + msg: [MetadataMessage.CLOSE_EVENT], + }); + + return await lucidTx.complete(); + } + + async addSellers(options: AddSellersOptions): Promise { + validateAddSeller(options, this.lucid, this.networkId); + 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.LBE_V2_ADD_SELLERS], + }); + + return lucidTx.complete(); + } + + async countingSellers(options: CountingSellersOptions): Promise { + validateCountingSeller(options, this.lucid, this.networkId); + const { treasuryUtxo, managerUtxo, sellerUtxos, currentSlot } = options; + const currentTime = this.lucid.utils.slotToUnixTime(currentSlot); + const config = LbeV2Constant.CONFIG[this.networkId]; + + const rawManagerDatum = managerUtxo.datum; + invariant(rawManagerDatum, "Treasury utxo must have inline datum"); + const managerDatum = LbeV2Types.ManagerDatum.fromPlutusData( + Data.from(rawManagerDatum) + ); + const sortedSellerUtxos = [...sellerUtxos].sort(compareUtxo); + + const sellerDatums = sortedSellerUtxos.map((utxo) => { + const rawSellerDatum = utxo.datum; + invariant(rawSellerDatum, "Seller utxo must have inline datum"); + const sellerDatum = LbeV2Types.SellerDatum.fromPlutusData( + Data.from(rawSellerDatum), + this.networkId + ); + return sellerDatum; + }); + + 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); + + const sellerRefs = await this.lucid.utxosByOutRef([ + LbeV2Constant.DEPLOYED_SCRIPTS[this.networkId].seller, + ]); + invariant( + sellerRefs.length === 1, + "cannot find deployed script for LbeV2 Seller" + ); + lucidTx.readFrom(sellerRefs); + + lucidTx.readFrom([treasuryUtxo]); + + // COLLECT FROM + lucidTx.collectFrom( + [managerUtxo], + Data.to( + LbeV2Types.ManagerRedeemer.toPlutusData( + LbeV2Types.ManagerRedeemer.COLLECT_SELLERS + ) + ) + ); + lucidTx.collectFrom( + sellerUtxos, + Data.to( + LbeV2Types.SellerRedeemer.toPlutusData( + LbeV2Types.SellerRedeemer.COUNTING_SELLERS + ) + ) + ); + + // MINT + lucidTx.mintAssets( + { [config.sellerAsset]: -BigInt(sellerUtxos.length) }, + Data.to( + LbeV2Types.FactoryRedeemer.toPlutusData({ + type: LbeV2Types.FactoryRedeemerType.BURN_SELLER, + }) + ) + ); + + // PAY TO + let totalReserveRaise = 0n; + let totalPenalty = 0n; + + for (const sellerDatum of sellerDatums) { + totalReserveRaise += sellerDatum.amount; + totalPenalty += sellerDatum.penaltyAmount; + } + const newManagerDatum: LbeV2Types.ManagerDatum = { + ...managerDatum, + reserveRaise: managerDatum.reserveRaise + totalReserveRaise, + totalPenalty: managerDatum.totalPenalty + totalPenalty, + sellerCount: managerDatum.sellerCount - BigInt(sellerUtxos.length), + }; + lucidTx.payToContract( + config.managerAddress, + { + inline: Data.to(LbeV2Types.ManagerDatum.toPlutusData(newManagerDatum)), + }, + { ...managerUtxo.assets } + ); + for (let i = 0; i < sellerDatums.length; ++i) { + const sellerDatum = sellerDatums[i]; + const sellerUtxo = sortedSellerUtxos[i]; + lucidTx.payToAddress(sellerDatum.owner, { + lovelace: + sellerUtxo.assets["lovelace"] - + LbeV2Constant.COLLECT_SELLER_COMMISSION, + }); + } + + // VALID TIME RANGE + lucidTx.validFrom(currentTime).validTo(currentTime + THREE_HOUR_IN_MS); + + // METADATA + lucidTx.attachMetadata(674, { + msg: [MetadataMessage.LBE_V2_COUNTING_SELLERS], + }); + + return lucidTx.complete(); + } + + async collectManager(options: CollectManagerOptions): Promise { + validateCollectManager(options, this.lucid, this.networkId); + const { treasuryUtxo, managerUtxo, currentSlot } = options; + const currentTime = this.lucid.utils.slotToUnixTime(currentSlot); + const config = LbeV2Constant.CONFIG[this.networkId]; + + const rawManagerDatum = managerUtxo.datum; + invariant(rawManagerDatum, "Treasury utxo must have inline datum"); + const managerDatum = LbeV2Types.ManagerDatum.fromPlutusData( + Data.from(rawManagerDatum) + ); + + const rawTreasuryDatum = treasuryUtxo.datum; + invariant(rawTreasuryDatum, "Treasury utxo must have inline datum"); + const treasuryDatum = LbeV2Types.TreasuryDatum.fromPlutusData( + this.networkId, + Data.from(rawTreasuryDatum) + ); + + 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); + + const treasuryRefs = await this.lucid.utxosByOutRef([ + LbeV2Constant.DEPLOYED_SCRIPTS[this.networkId].treasury, + ]); + invariant( + treasuryRefs.length === 1, + "cannot find deployed script for LbeV2 Treasury" + ); + lucidTx.readFrom(treasuryRefs); + + // COLLECT FROM + lucidTx.collectFrom( + [managerUtxo], + Data.to( + LbeV2Types.ManagerRedeemer.toPlutusData( + LbeV2Types.ManagerRedeemer.SPEND_MANAGER + ) + ) + ); + lucidTx.collectFrom( + [treasuryUtxo], + Data.to( + LbeV2Types.TreasuryRedeemer.toPlutusData({ + type: LbeV2Types.TreasuryRedeemerType.COLLECT_MANAGER, + }) + ) + ); + + // MINT + lucidTx.mintAssets( + { [config.managerAsset]: -1n }, + Data.to( + LbeV2Types.FactoryRedeemer.toPlutusData({ + type: LbeV2Types.FactoryRedeemerType.MINT_MANAGER, + }) + ) + ); + + // PAY TO + lucidTx.payToContract( + treasuryUtxo.address, + { + inline: Data.to( + LbeV2Types.TreasuryDatum.toPlutusData({ + ...treasuryDatum, + isManagerCollected: true, + reserveRaise: managerDatum.reserveRaise, + totalPenalty: managerDatum.totalPenalty, + }) + ), + }, + treasuryUtxo.assets + ); + + // VALID TIME RANGE + lucidTx.validFrom(currentTime).validTo(currentTime + THREE_HOUR_IN_MS); + + // METADATA + lucidTx.attachMetadata(674, { + msg: [MetadataMessage.LBE_V2_COLLECT_MANAGER], + }); + + return lucidTx.complete(); + } + + async collectOrders(options: CollectOrdersOptions): Promise { + validateCollectOrders(options, this.networkId); + const { treasuryUtxo, orderUtxos, 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 sortedOrderUtxos = [...orderUtxos].sort(compareUtxo); + const orderDatums = sortedOrderUtxos.map((utxo) => { + const rawOrderDatum = utxo.datum; + invariant(rawOrderDatum, "Order utxo must have inline datum"); + return LbeV2Types.OrderDatum.fromPlutusData( + Data.from(rawOrderDatum), + this.networkId + ); + }); + + let deltaCollectedFund = 0n; + for (const orderDatum of orderDatums) { + deltaCollectedFund += orderDatum.amount + orderDatum.penaltyAmount; + } + + const lucidTx = this.lucid.newTx(); + + // READ FROM + const orderRefs = await this.lucid.utxosByOutRef([ + LbeV2Constant.DEPLOYED_SCRIPTS[this.networkId].order, + ]); + invariant( + orderRefs.length === 1, + "cannot find deployed script for LbeV2 Order" + ); + lucidTx.readFrom(orderRefs); + + 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 treasuryRefs = await this.lucid.utxosByOutRef([ + LbeV2Constant.DEPLOYED_SCRIPTS[this.networkId].treasury, + ]); + invariant( + treasuryRefs.length === 1, + "cannot find deployed script for LbeV2 Treasury" + ); + lucidTx.readFrom(treasuryRefs); + + // COLLECT FROM + lucidTx.collectFrom( + orderUtxos, + Data.to( + LbeV2Types.OrderRedeemer.toPlutusData( + LbeV2Types.OrderRedeemer.COLLECT_ORDER + ) + ) + ); + lucidTx.collectFrom( + [treasuryUtxo], + Data.to( + LbeV2Types.TreasuryRedeemer.toPlutusData({ + type: LbeV2Types.TreasuryRedeemerType.COLLECT_ORDERS, + }) + ) + ); + + // PAY TO + const newTreasuryAssets: Assets = { ...treasuryUtxo.assets }; + const raiseAssetUnit = Asset.toString(treasuryDatum.raiseAsset); + if (raiseAssetUnit in newTreasuryAssets) { + newTreasuryAssets[raiseAssetUnit] = + newTreasuryAssets[raiseAssetUnit] + deltaCollectedFund; + } else { + newTreasuryAssets[raiseAssetUnit] = deltaCollectedFund; + } + lucidTx.payToContract( + config.treasuryAddress, + { + inline: Data.to( + LbeV2Types.TreasuryDatum.toPlutusData({ + ...treasuryDatum, + collectedFund: treasuryDatum.collectedFund + deltaCollectedFund, + }) + ), + }, + newTreasuryAssets + ); + for (let i = 0; i < orderDatums.length; ++i) { + const orderDatum = orderDatums[i]; + const orderUtxo = sortedOrderUtxos[i]; + lucidTx.payToContract( + orderUtxo.address, + { + inline: Data.to( + LbeV2Types.OrderDatum.toPlutusData({ + ...orderDatum, + isCollected: true, + }) + ), + }, + { + [config.orderAsset]: 1n, + lovelace: + LbeV2Constant.ORDER_MIN_ADA + LbeV2Constant.ORDER_COMMISSION, + } + ); + } + + // WITHDRAW + lucidTx.withdraw( + config.factoryRewardAddress, + 0n, + Data.to( + LbeV2Types.FactoryRedeemer.toPlutusData({ + type: LbeV2Types.FactoryRedeemerType.MANAGE_ORDER, + }) + ) + ); + + // VALID TIME RANGE + lucidTx.validFrom(currentTime).validTo(currentTime + THREE_HOUR_IN_MS); + + // METADATA + lucidTx.attachMetadata(674, { + msg: [MetadataMessage.LBE_V2_COLLECT_ORDER], + }); + + return lucidTx.complete(); + } + + calculateRedeemAmount(params: CalculationRedeemAmountParams): { + liquidityAmount: bigint; + returnedRaiseAmount: bigint; + } { + const { userAmount, totalPenalty, reserveRaise, totalLiquidity, maxRaise } = + params; + + if (userAmount <= 0n) { + throw new Error("User amount must be higher than 0n"); + } + if (totalLiquidity <= 0n) { + throw new Error("totalLiquidity must be higher than 0n"); + } + if (reserveRaise <= 0n) { + throw new Error("reserveRaise must be higher than 0n"); + } + + const totalReturnedRaiseAsset = + maxRaise && maxRaise < totalPenalty + reserveRaise + ? totalPenalty + reserveRaise - maxRaise + : 0n; + return { + liquidityAmount: (totalLiquidity * userAmount) / reserveRaise, + returnedRaiseAmount: + (totalReturnedRaiseAsset * userAmount) / reserveRaise, + }; + } + + async redeemOrders(options: RedeemOrdersOptions): Promise { + validateRedeemOrders(options, this.networkId); + const { treasuryUtxo, orderUtxos, 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 sortedOrderUtxos = [...orderUtxos].sort(compareUtxo); + const orderDatums = sortedOrderUtxos.map((utxo) => { + const rawOrderDatum = utxo.datum; + invariant(rawOrderDatum, "Order utxo must have inline datum"); + return LbeV2Types.OrderDatum.fromPlutusData( + Data.from(rawOrderDatum), + this.networkId + ); + }); + + const raiseAssetUnit = Asset.toString(treasuryDatum.raiseAsset); + const dexV2Config = DexV2Constant.CONFIG[this.networkId]; + + const lpAssetUnit = + dexV2Config.lpPolicyId + + PoolV2.computeLPAssetName( + treasuryDatum.raiseAsset, + treasuryDatum.baseAsset + ); + + const orderOutputs: { address: Address; assets: Assets }[] = []; + let totalFund = 0n; + let totalOrderLiquidity = 0n; + let totalOrderBonusRaise = 0n; + for (const orderDatum of orderDatums) { + let lpAmount = 0n; + let bonusRaise = 0n; + + if (orderDatum.amount !== 0n) { + const result = this.calculateRedeemAmount({ + userAmount: orderDatum.amount, + totalPenalty: treasuryDatum.totalPenalty, + reserveRaise: treasuryDatum.reserveRaise, + totalLiquidity: treasuryDatum.totalLiquidity, + maxRaise: treasuryDatum.maximumRaise, + }); + lpAmount = result.liquidityAmount; + bonusRaise = result.returnedRaiseAmount; + } + totalFund += orderDatum.amount + orderDatum.penaltyAmount; + totalOrderLiquidity += lpAmount; + totalOrderBonusRaise += bonusRaise; + + const orderOutAssets: Assets = { + lovelace: LbeV2Constant.ORDER_MIN_ADA, + }; + if (lpAmount > 0n) { + orderOutAssets[lpAssetUnit] = lpAmount; + } + if (bonusRaise > 0n) { + if (raiseAssetUnit in orderOutAssets) { + orderOutAssets[raiseAssetUnit] = + orderOutAssets[raiseAssetUnit] + bonusRaise; + } else { + orderOutAssets[raiseAssetUnit] = bonusRaise; + } + } + orderOutputs.push({ address: orderDatum.owner, assets: orderOutAssets }); + } + + const lucidTx = this.lucid.newTx(); + + // READ FROM + const deployed = LbeV2Constant.DEPLOYED_SCRIPTS[this.networkId]; + const orderRefs = await this.lucid.utxosByOutRef([deployed.order]); + invariant( + orderRefs.length === 1, + "cannot find deployed script for LbeV2 Order" + ); + lucidTx.readFrom(orderRefs); + + const treasuryRefs = await this.lucid.utxosByOutRef([deployed.treasury]); + invariant( + treasuryRefs.length === 1, + "cannot find deployed script for LbeV2 Treasury" + ); + lucidTx.readFrom(treasuryRefs); + + const factoryRefs = await this.lucid.utxosByOutRef([deployed.factory]); + invariant( + factoryRefs.length === 1, + "cannot find deployed script for LbeV2 Factory" + ); + lucidTx.readFrom(factoryRefs); + + // COLLECT FROM + lucidTx.collectFrom( + orderUtxos, + Data.to( + LbeV2Types.OrderRedeemer.toPlutusData( + LbeV2Types.OrderRedeemer.REDEEM_ORDER + ) + ) + ); + lucidTx.collectFrom( + [treasuryUtxo], + Data.to( + LbeV2Types.TreasuryRedeemer.toPlutusData({ + type: LbeV2Types.TreasuryRedeemerType.REDEEM_ORDERS, + }) + ) + ); + + // PAY TO + const newTreasuryAssets: Assets = { ...treasuryUtxo.assets }; + if (raiseAssetUnit in newTreasuryAssets && totalOrderBonusRaise > 0n) { + newTreasuryAssets[raiseAssetUnit] = + newTreasuryAssets[raiseAssetUnit] - totalOrderBonusRaise; + if (newTreasuryAssets[raiseAssetUnit] === 0n) { + delete newTreasuryAssets[raiseAssetUnit]; + } + } + if (lpAssetUnit in newTreasuryAssets && totalOrderLiquidity > 0n) { + newTreasuryAssets[lpAssetUnit] = + newTreasuryAssets[lpAssetUnit] - totalOrderLiquidity; + if (newTreasuryAssets[lpAssetUnit] === 0n) { + delete newTreasuryAssets[lpAssetUnit]; + } + } + lucidTx.payToContract( + config.treasuryAddress, + { + inline: Data.to( + LbeV2Types.TreasuryDatum.toPlutusData({ + ...treasuryDatum, + collectedFund: treasuryDatum.collectedFund - totalFund, + }) + ), + }, + newTreasuryAssets + ); + for (const { assets, address } of orderOutputs) { + lucidTx.payToAddress(address, assets); + } + + // MINT + lucidTx.mintAssets( + { [config.orderAsset]: -BigInt(orderDatums.length) }, + Data.to( + LbeV2Types.FactoryRedeemer.toPlutusData({ + type: LbeV2Types.FactoryRedeemerType.MINT_REDEEM_ORDERS, + }) + ) + ); + + // WITHDRAW + lucidTx.withdraw( + config.factoryRewardAddress, + 0n, + Data.to( + LbeV2Types.FactoryRedeemer.toPlutusData({ + type: LbeV2Types.FactoryRedeemerType.MANAGE_ORDER, + }) + ) + ); + + // VALID TIME RANGE + lucidTx.validFrom(currentTime).validTo(currentTime + THREE_HOUR_IN_MS); + + // METADATA + lucidTx.attachMetadata(674, { + msg: [MetadataMessage.LBE_V2_REDEEM_LP], + }); + + return lucidTx.complete(); + } + + async refundOrders(options: RefundOrdersOptions): Promise { + validateRefundOrders(options, this.networkId); + const { treasuryUtxo, orderUtxos, 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 sortedOrderUtxos = [...orderUtxos].sort(compareUtxo); + const orderDatums = sortedOrderUtxos.map((utxo) => { + const rawOrderDatum = utxo.datum; + invariant(rawOrderDatum, "Order utxo must have inline datum"); + return LbeV2Types.OrderDatum.fromPlutusData( + Data.from(rawOrderDatum), + this.networkId + ); + }); + + const raiseAssetUnit = Asset.toString(treasuryDatum.raiseAsset); + + const orderOutputs: { address: Address; assets: Assets }[] = []; + let refundAmount = 0n; + let totalOrderAmount = 0n; + let totalOrderPenalty = 0n; + for (const orderDatum of orderDatums) { + const orderRefundAmount = orderDatum.amount + orderDatum.penaltyAmount; + refundAmount += orderRefundAmount; + totalOrderAmount += orderDatum.amount; + totalOrderPenalty += orderDatum.penaltyAmount; + const orderOutAssets: Assets = { + lovelace: LbeV2Constant.ORDER_MIN_ADA, + }; + if (orderRefundAmount > 0n) { + if (raiseAssetUnit in orderOutAssets) { + orderOutAssets[raiseAssetUnit] = + orderOutAssets[raiseAssetUnit] + orderRefundAmount; + } else { + orderOutAssets[raiseAssetUnit] = orderRefundAmount; + } + } + orderOutputs.push({ + address: orderDatum.owner, + assets: orderOutAssets, + }); + } + + const lucidTx = this.lucid.newTx(); + + // READ FROM + const deployed = LbeV2Constant.DEPLOYED_SCRIPTS[this.networkId]; + const orderRefs = await this.lucid.utxosByOutRef([deployed.order]); + invariant( + orderRefs.length === 1, + "cannot find deployed script for LbeV2 Order" + ); + lucidTx.readFrom(orderRefs); + + const treasuryRefs = await this.lucid.utxosByOutRef([deployed.treasury]); + invariant( + treasuryRefs.length === 1, + "cannot find deployed script for LbeV2 Treasury" + ); + lucidTx.readFrom(treasuryRefs); + + const factoryRefs = await this.lucid.utxosByOutRef([deployed.factory]); + invariant( + factoryRefs.length === 1, + "cannot find deployed script for LbeV2 Factory" + ); + lucidTx.readFrom(factoryRefs); + + // COLLECT FROM + lucidTx.collectFrom( + orderUtxos, + Data.to( + LbeV2Types.OrderRedeemer.toPlutusData( + LbeV2Types.OrderRedeemer.REDEEM_ORDER + ) + ) + ); + lucidTx.collectFrom( + [treasuryUtxo], + Data.to( + LbeV2Types.TreasuryRedeemer.toPlutusData({ + type: LbeV2Types.TreasuryRedeemerType.REDEEM_ORDERS, + }) + ) + ); + + // PAY TO + const newTreasuryAssets: Assets = { ...treasuryUtxo.assets }; + if (raiseAssetUnit in newTreasuryAssets) { + newTreasuryAssets[raiseAssetUnit] = + newTreasuryAssets[raiseAssetUnit] - refundAmount; + if (newTreasuryAssets[raiseAssetUnit] === 0n) { + delete newTreasuryAssets[raiseAssetUnit]; + } + } + lucidTx.payToContract( + config.treasuryAddress, + { + inline: Data.to( + LbeV2Types.TreasuryDatum.toPlutusData({ + ...treasuryDatum, + collectedFund: treasuryDatum.collectedFund - refundAmount, + reserveRaise: treasuryDatum.collectedFund - totalOrderAmount, + totalPenalty: treasuryDatum.totalPenalty - totalOrderPenalty, + }) + ), + }, + newTreasuryAssets + ); + for (const { assets, address } of orderOutputs) { + lucidTx.payToAddress(address, assets); + } + + // MINT + lucidTx.mintAssets( + { [config.orderAsset]: -BigInt(orderDatums.length) }, + Data.to( + LbeV2Types.FactoryRedeemer.toPlutusData({ + type: LbeV2Types.FactoryRedeemerType.MINT_REDEEM_ORDERS, + }) + ) + ); + + // WITHDRAW + lucidTx.withdraw( + config.factoryRewardAddress, + 0n, + Data.to( + LbeV2Types.FactoryRedeemer.toPlutusData({ + type: LbeV2Types.FactoryRedeemerType.MANAGE_ORDER, + }) + ) + ); + + // VALID TIME RANGE + lucidTx.validFrom(currentTime).validTo(currentTime + THREE_HOUR_IN_MS); + + // METADATA + lucidTx.attachMetadata(674, { + msg: [MetadataMessage.LBE_V2_REFUND], + }); + + return lucidTx.complete(); + } + + async createAmmPool(options: CreateAmmPoolTxOptions): Promise { + validateCreateAmmPool(options, this.networkId); + const { treasuryUtxo, ammFactoryUtxo, 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 { + baseAsset, + raiseAsset, + maximumRaise, + collectedFund, + receiver, + reserveBase, + poolBaseFee, + poolAllocation, + } = treasuryDatum; + + let totalReserveRaise: bigint; + if (maximumRaise && maximumRaise < collectedFund) { + totalReserveRaise = maximumRaise; + } else { + totalReserveRaise = collectedFund; + } + const [assetA, assetB] = + Asset.compare(baseAsset, raiseAsset) < 0 + ? [baseAsset, raiseAsset] + : [raiseAsset, baseAsset]; + const lpAssetName = PoolV2.computeLPAssetName(assetA, assetB); + const lpAsset: Asset = { + tokenName: lpAssetName, + policyId: DexV2Constant.CONFIG[this.networkId].lpPolicyId, + }; + let reserveA: bigint; + let reserveB: bigint; + if (Asset.compare(assetA, baseAsset) === 0) { + reserveA = reserveBase; + reserveB = totalReserveRaise; + } else { + reserveA = totalReserveRaise; + reserveB = reserveBase; + } + const poolReserveA = (reserveA * poolAllocation) / 100n; + const poolReserveB = (reserveB * poolAllocation) / 100n; + const totalLiquidity = DexV2Calculation.calculateInitialLiquidity({ + amountA: poolReserveA, + amountB: poolReserveB, + }); + const totalLbeLPs = totalLiquidity - PoolV2.MINIMUM_LIQUIDITY; + const receiverLP = (totalLbeLPs * (poolAllocation - 50n)) / poolAllocation; + const treasuryOutDatum: LbeV2Types.TreasuryDatum = { + ...treasuryDatum, + totalLiquidity: totalLbeLPs - receiverLP, + }; + + const lucidTx = this.lucid.newTx(); + + // READ FROM + const treasuryRefs = await this.lucid.utxosByOutRef([ + LbeV2Constant.DEPLOYED_SCRIPTS[this.networkId].treasury, + ]); + invariant( + treasuryRefs.length === 1, + "cannot find deployed script for LbeV2 Treasury" + ); + + lucidTx.readFrom(treasuryRefs); + + // SPENT + lucidTx.collectFrom( + [treasuryUtxo], + Data.to( + LbeV2Types.TreasuryRedeemer.toPlutusData({ + type: LbeV2Types.TreasuryRedeemerType.CREATE_AMM_POOL, + }) + ) + ); + + // PAY TO + const receiveAssets: Assets = {}; + if (reserveA - poolReserveA !== 0n) { + receiveAssets[Asset.toString(assetA)] = reserveA - poolReserveA; + } + if (reserveB - poolReserveB !== 0n) { + receiveAssets[Asset.toString(assetB)] = reserveB - poolReserveB; + } + if (receiverLP) { + receiveAssets[Asset.toString(lpAsset)] = receiverLP; + } + lucidTx.payToAddress(receiver, receiveAssets); + + const newTreasuryAssets: Assets = { + ...treasuryUtxo.assets, + }; + delete newTreasuryAssets[Asset.toString(baseAsset)]; + newTreasuryAssets[Asset.toString(raiseAsset)] -= totalReserveRaise; + if (newTreasuryAssets[Asset.toString(raiseAsset)] === 0n) { + delete newTreasuryAssets[Asset.toString(raiseAsset)]; + } + if (totalLbeLPs - receiverLP !== 0n) { + newTreasuryAssets[Asset.toString(lpAsset)] = totalLbeLPs - receiverLP; + } + newTreasuryAssets["lovelace"] -= LbeV2Constant.CREATE_POOL_COMMISSION; + lucidTx.payToContract( + config.treasuryAddress, + { + inline: Data.to( + LbeV2Types.TreasuryDatum.toPlutusData(treasuryOutDatum) + ), + }, + newTreasuryAssets + ); + + // CREATE POOL + const poolBatchingStakeCredential = this.lucid.utils.getAddressDetails( + DexV2Constant.CONFIG[this.networkId].poolBatchingAddress + )?.stakeCredential; + invariant( + poolBatchingStakeCredential, + `cannot parse Liquidity Pool batching address` + ); + const poolDatum: PoolV2.Datum = { + poolBatchingStakeCredential: poolBatchingStakeCredential, + assetA: assetA, + assetB: assetB, + totalLiquidity: totalLiquidity, + reserveA: poolReserveA, + reserveB: poolReserveB, + baseFee: { + feeANumerator: poolBaseFee, + feeBNumerator: poolBaseFee, + }, + feeSharingNumerator: undefined, + allowDynamicFee: false, + }; + await this.buildCreateAMMPool(lucidTx, poolDatum, ammFactoryUtxo, lpAsset); + + // VALID TIME RANGE + lucidTx.validFrom(currentTime).validTo(currentTime + THREE_HOUR_IN_MS); + + // METADATA + lucidTx.attachMetadata(674, { + msg: [MetadataMessage.LBE_V2_CREATE_AMM_POOL], + }); + + return lucidTx.complete(); + } + + private async buildCreateAMMPool( + lucidTx: Tx, + poolDatum: PoolV2.Datum, + factoryUtxo: UTxO, + lpAsset: Asset + ): Promise { + const dexV2Config = DexV2Constant.CONFIG[this.networkId]; + const { assetA, assetB, reserveA, reserveB, totalLiquidity } = poolDatum; + const lpAssetName = lpAsset.tokenName; + const poolAssets: Assets = { + lovelace: PoolV2.DEFAULT_POOL_ADA, + [Asset.toString(lpAsset)]: + PoolV2.MAX_LIQUIDITY - (totalLiquidity - PoolV2.MINIMUM_LIQUIDITY), + [dexV2Config.poolAuthenAsset]: 1n, + }; + if (poolAssets[Asset.toString(assetA)]) { + poolAssets[Asset.toString(assetA)] += reserveA; + } else { + poolAssets[Asset.toString(assetA)] = reserveA; + } + if (poolAssets[Asset.toString(assetB)]) { + poolAssets[Asset.toString(assetB)] += reserveB; + } else { + poolAssets[Asset.toString(assetB)] = reserveB; + } + + const rawFactoryDatum = factoryUtxo.datum; + invariant(rawFactoryDatum, "Treasury utxo must have inline datum"); + const factoryDatum = FactoryV2.Datum.fromPlutusData( + Data.from(rawFactoryDatum) + ); + + const newFactoryDatum1: FactoryV2.Datum = { + head: factoryDatum.head, + tail: lpAssetName, + }; + const newFactoryDatum2: FactoryV2.Datum = { + head: lpAssetName, + tail: factoryDatum.tail, + }; + + // READ FROM + const ammFactoryRefs = await this.lucid.utxosByOutRef([ + DexV2Constant.DEPLOYED_SCRIPTS[this.networkId].factory, + ]); + invariant( + ammFactoryRefs.length === 1, + "cannot find deployed script for Factory Validator" + ); + const ammFactoryRef = ammFactoryRefs[0]; + + const ammAuthenRefs = await this.lucid.utxosByOutRef([ + DexV2Constant.DEPLOYED_SCRIPTS[this.networkId].authen, + ]); + invariant( + ammAuthenRefs.length === 1, + "cannot find deployed script for Authen Minting Policy" + ); + const ammAuthenRef = ammAuthenRefs[0]; + + // COLLECT FROM + lucidTx.collectFrom( + [factoryUtxo], + Data.to( + FactoryV2.Redeemer.toPlutusData({ + assetA: assetA, + assetB: assetB, + }) + ) + ); + + // PAY TO + lucidTx + .payToContract( + dexV2Config.poolCreationAddress, + { + inline: Data.to(PoolV2.Datum.toPlutusData(poolDatum)), + }, + poolAssets + ) + .payToContract( + dexV2Config.factoryAddress, + { + inline: Data.to(FactoryV2.Datum.toPlutusData(newFactoryDatum1)), + }, + { + [dexV2Config.factoryAsset]: 1n, + } + ) + .payToContract( + dexV2Config.factoryAddress, + { + inline: Data.to(FactoryV2.Datum.toPlutusData(newFactoryDatum2)), + }, + { + [dexV2Config.factoryAsset]: 1n, + } + ); + + // MINT + lucidTx.mintAssets( + { + [Asset.toString(lpAsset)]: PoolV2.MAX_LIQUIDITY, + [dexV2Config.factoryAsset]: 1n, + [dexV2Config.poolAuthenAsset]: 1n, + }, + Data.to(new Constr(1, [])) + ); + + lucidTx.readFrom([ammFactoryRef, ammAuthenRef]); + } +} diff --git a/src/lbe-v2/type.ts b/src/lbe-v2/type.ts new file mode 100644 index 0000000..b6a5a48 --- /dev/null +++ b/src/lbe-v2/type.ts @@ -0,0 +1,128 @@ +import { Address, UTxO } from "@minswap/lucid-cardano"; + +import { LbeV2Types } from "../types/lbe-v2"; + +export type LbeV2SocialLinks = { + twitter?: string; + telegram?: string; + discord?: string; + website?: string; +}; + +export type LbeV2Tokenomic = { + tag: string; + percentage: string; +}; + +export type LbeV2ProjectDetails = { + eventName: string; + description?: string; + socialLinks?: LbeV2SocialLinks; + tokenomics?: LbeV2Tokenomic[]; +}; + +export type LbeV2CreateEventOptions = { + factoryUtxo: UTxO; + lbeV2Parameters: LbeV2Types.LbeV2Parameters; + currentSlot: number; + sellerOwner: Address; + sellerCount?: number; + projectDetails?: LbeV2ProjectDetails; +}; + +export type LbeV2UpdateEventOptions = { + owner: Address; + treasuryUtxo: UTxO; + lbeV2Parameters: LbeV2Types.LbeV2Parameters; + currentSlot: number; + projectDetails?: LbeV2ProjectDetails; +}; + +export type LbeV2CancelEventOptions = { + treasuryUtxo: UTxO; + cancelData: + | { reason: LbeV2Types.CancelReason.BY_OWNER; owner: Address } + | { reason: LbeV2Types.CancelReason.NOT_REACH_MINIMUM } + | { reason: LbeV2Types.CancelReason.CREATED_POOL; ammPoolUtxo: UTxO }; + currentSlot: number; +}; + +export type LbeV2ManageOrderAction = + | { + type: "deposit"; + additionalAmount: bigint; + } + | { + type: "withdraw"; + withdrawalAmount: bigint; + }; + +export type LbeV2DepositOrWithdrawOptions = { + currentSlot: number; + existingOrderUtxos: UTxO[]; + treasuryUtxo: UTxO; + sellerUtxo: UTxO; + owner: Address; + action: LbeV2ManageOrderAction; +}; + +export type CloseEventOptions = { + treasuryUtxo: UTxO; + headFactoryUtxo: UTxO; + tailFactoryUtxo: UTxO; + currentSlot: number; + owner: Address; +}; + +export type AddSellersOptions = { + treasuryUtxo: UTxO; + managerUtxo: UTxO; + addSellerCount: number; + sellerOwner: Address; + currentSlot: number; +}; + +export type CountingSellersOptions = { + treasuryUtxo: UTxO; + managerUtxo: UTxO; + sellerUtxos: UTxO[]; + currentSlot: number; +}; + +export type CollectManagerOptions = { + treasuryUtxo: UTxO; + managerUtxo: UTxO; + currentSlot: number; +}; + +export type CollectOrdersOptions = { + treasuryUtxo: UTxO; + orderUtxos: UTxO[]; + currentSlot: number; +}; + +export type RedeemOrdersOptions = { + treasuryUtxo: UTxO; + orderUtxos: UTxO[]; + currentSlot: number; +}; + +export type RefundOrdersOptions = { + treasuryUtxo: UTxO; + orderUtxos: UTxO[]; + currentSlot: number; +}; + +export type CreateAmmPoolTxOptions = { + treasuryUtxo: UTxO; + ammFactoryUtxo: UTxO; + currentSlot: number; +}; + +export type CalculationRedeemAmountParams = { + userAmount: bigint; + totalPenalty: bigint; + reserveRaise: bigint; + totalLiquidity: bigint; + maxRaise?: bigint; +}; diff --git a/src/lbe-v2/validation.ts b/src/lbe-v2/validation.ts new file mode 100644 index 0000000..17a05c4 --- /dev/null +++ b/src/lbe-v2/validation.ts @@ -0,0 +1,821 @@ +import { Data, Lucid } from "@minswap/lucid-cardano"; +import invariant from "@minswap/tiny-invariant"; + +import { + Asset, + DexV2Calculation, + LbeV2Constant, + MAX_POOL_V2_TRADING_FEE_NUMERATOR, + MIN_POOL_V2_TRADING_FEE_NUMERATOR, + NetworkId, + PoolV2, +} from ".."; +import { FactoryV2 } from "../types/factory"; +import { LbeV2Types } from "../types/lbe-v2"; +import { + AddSellersOptions, + CloseEventOptions, + CollectManagerOptions, + CollectOrdersOptions, + CountingSellersOptions, + CreateAmmPoolTxOptions, + LbeV2CancelEventOptions, + LbeV2CreateEventOptions, + LbeV2DepositOrWithdrawOptions, + LbeV2ProjectDetails, + LbeV2UpdateEventOptions, + RedeemOrdersOptions, + RefundOrdersOptions, +} from "./type"; + +export function validateCreateEvent( + options: LbeV2CreateEventOptions, + lucid: Lucid, + networkId: NetworkId +): void { + const { lbeV2Parameters, currentSlot, factoryUtxo, projectDetails } = options; + const currentTime = lucid.utils.slotToUnixTime(currentSlot); + const { baseAsset, raiseAsset } = lbeV2Parameters; + const datum = factoryUtxo.datum; + invariant(datum, "Factory utxo must have inline datum"); + const factory = LbeV2Types.FactoryDatum.fromPlutusData(Data.from(datum)); + const config = LbeV2Constant.CONFIG[networkId]; + invariant( + config.factoryAsset in factoryUtxo.assets, + "Factory utxo assets must have factory asset" + ); + const lbeV2Id = PoolV2.computeLPAssetName(baseAsset, raiseAsset); + invariant( + factory.head < lbeV2Id && lbeV2Id < factory.tail, + "LBE ID name must be between factory head and tail" + ); + validateLbeV2Parameters(lbeV2Parameters, currentTime); + if (projectDetails !== undefined) { + validateProjectDetails(projectDetails); + } +} + +export function validateLbeV2Parameters( + params: LbeV2Types.LbeV2Parameters, + currentTime: number +): void { + const { + poolBaseFee, + penaltyConfig, + reserveBase, + minimumRaise, + maximumRaise, + minimumOrderRaise, + poolAllocation, + startTime, + endTime, + baseAsset, + raiseAsset, + } = params; + invariant( + Asset.toString(baseAsset) !== Asset.toString(raiseAsset), + "Base Asset, Raise Asset must be different" + ); + invariant( + Asset.toString(baseAsset) !== "lovelace", + "Base Asset must not equal ADA" + ); + invariant(startTime >= BigInt(currentTime), "LBE must start in future"); + invariant(startTime < endTime, "StartTime < EndTime"); + invariant( + endTime - startTime <= LbeV2Constant.MAX_DISCOVERY_RANGE, + "Discovery Phase must in a month" + ); + invariant( + poolAllocation >= LbeV2Constant.MIN_POOL_ALLOCATION_POINT, + `Pool Allocation must greater than ${LbeV2Constant.MIN_POOL_ALLOCATION_POINT}` + ); + invariant( + poolAllocation <= LbeV2Constant.MAX_POOL_ALLOCATION_POINT, + `Pool Allocation must less than ${LbeV2Constant.MAX_POOL_ALLOCATION_POINT}` + ); + if (minimumOrderRaise) { + invariant(minimumOrderRaise > 0n, "Minimum Order > 0"); + } + if (maximumRaise) { + invariant(maximumRaise > 0n, "Maximum Raise > 0"); + } + if (minimumRaise) { + invariant(minimumRaise > 0n, "Minimum Raise > 0"); + if (maximumRaise !== undefined) { + invariant(minimumRaise < maximumRaise, "Minimum Raise < Maximum Raise"); + } + } + invariant(reserveBase > 0n, "Reserve Base > 0"); + if (penaltyConfig) { + const { penaltyStartTime, percent } = penaltyConfig; + invariant(penaltyStartTime > startTime, "Penalty Start Time > Start Time"); + invariant(penaltyStartTime < endTime, "Penalty Start Time < End Time"); + invariant( + penaltyStartTime >= endTime - LbeV2Constant.MAX_PENALTY_RANGE, + "Maximum penalty period of 2 final days" + ); + invariant(percent > 0n, "Penalty Percent > 0"); + invariant( + percent <= LbeV2Constant.MAX_PENALTY_RATE, + `Penalty Percent <= ${LbeV2Constant.MAX_PENALTY_RATE}` + ); + } + const poolBaseFeeMin = MIN_POOL_V2_TRADING_FEE_NUMERATOR; + const poolBaseFeeMax = MAX_POOL_V2_TRADING_FEE_NUMERATOR; + invariant( + poolBaseFee >= poolBaseFeeMin && poolBaseFee <= poolBaseFeeMax, + `Pool Base Fee must in range ${poolBaseFeeMin} - ${poolBaseFeeMax}` + ); +} + +export function validateProjectDetails(details: LbeV2ProjectDetails): void { + const { eventName, description, tokenomics } = details; + + invariant(eventName.length <= 50, "Event Name is too long"); + invariant(description?.length ?? 0 < 1000, "Event Description is too long"); + let totalPercentage = 0; + for (const d of tokenomics ?? []) { + invariant(d.tag.length <= 50, "tokenomic tag is too long"); + const percentage = Number(d.percentage); + invariant( + !isNaN(percentage) && percentage > 0 && percentage <= 100, + "invalid percentage" + ); + totalPercentage += percentage; + } + invariant( + totalPercentage === 100 || tokenomics === undefined, + "total percentage is not 100%" + ); +} + +export function validateUpdateEvent( + options: LbeV2UpdateEventOptions, + lucid: Lucid, + networkId: NetworkId +): void { + const { owner, treasuryUtxo, lbeV2Parameters, currentSlot, projectDetails } = + options; + const config = LbeV2Constant.CONFIG[networkId]; + const currentTime = lucid.utils.slotToUnixTime(currentSlot); + const datum = treasuryUtxo.datum; + invariant( + config.treasuryAsset in treasuryUtxo.assets, + "Treasury utxo assets must have treasury asset" + ); + invariant(datum, "Treasury utxo must have inline datum"); + const treasuryDatum = LbeV2Types.TreasuryDatum.fromPlutusData( + networkId, + Data.from(datum) + ); + invariant( + currentTime < treasuryDatum.startTime, + "validateUpdateLbe: currentTime must be before start time" + ); + invariant( + treasuryDatum.isCancelled === false, + "validateUpdateLbe: LBE is cancelled" + ); + invariant( + Asset.toString(treasuryDatum.baseAsset) === + Asset.toString(lbeV2Parameters.baseAsset), + "Invalid base asset" + ); + invariant( + Asset.toString(treasuryDatum.raiseAsset) === + Asset.toString(lbeV2Parameters.raiseAsset), + "Invalid raise asset" + ); + invariant(owner === treasuryDatum.owner, "Invalid owner"); + validateLbeV2Parameters(lbeV2Parameters, currentTime); + if (projectDetails !== undefined) { + validateProjectDetails(projectDetails); + } +} + +export function validateCancelEvent( + options: LbeV2CancelEventOptions, + lucid: Lucid, + networkId: NetworkId +): void { + const { treasuryUtxo, cancelData, currentSlot } = options; + const config = LbeV2Constant.CONFIG[networkId]; + + const currentTime = lucid.utils.slotToUnixTime(currentSlot); + const datum = treasuryUtxo.datum; + invariant( + config.treasuryAsset in treasuryUtxo.assets, + "Treasury utxo assets must have treasury asset" + ); + invariant(datum, "Treasury utxo must have inline datum"); + const treasuryDatum = LbeV2Types.TreasuryDatum.fromPlutusData( + networkId, + Data.from(datum) + ); + const { + revocable, + baseAsset, + raiseAsset, + endTime, + startTime, + totalLiquidity, + minimumRaise, + isManagerCollected, + totalPenalty, + reserveRaise, + owner, + isCancelled, + } = treasuryDatum; + const lbeId = PoolV2.computeLPAssetName(baseAsset, raiseAsset); + invariant(isCancelled === false, "Event already cancelled"); + switch (cancelData.reason) { + case LbeV2Types.CancelReason.BY_OWNER: { + invariant( + owner === cancelData.owner, + "validateCancelEvent: Invalid project owner" + ); + if (revocable) { + invariant( + BigInt(currentTime) < endTime, + "Cancel before discovery phase end" + ); + } else { + invariant( + BigInt(currentTime) < startTime, + "Cancel before discovery phase start" + ); + } + break; + } + case LbeV2Types.CancelReason.CREATED_POOL: { + const ammPoolUtxo = cancelData.ammPoolUtxo; + invariant(ammPoolUtxo.datum, "ammFactory utxo must have inline datum"); + const ammPool = PoolV2.Datum.fromPlutusData(Data.from(ammPoolUtxo.datum)); + invariant( + lbeId === PoolV2.computeLPAssetName(ammPool.assetA, ammPool.assetB), + "treasury and Amm Pool must share the same lbe id" + ); + invariant(totalLiquidity === 0n, "LBE has created pool"); + break; + } + case LbeV2Types.CancelReason.NOT_REACH_MINIMUM: { + if (minimumRaise && isManagerCollected) { + invariant( + reserveRaise + totalPenalty < minimumRaise, + "Not pass minimum raise" + ); + } + break; + } + } +} + +export function validateDepositOrWithdrawOrder( + options: LbeV2DepositOrWithdrawOptions, + lucid: Lucid, + networkId: NetworkId +): void { + const { + treasuryUtxo, + sellerUtxo, + existingOrderUtxos: orderUtxos, + currentSlot, + action, + } = options; + const currentTime = lucid.utils.slotToUnixTime(currentSlot); + const config = LbeV2Constant.CONFIG[networkId]; + + const rawTreasuryDatum = treasuryUtxo.datum; + invariant(rawTreasuryDatum, "Treasury utxo must have inline datum"); + const treasuryDatum = LbeV2Types.TreasuryDatum.fromPlutusData( + networkId, + Data.from(rawTreasuryDatum) + ); + invariant( + config.treasuryAsset in treasuryUtxo.assets, + "Treasury utxo assets must have treasury asset" + ); + + const rawSellerDatum = sellerUtxo.datum; + invariant(rawSellerDatum, "Seller utxo must have inline datum"); + const sellerDatum = LbeV2Types.SellerDatum.fromPlutusData( + Data.from(rawSellerDatum), + networkId + ); + invariant( + config.sellerAsset in sellerUtxo.assets, + "Seller utxo assets must have seller asset" + ); + + const orderDatums = orderUtxos.map((utxo) => { + const rawOrderDatum = utxo.datum; + invariant(rawOrderDatum, "Order utxo must have inline datum"); + invariant( + config.orderAsset in utxo.assets, + "Order utxo assets must have order asset" + ); + return LbeV2Types.OrderDatum.fromPlutusData( + Data.from(rawOrderDatum), + networkId + ); + }); + + invariant( + PoolV2.computeLPAssetName( + treasuryDatum.baseAsset, + treasuryDatum.raiseAsset + ) === + PoolV2.computeLPAssetName(sellerDatum.baseAsset, sellerDatum.raiseAsset), + "treasury, seller must share the same lbe id" + ); + let currentAmount = 0n; + for (const orderDatum of orderDatums) { + invariant( + PoolV2.computeLPAssetName( + treasuryDatum.baseAsset, + treasuryDatum.raiseAsset + ) === + PoolV2.computeLPAssetName(orderDatum.baseAsset, orderDatum.raiseAsset), + "treasury, order must share the same lbe id" + ); + + const ownerPaymentCredential = lucid.utils.getAddressDetails( + orderDatum.owner + ).paymentCredential; + invariant( + ownerPaymentCredential && ownerPaymentCredential.type === "Key", + "Order owner must be pubkey hash" + ); + currentAmount += orderDatum.amount; + } + invariant(treasuryDatum.isCancelled === false, "lbe has cancelled"); + let newAmount: bigint; + if (action.type === "deposit") { + newAmount = currentAmount + action.additionalAmount; + } else { + invariant( + currentAmount >= action.withdrawalAmount, + `Exceed the maximum withdrawal, withdrawal: ${action.withdrawalAmount}, available: ${currentAmount}` + ); + newAmount = currentAmount - action.withdrawalAmount; + } + invariant( + treasuryDatum.startTime <= currentTime, + `The event hasn't really started yet, please wait a little longer.` + ); + invariant(currentTime <= treasuryDatum.endTime, "The event has been ended!"); + const minimumRaise = treasuryDatum.minimumOrderRaise; + if (minimumRaise !== undefined) { + invariant( + newAmount === 0n || newAmount >= minimumRaise, + "Using Seller Tx: Order must higher than min raise" + ); + } +} + +export function validateCloseEvent( + options: CloseEventOptions, + networkId: NetworkId +): void { + const { treasuryUtxo, headFactoryUtxo, tailFactoryUtxo, owner } = options; + const config = LbeV2Constant.CONFIG[networkId]; + + const rawTreasuryDatum = treasuryUtxo.datum; + invariant(rawTreasuryDatum, "Treasury utxo must have inline datum"); + const treasuryDatum = LbeV2Types.TreasuryDatum.fromPlutusData( + networkId, + Data.from(rawTreasuryDatum) + ); + invariant( + config.treasuryAsset in treasuryUtxo.assets, + "Treasury utxo assets must have treasury asset" + ); + const lbeId = PoolV2.computeLPAssetName( + treasuryDatum.baseAsset, + treasuryDatum.raiseAsset + ); + + const rawHeadFactoryDatum = headFactoryUtxo.datum; + invariant(rawHeadFactoryDatum, "Treasury utxo must have inline datum"); + const headFactoryDatum = LbeV2Types.FactoryDatum.fromPlutusData( + Data.from(rawHeadFactoryDatum) + ); + invariant( + config.factoryAsset in headFactoryUtxo.assets, + "Factory utxo assets must have factory asset" + ); + + const rawTailFactoryDatum = tailFactoryUtxo.datum; + invariant(rawTailFactoryDatum, "Treasury utxo must have inline datum"); + const tailFactoryDatum = LbeV2Types.FactoryDatum.fromPlutusData( + Data.from(rawTailFactoryDatum) + ); + invariant( + config.factoryAsset in tailFactoryUtxo.assets, + "Factory utxo assets must have factory asset" + ); + + invariant(headFactoryDatum.tail === lbeId, "Head Factory is invalid"); + invariant(tailFactoryDatum.head === lbeId, "Tail Factory is invalid"); + + invariant(treasuryDatum.isCancelled === true, "lbe must be cancelled"); + invariant(treasuryDatum.owner === owner, "Only Owner can close"); + invariant(treasuryDatum.isManagerCollected, "Manager must be collected"); + invariant( + treasuryDatum.totalPenalty === 0n && treasuryDatum.reserveRaise === 0n, + "All Orders have been refunded" + ); +} + +export function validateAddSeller( + options: AddSellersOptions, + lucid: Lucid, + networkId: NetworkId +): void { + const { addSellerCount, treasuryUtxo, managerUtxo, currentSlot } = options; + const currentTime = lucid.utils.slotToUnixTime(currentSlot); + const config = LbeV2Constant.CONFIG[networkId]; + + const rawTreasuryDatum = treasuryUtxo.datum; + invariant(rawTreasuryDatum, "Treasury utxo must have inline datum"); + const treasuryDatum = LbeV2Types.TreasuryDatum.fromPlutusData( + networkId, + Data.from(rawTreasuryDatum) + ); + invariant( + config.treasuryAsset in treasuryUtxo.assets, + "Treasury utxo assets must have treasury asset" + ); + + const rawManagerDatum = managerUtxo.datum; + invariant(rawManagerDatum, "Manager 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 add seller before encounter phase" + ); +} + +export function validateCountingSeller( + options: CountingSellersOptions, + lucid: Lucid, + networkId: NetworkId +): void { + const { treasuryUtxo, managerUtxo, sellerUtxos, currentSlot } = options; + const currentTime = lucid.utils.slotToUnixTime(currentSlot); + const config = LbeV2Constant.CONFIG[networkId]; + + const rawTreasuryDatum = treasuryUtxo.datum; + invariant(rawTreasuryDatum, "Treasury utxo must have inline datum"); + const treasuryDatum = LbeV2Types.TreasuryDatum.fromPlutusData( + networkId, + Data.from(rawTreasuryDatum) + ); + invariant( + config.treasuryAsset in treasuryUtxo.assets, + "Treasury utxo assets must have treasury asset" + ); + + const rawManagerDatum = managerUtxo.datum; + invariant(rawManagerDatum, "Manager 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( + PoolV2.computeLPAssetName( + treasuryDatum.baseAsset, + treasuryDatum.raiseAsset + ) === + PoolV2.computeLPAssetName( + managerDatum.baseAsset, + managerDatum.raiseAsset + ), + "treasury, manager must share the same lbe id" + ); + + const _sellerDatums = sellerUtxos.map((utxo) => { + const rawSellerDatum = utxo.datum; + invariant(rawSellerDatum, "Seller utxo must have inline datum"); + invariant( + config.sellerAsset in utxo.assets, + "Seller utxo assets must have seller asset" + ); + const sellerDatum = LbeV2Types.SellerDatum.fromPlutusData( + Data.from(rawSellerDatum), + networkId + ); + invariant( + PoolV2.computeLPAssetName( + treasuryDatum.baseAsset, + treasuryDatum.raiseAsset + ) === + PoolV2.computeLPAssetName( + sellerDatum.baseAsset, + sellerDatum.raiseAsset + ), + "treasury, seller must share the same lbe id" + ); + return sellerDatum; + }); + + invariant( + sellerUtxos.length >= LbeV2Constant.MINIMUM_SELLER_COLLECTED || + BigInt(sellerUtxos.length) === managerDatum.sellerCount, + "not collect enough sellers" + ); + invariant(sellerUtxos.length > 0, "At least one seller input is required."); + invariant( + currentTime > treasuryDatum.endTime || treasuryDatum.isCancelled === true, + "lbe is not cancel or discovery phase is not ended" + ); +} + +export function validateCollectManager( + options: CollectManagerOptions, + lucid: Lucid, + networkId: NetworkId +): void { + const { treasuryUtxo, managerUtxo, currentSlot } = options; + const currentTime = lucid.utils.slotToUnixTime(currentSlot); + const config = LbeV2Constant.CONFIG[networkId]; + + const rawTreasuryDatum = treasuryUtxo.datum; + invariant(rawTreasuryDatum, "Treasury utxo must have inline datum"); + const treasuryDatum = LbeV2Types.TreasuryDatum.fromPlutusData( + networkId, + Data.from(rawTreasuryDatum) + ); + invariant( + config.treasuryAsset in treasuryUtxo.assets, + "Treasury utxo assets must have treasury asset" + ); + + const rawManagerDatum = managerUtxo.datum; + invariant(rawManagerDatum, "Manager 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( + PoolV2.computeLPAssetName( + treasuryDatum.baseAsset, + treasuryDatum.raiseAsset + ) === + PoolV2.computeLPAssetName( + managerDatum.baseAsset, + managerDatum.raiseAsset + ), + "treasury, manager must share the same lbe id" + ); + + invariant( + currentTime > treasuryDatum.endTime || treasuryDatum.isCancelled === true, + "lbe is not cancel or discovery phase is not ended" + ); + invariant( + managerDatum.sellerCount === 0n, + "Must collect all seller before collecting manager" + ); + invariant( + treasuryDatum.isManagerCollected === false, + "LBE collected manager yet" + ); +} + +export function validateCollectOrders( + options: CollectOrdersOptions, + networkId: NetworkId +): void { + const { treasuryUtxo, orderUtxos } = options; + const config = LbeV2Constant.CONFIG[networkId]; + + const rawTreasuryDatum = treasuryUtxo.datum; + invariant(rawTreasuryDatum, "Treasury utxo must have inline datum"); + const treasuryDatum = LbeV2Types.TreasuryDatum.fromPlutusData( + networkId, + Data.from(rawTreasuryDatum) + ); + invariant( + config.treasuryAsset in treasuryUtxo.assets, + "Treasury utxo assets must have treasury asset" + ); + let collectAmount = 0n; + for (const orderUtxo of orderUtxos) { + const rawOrderDatum = orderUtxo.datum; + invariant(rawOrderDatum, "Order utxo must have inline datum"); + const orderDatum = LbeV2Types.OrderDatum.fromPlutusData( + Data.from(rawOrderDatum), + networkId + ); + invariant(orderDatum.isCollected === false, "Order must not be collected"); + invariant( + config.orderAsset in orderUtxo.assets, + "Order utxo assets must have order asset" + ); + invariant( + PoolV2.computeLPAssetName( + treasuryDatum.baseAsset, + treasuryDatum.raiseAsset + ) === + PoolV2.computeLPAssetName(orderDatum.baseAsset, orderDatum.raiseAsset), + "treasury, order must share the same lbe id" + ); + collectAmount += orderDatum.amount + orderDatum.penaltyAmount; + } + + const remainAmount = + treasuryDatum.reserveRaise + + treasuryDatum.totalPenalty - + treasuryDatum.collectedFund; + invariant( + treasuryDatum.isManagerCollected === true, + "LBE didn't collect manager" + ); + invariant( + orderUtxos.length >= LbeV2Constant.MINIMUM_ORDER_COLLECTED || + collectAmount === remainAmount, + `validateCollectOrders: not collect enough orders LBE having base asset ${treasuryDatum.baseAsset.toString()} and raise asset ${treasuryDatum.raiseAsset.toString()}` + ); +} + +export function validateRedeemOrders( + options: RedeemOrdersOptions, + networkId: NetworkId +): void { + const { treasuryUtxo, orderUtxos } = options; + const config = LbeV2Constant.CONFIG[networkId]; + + const rawTreasuryDatum = treasuryUtxo.datum; + invariant(rawTreasuryDatum, "Treasury utxo must have inline datum"); + const treasuryDatum = LbeV2Types.TreasuryDatum.fromPlutusData( + networkId, + Data.from(rawTreasuryDatum) + ); + invariant( + config.treasuryAsset in treasuryUtxo.assets, + "Treasury utxo assets must have treasury asset" + ); + let redeemAmount = 0n; + for (const orderUtxo of orderUtxos) { + const rawOrderDatum = orderUtxo.datum; + invariant(rawOrderDatum, "Order utxo must have inline datum"); + const orderDatum = LbeV2Types.OrderDatum.fromPlutusData( + Data.from(rawOrderDatum), + networkId + ); + invariant( + config.orderAsset in orderUtxo.assets, + "Order utxo assets must have order asset" + ); + invariant( + PoolV2.computeLPAssetName( + treasuryDatum.baseAsset, + treasuryDatum.raiseAsset + ) === + PoolV2.computeLPAssetName(orderDatum.baseAsset, orderDatum.raiseAsset), + "treasury, order must share the same lbe id" + ); + redeemAmount += orderDatum.amount + orderDatum.penaltyAmount; + } + + invariant(treasuryDatum.totalLiquidity > 0n, "LBE didn't create pool"); + invariant( + orderUtxos.length >= LbeV2Constant.MINIMUM_ORDER_REDEEMED || + redeemAmount === treasuryDatum.collectedFund, + `validateCollectOrders: not collect enough orders LBE having base asset ${treasuryDatum.baseAsset.toString()} and raise asset ${treasuryDatum.raiseAsset.toString()}` + ); +} + +export function validateRefundOrders( + options: RefundOrdersOptions, + networkId: NetworkId +): void { + const { treasuryUtxo, orderUtxos } = options; + const config = LbeV2Constant.CONFIG[networkId]; + + const rawTreasuryDatum = treasuryUtxo.datum; + invariant(rawTreasuryDatum, "Treasury utxo must have inline datum"); + const treasuryDatum = LbeV2Types.TreasuryDatum.fromPlutusData( + networkId, + Data.from(rawTreasuryDatum) + ); + invariant( + config.treasuryAsset in treasuryUtxo.assets, + "Treasury utxo assets must have treasury asset" + ); + let refundAmount = 0n; + for (const orderUtxo of orderUtxos) { + const rawOrderDatum = orderUtxo.datum; + invariant(rawOrderDatum, "Order utxo must have inline datum"); + const orderDatum = LbeV2Types.OrderDatum.fromPlutusData( + Data.from(rawOrderDatum), + networkId + ); + invariant( + config.orderAsset in orderUtxo.assets, + "Order utxo assets must have order asset" + ); + invariant( + PoolV2.computeLPAssetName( + treasuryDatum.baseAsset, + treasuryDatum.raiseAsset + ) === + PoolV2.computeLPAssetName(orderDatum.baseAsset, orderDatum.raiseAsset), + "treasury, order must share the same lbe id" + ); + refundAmount += orderDatum.amount + orderDatum.penaltyAmount; + } + + invariant(treasuryDatum.isCancelled === true, "LBE is not cancelled"); + invariant( + treasuryDatum.isManagerCollected === true, + "LBE didn't collect manager" + ); + invariant( + orderUtxos.length >= LbeV2Constant.MINIMUM_ORDER_REDEEMED || + refundAmount === treasuryDatum.collectedFund, + `validateCollectOrders: not collect enough orders LBE having base asset ${treasuryDatum.baseAsset.toString()} and raise asset ${treasuryDatum.raiseAsset.toString()}` + ); +} + +export function validateCreateAmmPool( + options: CreateAmmPoolTxOptions, + networkId: NetworkId +): void { + const { treasuryUtxo, ammFactoryUtxo } = options; + const rawTreasuryDatum = treasuryUtxo.datum; + invariant(rawTreasuryDatum, "Treasury utxo must have inline datum"); + const treasuryDatum = LbeV2Types.TreasuryDatum.fromPlutusData( + networkId, + Data.from(rawTreasuryDatum) + ); + + const rawAmmFactoryDatum = ammFactoryUtxo.datum; + invariant(rawAmmFactoryDatum, "Amm Factory utxo must have inline datum"); + const ammFactory = FactoryV2.Datum.fromPlutusData( + Data.from(rawAmmFactoryDatum) + ); + + const { + baseAsset, + raiseAsset, + isManagerCollected, + collectedFund, + reserveBase, + reserveRaise, + totalPenalty, + isCancelled, + minimumRaise, + totalLiquidity, + } = treasuryDatum; + + const lpAssetName = PoolV2.computeLPAssetName(baseAsset, raiseAsset); + + invariant( + lpAssetName > ammFactory.head && lpAssetName < ammFactory.tail, + "Invalid factory" + ); + invariant( + isManagerCollected && collectedFund === reserveRaise + totalPenalty, + "must collect all before create pool" + ); + invariant(!isCancelled, "LBE must not be cancelled"); + invariant(collectedFund >= (minimumRaise ?? 1n), "Lbe do not raise enough"); + + const initialLiquidity = DexV2Calculation.calculateInitialLiquidity({ + amountA: reserveBase, + amountB: reserveRaise + totalPenalty, + }); + invariant( + initialLiquidity > PoolV2.MINIMUM_LIQUIDITY, + "Can not create pool because initialLiquidity is too low" + ); + invariant(totalLiquidity === 0n, "Lbe creating is already success"); +} diff --git a/src/stableswap.ts b/src/stableswap.ts index d01656d..5805754 100644 --- a/src/stableswap.ts +++ b/src/stableswap.ts @@ -1,4 +1,3 @@ -import invariant from "@minswap/tiny-invariant"; import { Address, Assets, @@ -7,7 +6,8 @@ import { Lucid, TxComplete, UTxO, -} from "lucid-cardano"; +} from "@minswap/lucid-cardano"; +import invariant from "@minswap/tiny-invariant"; import { FIXED_DEPOSIT_ADA, diff --git a/src/syncer/repository/postgres-repository.ts b/src/syncer/repository/postgres-repository.ts index 48212a4..b899682 100644 --- a/src/syncer/repository/postgres-repository.ts +++ b/src/syncer/repository/postgres-repository.ts @@ -1,8 +1,8 @@ import * as OgmiosSchema from "@cardano-ogmios/schema"; +import { Data } from "@minswap/lucid-cardano"; import * as Prisma from "@prisma/client"; import { Decimal } from "@prisma/client/runtime/library"; import JSONBig from "json-bigint" -import { Data } from "lucid-cardano"; import { Asset } from "../../types/asset"; import { SECURITY_PARAM } from "../../types/constants"; diff --git a/src/types/address.internal.ts b/src/types/address.internal.ts index 796b322..bbfc5b9 100644 --- a/src/types/address.internal.ts +++ b/src/types/address.internal.ts @@ -1,4 +1,3 @@ -import invariant from "@minswap/tiny-invariant"; import { Address, C, @@ -6,7 +5,8 @@ import { Credential, Data, getAddressDetails, -} from "lucid-cardano"; +} from "@minswap/lucid-cardano"; +import invariant from "@minswap/tiny-invariant"; import { NetworkId } from "./network"; diff --git a/src/types/asset.ts b/src/types/asset.ts index 3ea18b8..5cf90fd 100644 --- a/src/types/asset.ts +++ b/src/types/asset.ts @@ -1,4 +1,5 @@ -import { Constr, Data } from "lucid-cardano"; +import { Constr, Data } from "@minswap/lucid-cardano"; +import invariant from "@minswap/tiny-invariant"; import { StringUtils } from "./string"; @@ -48,6 +49,10 @@ export namespace Asset { if (data.index !== 0) { throw new Error(`Index of Asset must be 0, actual: ${data.index}`) } + invariant( + data.fields.length === 2, + `Asset fields length must be 2, actual: ${data.fields.length}` + ); return { policyId: data.fields[0] as string, tokenName: data.fields[1] as string diff --git a/src/types/common.ts b/src/types/common.ts new file mode 100644 index 0000000..2b73f3b --- /dev/null +++ b/src/types/common.ts @@ -0,0 +1,68 @@ +import { Constr, Data } from "@minswap/lucid-cardano"; + +export namespace Options { + export function toPlutusData( + data: T | undefined, + toPlutusDataFn: (data: T) => Data + ): Constr { + return data !== undefined + ? new Constr(0, [toPlutusDataFn(data)]) + : new Constr(1, []); + } + + export function fromPlutusData( + data: Constr, + fromPlutusDataFn: (data: Data) => T + ): T | undefined { + switch (data.index) { + case 0: { + return fromPlutusDataFn(data.fields[0]); + } + case 1: { + return undefined; + } + default: { + throw Error(`Index of Options must be 0 or 1, actual: ${data.index}`); + } + } + } +} + +export namespace Bool { + export function toPlutusData(data: boolean): Constr { + return data ? new Constr(1, []) : new Constr(0, []); + } + + export function fromPlutusData(data: Constr): boolean { + switch (data.index) { + case 0: { + return false; + } + case 1: { + return true; + } + default: { + throw Error(`Index of Bool must be 0 or 1, actual: ${data.index}`); + } + } + } +} + +export namespace RedeemerWrapper { + export function toPlutusData(d: Data): Data { + return new Constr(1, [d]); + } + + export function fromPlutusData(data: Constr): Data { + switch (data.index) { + case 1: { + return data.fields[0]; + } + default: { + throw Error( + `Index of RedeemerWrapper must be 1, actual: ${data.index}` + ); + } + } + } +} diff --git a/src/types/constants.ts b/src/types/constants.ts index e76d033..7c73380 100644 --- a/src/types/constants.ts +++ b/src/types/constants.ts @@ -1,5 +1,5 @@ +import { Address, OutRef, Script } from "@minswap/lucid-cardano"; import invariant from "@minswap/tiny-invariant"; -import { Address, OutRef, Script } from "lucid-cardano"; import { Asset } from ".."; import { NetworkEnvironment, NetworkId } from "./network"; @@ -11,11 +11,15 @@ export namespace DexV1Constant { [NetworkId.MAINNET]: "addr1zxn9efv2f6w82hagxqtn62ju4m293tqvw0uhmdl64ch8uw6j2c79gy9l76sdg0xwhd7r0c0kna0tycz4y5s6mlenh8pq6s3z70", }; - export const POOL_SCRIPT_HASH = "script1uychk9f04tqngfhx4qlqdlug5ntzen3uzc62kzj7cyesjk0d9me"; - export const FACTORY_POLICY_ID = "13aa2accf2e1561723aa26871e071fdf32c867cff7e7d50ad470d62f"; + export const POOL_SCRIPT_HASH = + "script1uychk9f04tqngfhx4qlqdlug5ntzen3uzc62kzj7cyesjk0d9me"; + export const FACTORY_POLICY_ID = + "13aa2accf2e1561723aa26871e071fdf32c867cff7e7d50ad470d62f"; export const FACTORY_ASSET_NAME = "4d494e53574150"; - export const LP_POLICY_ID = "e4214b7cce62ac6fbba385d164df48e157eae5863521b4b67ca71d86"; - export const POOL_NFT_POLICY_ID = "0be55d262b29f564998ff81efe21bdc0022621c12f15af08d0f2ddb1"; + export const LP_POLICY_ID = + "e4214b7cce62ac6fbba385d164df48e157eae5863521b4b67ca71d86"; + export const POOL_NFT_POLICY_ID = + "0be55d262b29f564998ff81efe21bdc0022621c12f15af08d0f2ddb1"; export const ORDER_SCRIPT: Script = { type: "PlutusV1", script: @@ -183,168 +187,168 @@ export namespace StableswapConstant { > = { [NetworkId.TESTNET]: { "06fe1ba957728130154154d5e5b25a7b533ebe6c4516356c0aa69355646a65642d697573642d76312e342d6c70": - { - order: { - txHash: - "527e421bc3eb8b9e5ec0a9ad214bb9b76148f57b9a5a8cbd83a51264f943e91d", - outputIndex: 0, - }, - pool: { - txHash: - "527e421bc3eb8b9e5ec0a9ad214bb9b76148f57b9a5a8cbd83a51264f943e91d", - outputIndex: 1, - }, - lp: { - txHash: - "527e421bc3eb8b9e5ec0a9ad214bb9b76148f57b9a5a8cbd83a51264f943e91d", - outputIndex: 2, - }, - poolBatching: { - txHash: - "527e421bc3eb8b9e5ec0a9ad214bb9b76148f57b9a5a8cbd83a51264f943e91d", - outputIndex: 3, + { + order: { + txHash: + "527e421bc3eb8b9e5ec0a9ad214bb9b76148f57b9a5a8cbd83a51264f943e91d", + outputIndex: 0, + }, + pool: { + txHash: + "527e421bc3eb8b9e5ec0a9ad214bb9b76148f57b9a5a8cbd83a51264f943e91d", + outputIndex: 1, + }, + lp: { + txHash: + "527e421bc3eb8b9e5ec0a9ad214bb9b76148f57b9a5a8cbd83a51264f943e91d", + outputIndex: 2, + }, + poolBatching: { + txHash: + "527e421bc3eb8b9e5ec0a9ad214bb9b76148f57b9a5a8cbd83a51264f943e91d", + outputIndex: 3, + }, }, - }, "06fe1ba957728130154154d5e5b25a7b533ebe6c4516356c0aa69355757364632d757364742d76312e342d6c70": - { - order: { - txHash: - "cf699550642c8ffc1673d1e5d56d8562ca7c7f5c0b513a8428c3f52cdcc8fdb7", - outputIndex: 0, - }, - pool: { - txHash: - "cf699550642c8ffc1673d1e5d56d8562ca7c7f5c0b513a8428c3f52cdcc8fdb7", - outputIndex: 1, - }, - lp: { - txHash: - "cf699550642c8ffc1673d1e5d56d8562ca7c7f5c0b513a8428c3f52cdcc8fdb7", - outputIndex: 2, + { + order: { + txHash: + "cf699550642c8ffc1673d1e5d56d8562ca7c7f5c0b513a8428c3f52cdcc8fdb7", + outputIndex: 0, + }, + pool: { + txHash: + "cf699550642c8ffc1673d1e5d56d8562ca7c7f5c0b513a8428c3f52cdcc8fdb7", + outputIndex: 1, + }, + lp: { + txHash: + "cf699550642c8ffc1673d1e5d56d8562ca7c7f5c0b513a8428c3f52cdcc8fdb7", + outputIndex: 2, + }, + poolBatching: { + txHash: + "cf699550642c8ffc1673d1e5d56d8562ca7c7f5c0b513a8428c3f52cdcc8fdb7", + outputIndex: 3, + }, }, - poolBatching: { - txHash: - "cf699550642c8ffc1673d1e5d56d8562ca7c7f5c0b513a8428c3f52cdcc8fdb7", - outputIndex: 3, - }, - }, "06fe1ba957728130154154d5e5b25a7b533ebe6c4516356c0aa69355646a65642d697573642d6461692d76312e342d6c70": - { - order: { - txHash: - "a8ab602259654697c85e2f61752d34cdb631f314eaeded0676fee6f6be70afe7", - outputIndex: 0, - }, - pool: { - txHash: - "a8ab602259654697c85e2f61752d34cdb631f314eaeded0676fee6f6be70afe7", - outputIndex: 1, + { + order: { + txHash: + "a8ab602259654697c85e2f61752d34cdb631f314eaeded0676fee6f6be70afe7", + outputIndex: 0, + }, + pool: { + txHash: + "a8ab602259654697c85e2f61752d34cdb631f314eaeded0676fee6f6be70afe7", + outputIndex: 1, + }, + lp: { + txHash: + "a8ab602259654697c85e2f61752d34cdb631f314eaeded0676fee6f6be70afe7", + outputIndex: 2, + }, + poolBatching: { + txHash: + "a8ab602259654697c85e2f61752d34cdb631f314eaeded0676fee6f6be70afe7", + outputIndex: 3, + }, }, - lp: { - txHash: - "a8ab602259654697c85e2f61752d34cdb631f314eaeded0676fee6f6be70afe7", - outputIndex: 2, - }, - poolBatching: { - txHash: - "a8ab602259654697c85e2f61752d34cdb631f314eaeded0676fee6f6be70afe7", - outputIndex: 3, - }, - }, }, [NetworkId.MAINNET]: { "5d4b6afd3344adcf37ccef5558bb87f522874578c32f17160512e398444a45442d695553442d534c50": - { - order: { - txHash: - "20227174ec2f7853a71a02c435d063b3bf63851d4e0ad9a0c09250a087a6577e", - outputIndex: 0, - }, - pool: { - txHash: - "20227174ec2f7853a71a02c435d063b3bf63851d4e0ad9a0c09250a087a6577e", - outputIndex: 1, - }, - lp: { - txHash: - "20227174ec2f7853a71a02c435d063b3bf63851d4e0ad9a0c09250a087a6577e", - outputIndex: 2, - }, - poolBatching: { - txHash: - "20227174ec2f7853a71a02c435d063b3bf63851d4e0ad9a0c09250a087a6577e", - outputIndex: 3, + { + order: { + txHash: + "20227174ec2f7853a71a02c435d063b3bf63851d4e0ad9a0c09250a087a6577e", + outputIndex: 0, + }, + pool: { + txHash: + "20227174ec2f7853a71a02c435d063b3bf63851d4e0ad9a0c09250a087a6577e", + outputIndex: 1, + }, + lp: { + txHash: + "20227174ec2f7853a71a02c435d063b3bf63851d4e0ad9a0c09250a087a6577e", + outputIndex: 2, + }, + poolBatching: { + txHash: + "20227174ec2f7853a71a02c435d063b3bf63851d4e0ad9a0c09250a087a6577e", + outputIndex: 3, + }, }, - }, d97fa91daaf63559a253970365fb219dc4364c028e5fe0606cdbfff9555344432d444a45442d534c50: - { - order: { - txHash: - "8b880e77a726e76e5dd585cda2c4c2ac93f1cfccc06910f00550fb820ae1fc54", - outputIndex: 0, - }, - pool: { - txHash: - "8b880e77a726e76e5dd585cda2c4c2ac93f1cfccc06910f00550fb820ae1fc54", - outputIndex: 1, + { + order: { + txHash: + "8b880e77a726e76e5dd585cda2c4c2ac93f1cfccc06910f00550fb820ae1fc54", + outputIndex: 0, + }, + pool: { + txHash: + "8b880e77a726e76e5dd585cda2c4c2ac93f1cfccc06910f00550fb820ae1fc54", + outputIndex: 1, + }, + lp: { + txHash: + "8b880e77a726e76e5dd585cda2c4c2ac93f1cfccc06910f00550fb820ae1fc54", + outputIndex: 2, + }, + poolBatching: { + txHash: + "8b880e77a726e76e5dd585cda2c4c2ac93f1cfccc06910f00550fb820ae1fc54", + outputIndex: 3, + }, }, - lp: { - txHash: - "8b880e77a726e76e5dd585cda2c4c2ac93f1cfccc06910f00550fb820ae1fc54", - outputIndex: 2, - }, - poolBatching: { - txHash: - "8b880e77a726e76e5dd585cda2c4c2ac93f1cfccc06910f00550fb820ae1fc54", - outputIndex: 3, - }, - }, "96402c6f5e7a04f16b4d6f500ab039ff5eac5d0226d4f88bf5523ce85553444d2d695553442d534c50": - { - order: { - txHash: - "48019a931af442e1eedab6c5b52b3069cf6eadb2483a2131f517e62fddfd5662", - outputIndex: 0, - }, - pool: { - txHash: - "48019a931af442e1eedab6c5b52b3069cf6eadb2483a2131f517e62fddfd5662", - outputIndex: 1, - }, - lp: { - txHash: - "48019a931af442e1eedab6c5b52b3069cf6eadb2483a2131f517e62fddfd5662", - outputIndex: 2, - }, - poolBatching: { - txHash: - "48019a931af442e1eedab6c5b52b3069cf6eadb2483a2131f517e62fddfd5662", - outputIndex: 3, + { + order: { + txHash: + "48019a931af442e1eedab6c5b52b3069cf6eadb2483a2131f517e62fddfd5662", + outputIndex: 0, + }, + pool: { + txHash: + "48019a931af442e1eedab6c5b52b3069cf6eadb2483a2131f517e62fddfd5662", + outputIndex: 1, + }, + lp: { + txHash: + "48019a931af442e1eedab6c5b52b3069cf6eadb2483a2131f517e62fddfd5662", + outputIndex: 2, + }, + poolBatching: { + txHash: + "48019a931af442e1eedab6c5b52b3069cf6eadb2483a2131f517e62fddfd5662", + outputIndex: 3, + }, }, - }, "07b0869ed7488657e24ac9b27b3f0fb4f76757f444197b2a38a15c3c444a45442d5553444d2d534c50": - { - order: { - txHash: - "dddccee9cd58cbf712f2ff2c49ea20537db681a333c701106aa13cd57aee3873", - outputIndex: 0, - }, - pool: { - txHash: - "dddccee9cd58cbf712f2ff2c49ea20537db681a333c701106aa13cd57aee3873", - outputIndex: 1, - }, - lp: { - txHash: - "dddccee9cd58cbf712f2ff2c49ea20537db681a333c701106aa13cd57aee3873", - outputIndex: 2, + { + order: { + txHash: + "dddccee9cd58cbf712f2ff2c49ea20537db681a333c701106aa13cd57aee3873", + outputIndex: 0, + }, + pool: { + txHash: + "dddccee9cd58cbf712f2ff2c49ea20537db681a333c701106aa13cd57aee3873", + outputIndex: 1, + }, + lp: { + txHash: + "dddccee9cd58cbf712f2ff2c49ea20537db681a333c701106aa13cd57aee3873", + outputIndex: 2, + }, + poolBatching: { + txHash: + "dddccee9cd58cbf712f2ff2c49ea20537db681a333c701106aa13cd57aee3873", + outputIndex: 3, + }, }, - poolBatching: { - txHash: - "dddccee9cd58cbf712f2ff2c49ea20537db681a333c701106aa13cd57aee3873", - outputIndex: 3, - }, - }, }, }; @@ -385,6 +389,7 @@ export namespace StableswapConstant { } export namespace DexV2Constant { + export const DEFAULT_CANCEL_TIPS = 300_000n; export type Config = { factoryAsset: string; poolAuthenAsset: string; @@ -393,6 +398,7 @@ export namespace DexV2Constant { globalSettingScriptHash: string; globalSettingScriptHashBech32: string; orderScriptHash: string; + orderScriptHashBech32: string; poolScriptHash: string; poolScriptHashBech32: string; poolCreationAddress: Address; @@ -428,6 +434,8 @@ export namespace DexV2Constant { "script1664wypvm4msc3a6fzayneamr0enee5sehham7nwtavwsk2s2vg9", orderScriptHash: "da9525463841173ad1230b1d5a1b5d0a3116bbdeb4412327148a1b7a", + orderScriptHashBech32: + "script1m22j233cgytn45frpvw45x6apgc3dw77k3qjxfc53gdh5cejhly", poolScriptHash: "d6ba9b7509eac866288ff5072d2a18205ac56f744bc82dcd808cb8fe", poolScriptHashBech32: @@ -461,6 +469,8 @@ export namespace DexV2Constant { "script17kqgctyepkrd549le97cnnhxa73qekzxzctrt9rcm945c880puk", orderScriptHash: "c3e28c36c3447315ba5a56f33da6a6ddc1770a876a8d9f0cb3a97c4c", + orderScriptHashBech32: + "script1c03gcdkrg3e3twj62menmf4xmhqhwz58d2xe7r9n497yc6r9qhd", poolScriptHash: "ea07b733d932129c378af627436e7cbc2ef0bf96e0036bb51b3bde6b", poolScriptHashBech32: @@ -550,9 +560,216 @@ export namespace DexV2Constant { }; } +export namespace LbeV2Constant { + export const FACTORY_AUTH_AN = "666163746f7279"; + export const TREASURY_AUTH_AN = "7472656173757279"; + export const MANAGER_AUTH_AN = "4d616e61676572"; + export const SELLER_AUTH_AN = "73656c6c6572"; + export const ORDER_AUTH_AN = "6f72646572"; + + export const ORDER_COMMISSION = 250_000n; + export const COLLECT_SELLER_COMMISSION = 250_000n; + export const SELLER_COMMISSION = 1_500_000n; + export const CREATE_POOL_COMMISSION = 10_000_000n; + + export const TREASURY_MIN_ADA = 5_000_000n; + export const MANAGER_MIN_ADA = 2_500_000n; + export const SELLER_MIN_ADA = 2_500_000n; + export const ORDER_MIN_ADA = 2_500_000n; + + export const MIN_POOL_ALLOCATION_POINT = 70n; + export const MAX_POOL_ALLOCATION_POINT = 100n; + export const MAX_PENALTY_RATE = 25n; + + export const MINIMUM_SELLER_COLLECTED = 20; + export const MINIMUM_ORDER_COLLECTED = 30; + export const MINIMUM_ORDER_REDEEMED = 30; + + export const MAX_DISCOVERY_RANGE = 2592000000n; + export const MAX_PENALTY_RANGE = 172800000n; + + export const DEFAULT_SELLER_COUNT = 20n; + + export type Config = { + factoryAsset: string; + factoryHash: string; + factoryHashBech32: string; + factoryAddress: string; + factoryRewardAddress: string; + + treasuryAsset: string; + treasuryHash: string; + treasuryHashBech32: string; + treasuryAddress: string; + + managerAsset: string; + managerHash: string; + managerHashBech32: string; + managerAddress: string; + + sellerAsset: string; + sellerHash: string; + sellerHashBech32: string; + sellerAddress: string; + + orderAsset: string; + orderHash: string; + orderHashBech32: string; + orderAddress: string; + }; + + export type DeployedScripts = { + factory: OutRef; + treasury: OutRef; + manager: OutRef; + seller: OutRef; + order: OutRef; + }; + const TESTNET_FACTORY_HASH = + "7f2f769a9260eb698232022af03fba12ef0a29f94fc93c4fd2624972"; + const MAINNET_FACTORY_HASH = + "dea947ac55fb4c2c38bb11341f2b82b2d62e1a120330f82dc1e56ead"; + export const CONFIG: Record = { + [NetworkId.TESTNET]: { + factoryAsset: TESTNET_FACTORY_HASH + FACTORY_AUTH_AN, + factoryHash: TESTNET_FACTORY_HASH, + factoryHashBech32: + "script10uhhdx5jvr4knq3jqg40q0a6zths520eflyncn7jvfyhyqahrl3", + factoryAddress: + "addr_test1wplj7a56jfswk6vzxgpz4uplhgfw7z3fl98uj0z06f3yjusz7ufvk", + factoryRewardAddress: + "stake_test17plj7a56jfswk6vzxgpz4uplhgfw7z3fl98uj0z06f3yjuszkz3mu", + + treasuryAsset: TESTNET_FACTORY_HASH + TREASURY_AUTH_AN, + treasuryHash: "f0dbf7cdc1042f403cad57cff6f602b2e657f8f557b8cf8c23482954", + treasuryHashBech32: + "script17rdl0nwpqsh5q09d2l8ldaszktn9078427uvlrprfq54gr7nrx6", + treasuryAddress: + "addr_test1wrcdha7dcyzz7spu44tulahkq2ewv4lc74tm3nuvydyzj4qx8r0da", + + managerAsset: TESTNET_FACTORY_HASH + MANAGER_AUTH_AN, + managerHash: "46246888d57347a8ad2705843e9131f03e55701571896ed571f90e3a", + managerHashBech32: + "script1gcjx3zx4wdr63tf8qkzrayf37ql92uq4wxyka4t3ly8r5kjsrlk", + managerAddress: + "addr_test1wprzg6yg64e5029dyuzcg053x8cru4tsz4ccjmk4w8usuwsp4y75x", + + sellerAsset: TESTNET_FACTORY_HASH + SELLER_AUTH_AN, + sellerHash: "f6ba0fa37ce6aaaf8da7b0ee4192361fd443a8d3d70fb275986a2fce", + sellerHashBech32: + "script176aqlgmuu642lrd8krhyry3krl2y82xn6u8myavcdghuukmdwrq", + sellerAddress: + "addr_test1wrmt5rar0nn24tud57cwusvjxc0agsag60tslvn4np4zlnszyuccc", + + orderAsset: TESTNET_FACTORY_HASH + ORDER_AUTH_AN, + orderHash: "28ead81adf8154687e0d1d09d14375f6be0626107545a59d7d5e311a", + orderHashBech32: + "script19r4dsxkls92xslsdr5yazsm476lqvfssw4z6t8tatcc350sd37w", + orderAddress: + "addr_test1zq5w4kq6m7q4g6r7p5wsn52rwhmtup3xzp65tfva040rzx5rajt8r8wqtygrfduwgukk73m5gcnplmztc5tl5ngy0upqqym3e9", + }, + [NetworkId.MAINNET]: { + factoryAsset: MAINNET_FACTORY_HASH + FACTORY_AUTH_AN, + factoryHash: MAINNET_FACTORY_HASH, + factoryHashBech32: + "script1m6550tz4ldxzcw9mzy6p72uzkttzuxsjqvc0stwpu4h26pl45ch", + factoryAddress: + "addr1w802j3av2ha5ctpchvgng8ets2edvts6zgpnp7pdc8jkatgwxaxhw", + factoryRewardAddress: + "stake17802j3av2ha5ctpchvgng8ets2edvts6zgpnp7pdc8jkatgjvaqtu", + + treasuryAsset: MAINNET_FACTORY_HASH + TREASURY_AUTH_AN, + treasuryHash: "1ce6abbd967cab867ad73855f8b154fcc57e41b15605b91590451650", + treasuryHashBech32: + "script1rnn2h0vk0j4cv7kh8p2l3v25lnzhusd32czmj9vsg5t9q69xnhh", + treasuryAddress: + "addr1wywwd2aaje72hpn66uu9t7932n7v2ljpk9tqtwg4jpz3v5qpqs70n", + + managerAsset: MAINNET_FACTORY_HASH + MANAGER_AUTH_AN, + managerHash: "e951d381ef510ae02b7496c2ff039e640ab2e2a561423d0cbf34b032", + managerHashBech32: + "script1a9ga8q002y9wq2m5jmp07qu7vs9t9c49v9pr6r9lxjcry2xehgl", + managerAddress: + "addr1w854r5upaags4cptwjtv9lcrnejq4vhz54s5y0gvhu6tqvsccjry6", + + sellerAsset: MAINNET_FACTORY_HASH + SELLER_AUTH_AN, + sellerHash: "ecf97d6f0ace26e69fa428610c7dbf5a686e1197f76511449d9a1b64", + sellerHashBech32: + "script1anuh6mc2ecnwd8ay9psscldltf5xuyvh7aj3z3yangdkgh7ds8d", + sellerAddress: + "addr1w8k0jlt0pt8zde5l5s5xzrrahadxsms3jlmk2y2ynkdpkeqn95g7r", + + orderAsset: MAINNET_FACTORY_HASH + ORDER_AUTH_AN, + orderHash: "5176775eed690d088bd29d9a6934b1e35ef1d897deb61d7b5dde11ca", + orderHashBech32: + "script129m8whhddyxs3z7jnkdxjd93ud00rkyhm6mp676amcgu5kg5c44", + orderAddress: + "addr1z9ghva67a45s6zyt62we56f5k834auwcjl0tv8tmth0prjjj2c79gy9l76sdg0xwhd7r0c0kna0tycz4y5s6mlenh8pqsk3urw", + }, + }; + + export const DEPLOYED_SCRIPTS: Record = { + [NetworkId.TESTNET]: { + factory: { + txHash: + "834e0958594e51c525363bbdabd0cdbe773a358ac2e2c8321cc3f645b30335ae", + outputIndex: 0, + }, + treasury: { + txHash: + "a5b0274543fbad4ca79798be047317a0b4b270ab6011dd7e08fc663ba6ee1f32", + outputIndex: 0, + }, + manager: { + txHash: + "f0c8a033bf84faad54e70c9882057a422fa1ee257843fad0a07aa5eb7ee9ebaf", + outputIndex: 0, + }, + seller: { + txHash: + "a15c06f2fa3e91359136b346eae43997311644320e18a0c5f2ea40c8127c9284", + outputIndex: 0, + }, + order: { + txHash: + "a08042f93335157e6dd8e87feef448d5e9000f60ef14cbe19ae365c8de9bead8", + outputIndex: 0, + }, + }, + [NetworkId.MAINNET]: { + factory: { + txHash: + "6b9976bb251ad15a21480bd37ea45343cff6fdd713744c1948ce674a8c4f510f", + outputIndex: 0, + }, + treasury: { + txHash: + "bf343adb586dab792665d23a1c1fa8727d2014e58630d007598296586782018d", + outputIndex: 0, + }, + manager: { + txHash: + "e8fb105295f8871670676fe2162f6a301c8413f8273a23cd1fde7c5f960db0af", + outputIndex: 0, + }, + seller: { + txHash: + "590ece2aa32fdc11c27a99ffe50392f8329e1645e9c3249cf0e3c3cd77cfa4e3", + outputIndex: 0, + }, + order: { + txHash: + "314cfc020092185a666cfc9d8d747dd0760358bc1cf06385343b97041b3c90ed", + outputIndex: 0, + }, + }, + }; +} + export enum MetadataMessage { DEPOSIT_ORDER = "SDK Minswap: Deposit Order", CANCEL_ORDER = "SDK Minswap: Cancel Order", + CANCEL_ORDERS_AUTOMATICALLY = "SDK Minswap: Cancel Orders Automatically", ZAP_IN_ORDER = "SDK Minswap: Zap Order", ZAP_OUT_ORDER = "SDK Minswap: Zap Out Order", SWAP_EXACT_IN_ORDER = "SDK Minswap: Swap Exact In Order", @@ -566,6 +783,21 @@ export enum MetadataMessage { DONATION_ORDER = "Minswap: Donation Order", MIXED_ORDERS = "SDK Minswap: Mixed Orders", CREATE_POOL = "SDK Minswap: Create Pool", + // LAUNCH + CREATE_EVENT = "SDK Minswap: Create Event", + UPDATE_EVENT = "SDK Minswap: Update Event", + CANCEL_EVENT_BY_OWNER = "SDK Minswap: Cancel Event By Onwer", + CANCEL_EVENT_BY_WORKER = "SDK Minswap: Cancel Event By Worker", + LBE_V2_DEPOSIT_ORDER_EVENT = "SDK Minswap: Deposit Lbe V2 Order", + LBE_V2_WITHDRAW_ORDER_EVENT = "SDK Minswap: Withdraw Lbe V2 Order", + CLOSE_EVENT = "SDK Minswap: Close Event", + LBE_V2_ADD_SELLERS = "SDK Minswap: Lbe V2 add more sellers", + LBE_V2_COUNTING_SELLERS = "SDK Minswap: Lbe V2 counting sellers", + LBE_V2_COLLECT_MANAGER = "SDK Minswap: Lbe V2 collect manager", + LBE_V2_COLLECT_ORDER = "SDK Minswap: Lbe V2 collect order", + LBE_V2_REDEEM_LP = "SDK Minswap: Lbe V2 redeem lp", + LBE_V2_REFUND = "SDK Minswap: Lbe V2 refund", + LBE_V2_CREATE_AMM_POOL = "SDK Minswap: Lbe V2 create AMM pool", } export const FIXED_DEPOSIT_ADA = 2_000_000n; @@ -574,4 +806,4 @@ export const SECURITY_PARAM: Record = { [NetworkEnvironment.MAINNET]: 2160, [NetworkEnvironment.TESTNET_PREPROD]: 2160, [NetworkEnvironment.TESTNET_PREVIEW]: 2160, -} +}; diff --git a/src/types/factory.ts b/src/types/factory.ts index c496c9d..8a84ba7 100644 --- a/src/types/factory.ts +++ b/src/types/factory.ts @@ -1,4 +1,4 @@ -import { Constr, Data } from "lucid-cardano"; +import { Constr, Data } from "@minswap/lucid-cardano"; import { Asset } from "./asset"; import { DexV2Constant } from "./constants"; diff --git a/src/types/lbe-v2.ts b/src/types/lbe-v2.ts new file mode 100644 index 0000000..246b5a1 --- /dev/null +++ b/src/types/lbe-v2.ts @@ -0,0 +1,845 @@ +import { Address, Constr, Data } from "@minswap/lucid-cardano"; +import invariant from "@minswap/tiny-invariant"; + +import { Asset, LbeV2Constant, NetworkId, PoolV2 } from ".."; +import { AddressPlutusData } from "./address.internal"; +import { Bool, Options } from "./common"; +import { TxIn, Value } from "./tx.internal"; + +export namespace LbeV2Types { + export enum ReceiverDatumType { + NO_DATUM = 0, + DATUM_HASH, + INLINE_DATUM, + } + + export type ReceiverDatum = + | { + type: ReceiverDatumType.NO_DATUM; + } + | { + type: ReceiverDatumType.DATUM_HASH | ReceiverDatumType.INLINE_DATUM; + hash: string; + }; + + export namespace ReceiverDatum { + export function toPlutusData(data: ReceiverDatum): Constr { + switch (data.type) { + case ReceiverDatumType.NO_DATUM: { + return new Constr(0, []); + } + case ReceiverDatumType.DATUM_HASH: { + return new Constr(1, [data.hash]); + } + case ReceiverDatumType.INLINE_DATUM: { + return new Constr(2, [data.hash]); + } + } + } + + export function fromPlutusData(data: Constr): ReceiverDatum { + switch (data.index) { + case ReceiverDatumType.NO_DATUM: { + invariant( + data.fields.length === 0, + `NO_DATUM Receiver Datum fields length must be 0, actual: ${data.fields.length}` + ); + return { type: ReceiverDatumType.NO_DATUM }; + } + case ReceiverDatumType.DATUM_HASH: { + invariant( + data.fields.length === 1, + `DATUM_HASH Receiver Datum fields length must be 1, actual: ${data.fields.length}` + ); + return { + type: ReceiverDatumType.DATUM_HASH, + hash: data.fields[0] as string, + }; + } + case ReceiverDatumType.INLINE_DATUM: { + invariant( + data.fields.length === 1, + `INLINE_DATUM Receiver Datum fields length must be 1, actual: ${data.fields.length}` + ); + return { + type: ReceiverDatumType.INLINE_DATUM, + hash: data.fields[0] as string, + }; + } + default: { + throw Error( + `Index of Receiver Datum must be 0, 1 or 2, actual: ${data.index}` + ); + } + } + } + } + + export type PenaltyConfig = { + penaltyStartTime: bigint; + percent: bigint; + }; + + export namespace PenaltyConfig { + export function toPlutusData(data: PenaltyConfig): Constr { + return new Constr(0, [data.penaltyStartTime, data.percent]); + } + + export function fromPlutusData(data: Constr): PenaltyConfig { + switch (data.index) { + case 0: { + invariant( + data.fields.length === 2, + `Penalty Config fields length must be 2, actual: ${data.fields.length}` + ); + return { + penaltyStartTime: data.fields[0] as bigint, + percent: data.fields[1] as bigint, + }; + } + default: { + throw Error( + `Index of Penalty Config must be 0, actual: ${data.index}` + ); + } + } + } + } + + export type TreasuryDatum = { + factoryPolicyId: string; + managerHash: string; + sellerHash: string; + orderHash: string; + baseAsset: Asset; + + raiseAsset: Asset; + startTime: bigint; + endTime: bigint; + owner: Address; + receiver: Address; + + receiverDatum: ReceiverDatum; + poolAllocation: bigint; + minimumOrderRaise?: bigint; + minimumRaise?: bigint; + maximumRaise?: bigint; + + reserveBase: bigint; + penaltyConfig?: PenaltyConfig; + poolBaseFee: bigint; + revocable: boolean; + collectedFund: bigint; + + reserveRaise: bigint; + totalPenalty: bigint; + totalLiquidity: bigint; + isCancelled: boolean; + isManagerCollected: boolean; + }; + + export namespace TreasuryDatum { + export function toPlutusData(datum: TreasuryDatum): Constr { + const { + factoryPolicyId, + managerHash, + sellerHash, + orderHash, + baseAsset, + + raiseAsset, + startTime, + endTime, + owner, + receiver, + + receiverDatum, + poolAllocation, + minimumOrderRaise, + minimumRaise, + maximumRaise, + + reserveBase, + penaltyConfig, + poolBaseFee, + revocable, + collectedFund, + + reserveRaise, + totalPenalty, + totalLiquidity, + isCancelled, + isManagerCollected, + } = datum; + return new Constr(0, [ + factoryPolicyId, + managerHash, + sellerHash, + orderHash, + Asset.toPlutusData(baseAsset), + + Asset.toPlutusData(raiseAsset), + startTime, + endTime, + AddressPlutusData.toPlutusData(owner), + AddressPlutusData.toPlutusData(receiver), + + ReceiverDatum.toPlutusData(receiverDatum), + poolAllocation, + Options.toPlutusData(minimumOrderRaise, (x) => x), + Options.toPlutusData(minimumRaise, (x) => x), + Options.toPlutusData(maximumRaise, (x) => x), + + reserveBase, + Options.toPlutusData(penaltyConfig, PenaltyConfig.toPlutusData), + poolBaseFee, + Bool.toPlutusData(revocable), + collectedFund, + + reserveRaise, + totalPenalty, + totalLiquidity, + Bool.toPlutusData(isCancelled), + Bool.toPlutusData(isManagerCollected), + ]); + } + + export function fromPlutusData( + networkId: NetworkId, + data: Constr + ): TreasuryDatum { + if (data.index !== 0) { + throw new Error( + `Index of Treasury Datum must be 0, actual: ${data.index}` + ); + } + + invariant( + data.fields.length === 25, + `Treasury Datum fields length must be 25, actual: ${data.fields.length}` + ); + const fields = data.fields; + return { + factoryPolicyId: fields[0] as string, + managerHash: fields[1] as string, + sellerHash: fields[2] as string, + orderHash: fields[3] as string, + baseAsset: Asset.fromPlutusData(fields[4] as Constr), + + raiseAsset: Asset.fromPlutusData(fields[5] as Constr), + startTime: fields[6] as bigint, + endTime: fields[7] as bigint, + owner: AddressPlutusData.fromPlutusData( + networkId, + fields[8] as Constr + ), + receiver: AddressPlutusData.fromPlutusData( + networkId, + fields[9] as Constr + ), + + receiverDatum: ReceiverDatum.fromPlutusData(fields[10] as Constr), + poolAllocation: fields[11] as bigint, + minimumOrderRaise: Options.fromPlutusData( + fields[12] as Constr, + (data) => data as bigint + ), + minimumRaise: Options.fromPlutusData( + fields[13] as Constr, + (data) => data as bigint + ), + maximumRaise: Options.fromPlutusData( + fields[14] as Constr, + (data) => data as bigint + ), + + reserveBase: fields[15] as bigint, + penaltyConfig: Options.fromPlutusData( + fields[16] as Constr, + (data) => PenaltyConfig.fromPlutusData(data as Constr) + ), + poolBaseFee: fields[17] as bigint, + revocable: Bool.fromPlutusData(fields[18] as Constr), + collectedFund: fields[19] as bigint, + + reserveRaise: fields[20] as bigint, + totalPenalty: fields[21] as bigint, + totalLiquidity: fields[22] as bigint, + isCancelled: Bool.fromPlutusData(fields[23] as Constr), + isManagerCollected: Bool.fromPlutusData(fields[24] as Constr), + }; + } + } + + export enum TreasuryRedeemerType { + COLLECT_MANAGER = 0, + COLLECT_ORDERS = 1, + CREATE_AMM_POOL = 2, + REDEEM_ORDERS = 3, + CLOSE_EVENT = 4, + CANCEL_LBE = 5, + UPDATE_LBE = 6, + } + + export enum CancelReason { + CREATED_POOL = 0, + BY_OWNER = 1, + NOT_REACH_MINIMUM = 2, + } + + export type TreasuryRedeemer = + | { + type: + | TreasuryRedeemerType.COLLECT_MANAGER + | TreasuryRedeemerType.COLLECT_ORDERS + | TreasuryRedeemerType.CREATE_AMM_POOL + | TreasuryRedeemerType.REDEEM_ORDERS + | TreasuryRedeemerType.CLOSE_EVENT + | TreasuryRedeemerType.UPDATE_LBE; + } + | { + type: TreasuryRedeemerType.CANCEL_LBE; + reason: CancelReason; + }; + + export namespace TreasuryRedeemer { + export function toPlutusData(data: TreasuryRedeemer): Constr { + switch (data.type) { + case TreasuryRedeemerType.COLLECT_MANAGER: + case TreasuryRedeemerType.COLLECT_ORDERS: + case TreasuryRedeemerType.CREATE_AMM_POOL: + case TreasuryRedeemerType.REDEEM_ORDERS: + case TreasuryRedeemerType.CLOSE_EVENT: + case TreasuryRedeemerType.UPDATE_LBE: { + return new Constr(data.type, []); + } + case TreasuryRedeemerType.CANCEL_LBE: { + return new Constr(data.type, [new Constr(data.reason, [])]); + } + } + } + } + + export class TreasuryState { + public readonly address: string; + public readonly txIn: TxIn; + public readonly value: Value; + public readonly datumCbor: string; + public readonly datum: TreasuryDatum; + + constructor( + networkId: NetworkId, + address: string, + txIn: TxIn, + value: Value, + datum: string + ) { + this.address = address; + this.txIn = txIn; + this.value = value; + this.datumCbor = datum; + this.datum = TreasuryDatum.fromPlutusData(networkId, Data.from(datum)); + + const config = LbeV2Constant.CONFIG[networkId]; + if ( + !value.find( + (v) => v.unit === config.treasuryAsset && v.quantity === "1" + ) + ) { + throw new Error( + "Cannot find the Treasury Authentication Asset in the value" + ); + } + } + + get lbeId(): string { + return PoolV2.computeLPAssetName( + this.datum.baseAsset, + this.datum.raiseAsset + ); + } + } + + export type LbeV2Parameters = { + baseAsset: Asset; + reserveBase: bigint; + raiseAsset: Asset; + startTime: bigint; + endTime: bigint; + owner: Address; + receiver: Address; + poolAllocation: bigint; + minimumOrderRaise?: bigint; + minimumRaise?: bigint; + maximumRaise?: bigint; + penaltyConfig?: PenaltyConfig; + revocable: boolean; + poolBaseFee: bigint; + }; + + export namespace LbeV2Parameters { + export function toLbeV2TreasuryDatum( + networkId: NetworkId, + lbeV2Parameters: LbeV2Parameters + ): TreasuryDatum { + const config = LbeV2Constant.CONFIG[networkId]; + const treasuryDatum: TreasuryDatum = { + factoryPolicyId: config.factoryHash, + managerHash: config.managerHash, + sellerHash: config.sellerHash, + orderHash: config.orderHash, + baseAsset: lbeV2Parameters.baseAsset, + + raiseAsset: lbeV2Parameters.raiseAsset, + startTime: lbeV2Parameters.startTime, + endTime: lbeV2Parameters.endTime, + owner: lbeV2Parameters.owner, + receiver: lbeV2Parameters.receiver, + + receiverDatum: { + type: ReceiverDatumType.NO_DATUM, + }, + poolAllocation: lbeV2Parameters.poolAllocation, + minimumOrderRaise: lbeV2Parameters.minimumOrderRaise, + minimumRaise: lbeV2Parameters.minimumRaise, + maximumRaise: lbeV2Parameters.maximumRaise, + + reserveBase: lbeV2Parameters.reserveBase, + penaltyConfig: lbeV2Parameters.penaltyConfig, + poolBaseFee: lbeV2Parameters.poolBaseFee, + revocable: lbeV2Parameters.revocable, + collectedFund: 0n, + + reserveRaise: 0n, + totalPenalty: 0n, + totalLiquidity: 0n, + isCancelled: false, + isManagerCollected: false, + }; + return treasuryDatum; + } + } + + export type FactoryDatum = { + head: string; + tail: string; + }; + + export namespace FactoryDatum { + export function toPlutusData(data: FactoryDatum): Constr { + return new Constr(0, [data.head, data.tail]); + } + + export function fromPlutusData(data: Constr): FactoryDatum { + switch (data.index) { + case 0: { + invariant( + data.fields.length === 2, + `Factory Datum fields length must be 2, actual: ${data.fields.length}` + ); + return { + head: data.fields[0] as string, + tail: data.fields[1] as string, + }; + } + default: { + throw Error(`Index of FactoryDatum must be 0, actual: ${data.index}`); + } + } + } + } + + export enum FactoryRedeemerType { + INITIALIZATION = 0, + CREATE_TREASURY = 1, + CLOSE_TREASURY = 2, + MINT_MANAGER = 3, + MINT_SELLER = 4, + BURN_SELLER = 5, + MINT_ORDER = 6, + MINT_REDEEM_ORDERS = 7, + MANAGE_ORDER = 8, + } + + export type FactoryRedeemer = + | { + type: + | FactoryRedeemerType.INITIALIZATION + | FactoryRedeemerType.MINT_MANAGER + | FactoryRedeemerType.MINT_SELLER + | FactoryRedeemerType.BURN_SELLER + | FactoryRedeemerType.MINT_ORDER + | FactoryRedeemerType.MINT_REDEEM_ORDERS + | FactoryRedeemerType.MANAGE_ORDER; + } + | { + type: + | FactoryRedeemerType.CREATE_TREASURY + | FactoryRedeemerType.CLOSE_TREASURY; + baseAsset: Asset; + raiseAsset: Asset; + }; + + export namespace FactoryRedeemer { + export function toPlutusData(data: FactoryRedeemer): Constr { + switch (data.type) { + case FactoryRedeemerType.INITIALIZATION: + case FactoryRedeemerType.MINT_MANAGER: + case FactoryRedeemerType.MINT_SELLER: + case FactoryRedeemerType.BURN_SELLER: + case FactoryRedeemerType.MINT_ORDER: + case FactoryRedeemerType.MINT_REDEEM_ORDERS: + case FactoryRedeemerType.MANAGE_ORDER: { + return new Constr(data.type, []); + } + case FactoryRedeemerType.CREATE_TREASURY: + case FactoryRedeemerType.CLOSE_TREASURY: { + return new Constr(data.type, [ + Asset.toPlutusData(data.baseAsset), + Asset.toPlutusData(data.raiseAsset), + ]); + } + } + } + } + + export class FactoryState { + public readonly address: string; + public readonly txIn: TxIn; + public readonly value: Value; + public readonly datumCbor: string; + public readonly datum: FactoryDatum; + + constructor( + networkId: NetworkId, + address: string, + txIn: TxIn, + value: Value, + datum: string + ) { + this.address = address; + this.txIn = txIn; + this.value = value; + this.datumCbor = datum; + this.datum = FactoryDatum.fromPlutusData(Data.from(datum)); + + const config = LbeV2Constant.CONFIG[networkId]; + if ( + !value.find((v) => v.unit === config.factoryAsset && v.quantity === "1") + ) { + throw new Error( + "Cannot find the Factory Authentication Asset in the value" + ); + } + } + + get head(): string { + return this.datum.head; + } + + get tail(): string { + return this.datum.tail; + } + } + + export type ManagerDatum = { + factoryPolicyId: string; + baseAsset: Asset; + raiseAsset: Asset; + sellerCount: bigint; + reserveRaise: bigint; + totalPenalty: bigint; + }; + + export namespace ManagerDatum { + export function toPlutusData(data: ManagerDatum): Constr { + return new Constr(0, [ + data.factoryPolicyId, + Asset.toPlutusData(data.baseAsset), + Asset.toPlutusData(data.raiseAsset), + data.sellerCount, + data.reserveRaise, + data.totalPenalty, + ]); + } + + export function fromPlutusData(data: Constr): ManagerDatum { + switch (data.index) { + case 0: { + const fields = data.fields; + invariant( + fields.length === 6, + `Manager Datum fields length must be 6, actual: ${fields.length}` + ); + return { + factoryPolicyId: fields[0] as string, + baseAsset: Asset.fromPlutusData(fields[1] as Constr), + raiseAsset: Asset.fromPlutusData(fields[2] as Constr), + sellerCount: fields[3] as bigint, + reserveRaise: fields[4] as bigint, + totalPenalty: fields[5] as bigint, + }; + } + default: { + throw Error(`Index of FactoryDatum must be 0, actual: ${data.index}`); + } + } + } + } + + export enum ManagerRedeemer { + ADD_SELLERS = 0, + COLLECT_SELLERS = 1, + SPEND_MANAGER = 2, + } + export namespace ManagerRedeemer { + export function toPlutusData(data: ManagerRedeemer): Constr { + return new Constr(data, []); + } + } + + export class ManagerState { + public readonly address: string; + public readonly txIn: TxIn; + public readonly value: Value; + public readonly datumCbor: string; + public readonly datum: ManagerDatum; + + constructor( + networkId: NetworkId, + address: string, + txIn: TxIn, + value: Value, + datum: string + ) { + this.address = address; + this.txIn = txIn; + this.value = value; + this.datumCbor = datum; + this.datum = ManagerDatum.fromPlutusData(Data.from(datum)); + + const config = LbeV2Constant.CONFIG[networkId]; + if ( + !value.find((v) => v.unit === config.managerAsset && v.quantity === "1") + ) { + throw new Error( + "Cannot find the Manager Authentication Asset in the value" + ); + } + } + + get lbeId(): string { + return PoolV2.computeLPAssetName( + this.datum.baseAsset, + this.datum.raiseAsset + ); + } + } + + export type SellerDatum = { + factoryPolicyId: string; + owner: Address; + baseAsset: Asset; + raiseAsset: Asset; + amount: bigint; + penaltyAmount: bigint; + }; + + export namespace SellerDatum { + export function toPlutusData(data: SellerDatum): Constr { + return new Constr(0, [ + data.factoryPolicyId, + AddressPlutusData.toPlutusData(data.owner), + Asset.toPlutusData(data.baseAsset), + Asset.toPlutusData(data.raiseAsset), + data.amount, + data.penaltyAmount, + ]); + } + + export function fromPlutusData( + data: Constr, + networkId: NetworkId + ): SellerDatum { + switch (data.index) { + case 0: { + const fields = data.fields; + invariant( + fields.length === 6, + `Seller Datum fields length must be 6, actual: ${fields.length}` + ); + return { + factoryPolicyId: fields[0] as string, + owner: AddressPlutusData.fromPlutusData( + networkId, + fields[1] as Constr + ), + baseAsset: Asset.fromPlutusData(fields[2] as Constr), + raiseAsset: Asset.fromPlutusData(fields[3] as Constr), + amount: fields[4] as bigint, + penaltyAmount: fields[5] as bigint, + }; + } + default: { + throw Error(`Index of SellerDatum must be 0, actual: ${data.index}`); + } + } + } + } + + export enum SellerRedeemer { + USING_SELLER = 0, + COUNTING_SELLERS = 1, + } + + export namespace SellerRedeemer { + export function toPlutusData(data: SellerRedeemer): Constr { + return new Constr(data, []); + } + } + + export class SellerState { + public readonly address: string; + public readonly txIn: TxIn; + public readonly value: Value; + public readonly datumCbor: string; + public readonly datum: SellerDatum; + + constructor( + networkId: NetworkId, + address: string, + txIn: TxIn, + value: Value, + datum: string + ) { + this.address = address; + this.txIn = txIn; + this.value = value; + this.datumCbor = datum; + this.datum = SellerDatum.fromPlutusData(Data.from(datum), networkId); + + const config = LbeV2Constant.CONFIG[networkId]; + if ( + !value.find((v) => v.unit === config.sellerAsset && v.quantity === "1") + ) { + throw new Error( + "Cannot find the Seller Authentication Asset in the value" + ); + } + } + + get lbeId(): string { + return PoolV2.computeLPAssetName( + this.datum.baseAsset, + this.datum.raiseAsset + ); + } + } + + export type OrderDatum = { + factoryPolicyId: string; + baseAsset: Asset; + raiseAsset: Asset; + owner: Address; + amount: bigint; + isCollected: boolean; + penaltyAmount: bigint; + }; + + export namespace OrderDatum { + export function toPlutusData(data: OrderDatum): Constr { + return new Constr(0, [ + data.factoryPolicyId, + Asset.toPlutusData(data.baseAsset), + Asset.toPlutusData(data.raiseAsset), + AddressPlutusData.toPlutusData(data.owner), + data.amount, + Bool.toPlutusData(data.isCollected), + data.penaltyAmount, + ]); + } + + export function fromPlutusData( + data: Constr, + networkId: NetworkId + ): OrderDatum { + switch (data.index) { + case 0: { + const fields = data.fields; + invariant( + fields.length === 7, + `Order Datum fields length must be 7, actual: ${fields.length}` + ); + return { + factoryPolicyId: fields[0] as string, + baseAsset: Asset.fromPlutusData(fields[1] as Constr), + raiseAsset: Asset.fromPlutusData(fields[2] as Constr), + owner: AddressPlutusData.fromPlutusData( + networkId, + fields[3] as Constr + ), + amount: fields[4] as bigint, + isCollected: Bool.fromPlutusData(fields[5] as Constr), + penaltyAmount: fields[6] as bigint, + }; + } + default: { + throw Error(`Index of OrderDatum must be 0, actual: ${data.index}`); + } + } + } + } + + export enum OrderRedeemer { + UPDATE_ORDER = 0, + COLLECT_ORDER = 1, + REDEEM_ORDER = 2, + } + + export namespace OrderRedeemer { + export function toPlutusData(data: OrderRedeemer): Constr { + return new Constr(data, []); + } + } + export class OrderState { + public readonly address: string; + public readonly txIn: TxIn; + public readonly value: Value; + public readonly datumCbor: string; + public readonly datum: OrderDatum; + + constructor( + networkId: NetworkId, + address: string, + txIn: TxIn, + value: Value, + datum: string + ) { + this.address = address; + this.txIn = txIn; + this.value = value; + this.datumCbor = datum; + this.datum = OrderDatum.fromPlutusData(Data.from(datum), networkId); + + const config = LbeV2Constant.CONFIG[networkId]; + if ( + !value.find((v) => v.unit === config.orderAsset && v.quantity === "1") + ) { + throw new Error( + "Cannot find the Order Authentication Asset in the value" + ); + } + } + + get lbeId(): string { + return PoolV2.computeLPAssetName( + this.datum.baseAsset, + this.datum.raiseAsset + ); + } + + get owner(): Address { + return this.datum.owner; + } + } +} diff --git a/src/types/order.ts b/src/types/order.ts index f89026f..9d6b98a 100644 --- a/src/types/order.ts +++ b/src/types/order.ts @@ -1,8 +1,10 @@ -import { Address, Constr, Data } from "lucid-cardano"; +import { Address, Constr, Data } from "@minswap/lucid-cardano"; +import invariant from "@minswap/tiny-invariant"; import { AddressPlutusData } from "./address.internal"; import { Asset } from "./asset"; import { NetworkId } from "./network"; +import { TxIn, Value } from "./tx.internal"; export namespace OrderV1 { export enum StepType { @@ -478,6 +480,11 @@ export namespace OrderV2 { export namespace AuthorizationMethod { export function fromPlutusData(data: Constr): AuthorizationMethod { let type: AuthorizationMethodType; + if (data.fields.length !== 1) { + throw Error( + `Field length of AuthorizationMethod must be in 1, actual: ${data.fields.length}` + ); + } switch (data.index) { case AuthorizationMethodType.SIGNATURE: { type = AuthorizationMethodType.SIGNATURE; @@ -1090,17 +1097,29 @@ export namespace OrderV2 { export function fromPlutusData(data: Constr): ExtraDatum { switch (data.index) { case ExtraDatumType.NO_DATUM: { + invariant( + data.fields.length === 0, + `Field Length of ExtraDatum.NO_DATUM must be 0, actually ${data.fields.length}` + ); return { type: ExtraDatumType.NO_DATUM, }; } case ExtraDatumType.DATUM_HASH: { + invariant( + data.fields.length === 1, + `Field Length of ExtraDatum.DATUM_HASH must be 1, actually ${data.fields.length}` + ); return { type: ExtraDatumType.DATUM_HASH, hash: data.fields[0] as string, }; } case ExtraDatumType.INLINE_DATUM: { + invariant( + data.fields.length === 1, + `Field Length of ExtraDatum.INLINE_DATUM must be 1, actually ${data.fields.length}` + ); return { type: ExtraDatumType.INLINE_DATUM, hash: data.fields[0] as string, @@ -1151,20 +1170,38 @@ export namespace OrderV2 { `Index of Order Datum must be 0, actual: ${data.index}` ); } + if (data.fields.length !== 9) { + throw new Error( + `Fields Length of Order Datum must be 9, actual: ${data.index}` + ); + } const maybeExpiry = data.fields[8] as Constr; let expiry: bigint[] | undefined; switch (maybeExpiry.index) { case 0: { - expiry = maybeExpiry.fields as bigint[]; - if (expiry.length !== 2) { + if (maybeExpiry.fields.length !== 1) { throw new Error( - `Order Expiry list must have 2 elements, actual: ${expiry.length}` + `Order maybeExpiry length must have 1 field, actual: ${maybeExpiry.fields.length}` ); } + if ( + !Array.isArray(maybeExpiry.fields[0]) || + maybeExpiry.fields[0].length !== 2 + ) { + throw new Error( + `maybeExpiry field0's length must be 2-element array, actual: ${maybeExpiry.fields[0]}` + ); + } + expiry = maybeExpiry.fields[0] as bigint[]; break; } case 1: { expiry = undefined; + if (maybeExpiry.fields.length !== 0) { + throw new Error( + `Order undefined Expiry must have 0 elements, actual: ${maybeExpiry.fields.length}` + ); + } break; } default: { @@ -1215,8 +1252,10 @@ export namespace OrderV2 { datum.maxBatcherFee, datum.expiredOptions ? new Constr(0, [ - datum.expiredOptions.expiredTime, - datum.expiredOptions.maxCancellationTip, + [ + datum.expiredOptions.expiredTime, + datum.expiredOptions.maxCancellationTip, + ], ]) : new Constr(1, []), ]); @@ -1228,4 +1267,26 @@ export namespace OrderV2 { CANCEL_ORDER_BY_OWNER, CANCEL_EXPIRED_ORDER_BY_ANYONE, } + + export class State { + public readonly address: string; + public readonly txIn: TxIn; + public readonly value: Value; + public readonly datumCbor: string; + public readonly datum: Datum; + + constructor( + networkId: NetworkId, + address: string, + txIn: TxIn, + value: Value, + datum: string + ) { + this.address = address; + this.txIn = txIn; + this.value = value; + this.datumCbor = datum; + this.datum = Datum.fromPlutusData(networkId, Data.from(datum)); + } + } } diff --git a/src/types/pool.internal.ts b/src/types/pool.internal.ts index f3363cb..512c26a 100644 --- a/src/types/pool.internal.ts +++ b/src/types/pool.internal.ts @@ -1,5 +1,5 @@ +import { Address, Constr, Data } from "@minswap/lucid-cardano"; import invariant from "@minswap/tiny-invariant"; -import { Address, Constr, Data } from "lucid-cardano"; import { getScriptHashFromAddress } from "../utils/address-utils.internal"; import { AddressPlutusData } from "./address.internal"; diff --git a/src/types/pool.ts b/src/types/pool.ts index 0740009..d4a71ef 100644 --- a/src/types/pool.ts +++ b/src/types/pool.ts @@ -1,19 +1,17 @@ +import { Constr, Credential, Data } from "@minswap/lucid-cardano"; import invariant from "@minswap/tiny-invariant"; -import { Constr, Credential, Data } from "lucid-cardano"; import { sha3 } from "../utils/hash.internal"; import { LucidCredential } from "./address.internal"; import { ADA, Asset } from "./asset"; -import { - DexV1Constant, - DexV2Constant, - StableswapConstant, -} from "./constants"; +import { DexV1Constant, DexV2Constant, StableswapConstant } from "./constants"; import { NetworkId } from "./network"; import { normalizeAssets, PoolFeeSharing } from "./pool.internal"; import { TxIn, Value } from "./tx.internal"; export const DEFAULT_POOL_V2_TRADING_FEE_DENOMINATOR = 10000n; +export const MIN_POOL_V2_TRADING_FEE_NUMERATOR = 5n; +export const MAX_POOL_V2_TRADING_FEE_NUMERATOR = 2000n; export namespace PoolV1 { /** @@ -34,7 +32,9 @@ export namespace PoolV1 { this.value = value; this.datumHash = datumHash; - const nft = value.find(({ unit }) => unit.startsWith(DexV1Constant.POOL_NFT_POLICY_ID)); + const nft = value.find(({ unit }) => + unit.startsWith(DexV1Constant.POOL_NFT_POLICY_ID) + ); invariant(nft, "pool doesn't have NFT"); const poolId = nft.unit.slice(56); // validate and memoize assetA and assetB @@ -50,7 +50,10 @@ export namespace PoolV1 { const nonADAAssets = relevantAssets.filter( ({ unit }) => unit !== "lovelace" ); - invariant(nonADAAssets.length === 1, "pool must have 1 non-ADA asset"); + invariant( + nonADAAssets.length === 1, + "pool must have 1 non-ADA asset" + ); this.assetB = nonADAAssets[0].unit; break; } @@ -59,7 +62,10 @@ export namespace PoolV1 { const nonADAAssets = relevantAssets.filter( ({ unit }) => unit !== "lovelace" ); - invariant(nonADAAssets.length === 2, "pool must have 1 non-ADA asset"); + invariant( + nonADAAssets.length === 2, + "pool must have 1 non-ADA asset" + ); [this.assetA, this.assetB] = normalizeAssets( nonADAAssets[0].unit, nonADAAssets[1].unit @@ -170,7 +176,7 @@ export namespace StablePool { public readonly value: Value; public readonly datumCbor: string; public readonly datum: Datum; - public readonly config: StableswapConstant.Config + public readonly config: StableswapConstant.Config; constructor( networkId: NetworkId, @@ -179,52 +185,54 @@ export namespace StablePool { value: Value, datum: string ) { - this.address = address - this.txIn = txIn - this.value = value - this.datumCbor = datum - this.datum = Datum.fromPlutusData(Data.from(datum)) - const allConfigs = StableswapConstant.CONFIG[networkId] - const config = allConfigs.find((cfg) => cfg.poolAddress === address) + this.address = address; + this.txIn = txIn; + this.value = value; + this.datumCbor = datum; + this.datum = Datum.fromPlutusData(Data.from(datum)); + const allConfigs = StableswapConstant.CONFIG[networkId]; + const config = allConfigs.find((cfg) => cfg.poolAddress === address); if (!config) { - throw new Error("Invalid Stable Pool address") + throw new Error("Invalid Stable Pool address"); } - this.config = config - if (!value.find((v) => v.unit === config.nftAsset && v.quantity === "1")) { - throw new Error("Cannot find the Pool NFT in the value") + this.config = config; + if ( + !value.find((v) => v.unit === config.nftAsset && v.quantity === "1") + ) { + throw new Error("Cannot find the Pool NFT in the value"); } } get assets(): string[] { - return this.config.assets + return this.config.assets; } get nft(): string { - return this.config.nftAsset + return this.config.nftAsset; } get lpAsset(): string { - return this.config.lpAsset + return this.config.lpAsset; } get reserves(): bigint[] { - return this.datum.balances + return this.datum.balances; } get totalLiquidity(): bigint { - return this.datum.totalLiquidity + return this.datum.totalLiquidity; } get orderHash(): string { - return this.datum.orderHash + return this.datum.orderHash; } get amp(): bigint { - return this.datum.amplificationCoefficient + return this.datum.amplificationCoefficient; } get id(): string { - return this.nft + return this.nft; } } @@ -233,16 +241,17 @@ export namespace StablePool { totalLiquidity: bigint; amplificationCoefficient: bigint; orderHash: string; - } + }; export namespace Datum { export function toPlutusData(datum: Datum): Constr { - const { balances, totalLiquidity, amplificationCoefficient, orderHash } = datum; + const { balances, totalLiquidity, amplificationCoefficient, orderHash } = + datum; return new Constr(0, [ balances, totalLiquidity, amplificationCoefficient, - orderHash + orderHash, ]); } @@ -254,8 +263,8 @@ export namespace StablePool { balances: data.fields[0] as bigint[], totalLiquidity: data.fields[1] as bigint, amplificationCoefficient: data.fields[2] as bigint, - orderHash: data.fields[3] as string - } + orderHash: data.fields[3] as string, + }; } } } @@ -271,9 +280,9 @@ export namespace PoolV2 { const [normalizedA, normalizedB] = normalizeAssets( Asset.toString(assetA), Asset.toString(assetB) - ) - const normalizedAssetA = Asset.fromString(normalizedA) - const normalizedAssetB = Asset.fromString(normalizedB) + ); + const normalizedAssetA = Asset.fromString(normalizedA); + const normalizedAssetB = Asset.fromString(normalizedB); const k1 = sha3(normalizedAssetA.policyId + normalizedAssetA.tokenName); const k2 = sha3(normalizedAssetB.policyId + normalizedAssetB.tokenName); return sha3(k1 + k2); @@ -288,14 +297,14 @@ export namespace PoolV2 { feeBNumerator: bigint; }; feeSharingNumerator?: bigint; - } + }; export class State { public readonly address: string; public readonly txIn: TxIn; public readonly value: Value; public readonly datumRaw: string; public readonly datum: Datum; - public readonly config: DexV2Constant.Config + public readonly config: DexV2Constant.Config; public readonly lpAsset: Asset; public readonly authenAsset: Asset; constructor( @@ -305,73 +314,81 @@ export namespace PoolV2 { value: Value, datum: string ) { - this.address = address - this.txIn = txIn - this.value = value - this.datumRaw = datum - this.datum = Datum.fromPlutusData(Data.from(datum)) - this.config = DexV2Constant.CONFIG[networkId] + this.address = address; + this.txIn = txIn; + this.value = value; + this.datumRaw = datum; + this.datum = Datum.fromPlutusData(Data.from(datum)); + this.config = DexV2Constant.CONFIG[networkId]; this.lpAsset = { policyId: this.config.lpPolicyId, - tokenName: computeLPAssetName(this.datum.assetA, this.datum.assetB) - } - this.authenAsset = Asset.fromString(this.config.poolAuthenAsset) - if (!value.find((v) => v.unit === this.config.poolAuthenAsset && v.quantity === "1")) { - throw new Error("Cannot find the Pool Authentication Asset in the value") + tokenName: computeLPAssetName(this.datum.assetA, this.datum.assetB), + }; + this.authenAsset = Asset.fromString(this.config.poolAuthenAsset); + if ( + !value.find( + (v) => v.unit === this.config.poolAuthenAsset && v.quantity === "1" + ) + ) { + throw new Error( + "Cannot find the Pool Authentication Asset in the value" + ); } } get assetA(): string { - return Asset.toString(this.datum.assetA) + return Asset.toString(this.datum.assetA); } get assetB(): string { - return Asset.toString(this.datum.assetB) + return Asset.toString(this.datum.assetB); } get totalLiquidity(): bigint { - return this.datum.totalLiquidity + return this.datum.totalLiquidity; } get reserveA(): bigint { - return this.datum.reserveA + return this.datum.reserveA; } get reserveB(): bigint { - return this.datum.reserveB + return this.datum.reserveB; } get feeA(): [bigint, bigint] { return [ this.datum.baseFee.feeANumerator, - DEFAULT_POOL_V2_TRADING_FEE_DENOMINATOR - ] + DEFAULT_POOL_V2_TRADING_FEE_DENOMINATOR, + ]; } get feeB(): [bigint, bigint] { return [ this.datum.baseFee.feeBNumerator, - DEFAULT_POOL_V2_TRADING_FEE_DENOMINATOR - ] + DEFAULT_POOL_V2_TRADING_FEE_DENOMINATOR, + ]; } get feeShare(): [bigint, bigint] | undefined { if (this.datum.feeSharingNumerator !== undefined) { return [ this.datum.feeSharingNumerator, - DEFAULT_POOL_V2_TRADING_FEE_DENOMINATOR - ] + DEFAULT_POOL_V2_TRADING_FEE_DENOMINATOR, + ]; } else { - return undefined + return undefined; } } get datumReserves(): [bigint, bigint] { - return [this.datum.reserveA, this.datum.reserveB] + return [this.datum.reserveA, this.datum.reserveB]; } get valueReserveA(): bigint { - const amount = BigInt(this.value.find((v) => v.unit === this.assetA)?.quantity ?? "0") + const amount = BigInt( + this.value.find((v) => v.unit === this.assetA)?.quantity ?? "0" + ); if (Asset.equals(this.datum.assetA, ADA)) { return amount - DEFAULT_POOL_ADA; } @@ -379,7 +396,9 @@ export namespace PoolV2 { } get valueReserveB(): bigint { - return BigInt(this.value.find((v) => v.unit === this.assetB)?.quantity ?? "0") + return BigInt( + this.value.find((v) => v.unit === this.assetB)?.quantity ?? "0" + ); } get valueReserves(): [bigint, bigint] { @@ -392,8 +411,8 @@ export namespace PoolV2 { valueReserves: this.valueReserves, totalLiquidity: this.datum.totalLiquidity, tradingFee: this.datum.baseFee, - feeSharingNumerator: this.datum.feeSharingNumerator - } + feeSharingNumerator: this.datum.feeSharingNumerator, + }; } } @@ -410,7 +429,7 @@ export namespace PoolV2 { }; feeSharingNumerator?: bigint; allowDynamicFee: boolean; - } + }; export namespace Datum { export function toPlutusData(datum: Datum): Constr { @@ -423,10 +442,12 @@ export namespace PoolV2 { reserveB, baseFee, feeSharingNumerator, - allowDynamicFee + allowDynamicFee, } = datum; return new Constr(0, [ - new Constr(0, [LucidCredential.toPlutusData(poolBatchingStakeCredential)]), + new Constr(0, [ + LucidCredential.toPlutusData(poolBatchingStakeCredential), + ]), Asset.toPlutusData(assetA), Asset.toPlutusData(assetB), totalLiquidity, @@ -437,7 +458,7 @@ export namespace PoolV2 { feeSharingNumerator !== undefined ? new Constr(0, [feeSharingNumerator]) : new Constr(1, []), - new Constr(allowDynamicFee ? 1 : 0, []) + new Constr(allowDynamicFee ? 1 : 0, []), ]); } @@ -445,15 +466,17 @@ export namespace PoolV2 { if (data.index !== 0) { throw new Error(`Index of Pool Datum must be 0, actual: ${data.index}`); } - const stakeCredentialConstr = data.fields[0] as Constr + const stakeCredentialConstr = data.fields[0] as Constr; if (stakeCredentialConstr.index !== 0) { - throw new Error(`Index of Stake Credential must be 0, actual: ${stakeCredentialConstr.index}`); + throw new Error( + `Index of Stake Credential must be 0, actual: ${stakeCredentialConstr.index}` + ); } let feeSharingNumerator: bigint | undefined = undefined; const maybeFeeSharingConstr = data.fields[8] as Constr; switch (maybeFeeSharingConstr.index) { case 0: { - feeSharingNumerator = maybeFeeSharingConstr.fields[0] as bigint + feeSharingNumerator = maybeFeeSharingConstr.fields[0] as bigint; break; } case 1: { @@ -469,7 +492,9 @@ export namespace PoolV2 { const allowDynamicFeeConstr = data.fields[9] as Constr; const allowDynamicFee = allowDynamicFeeConstr.index === 1; return { - poolBatchingStakeCredential: LucidCredential.fromPlutusData(stakeCredentialConstr.fields[0] as Constr), + poolBatchingStakeCredential: LucidCredential.fromPlutusData( + stakeCredentialConstr.fields[0] as Constr + ), assetA: Asset.fromPlutusData(data.fields[1] as Constr), assetB: Asset.fromPlutusData(data.fields[2] as Constr), totalLiquidity: data.fields[3] as bigint, @@ -477,10 +502,10 @@ export namespace PoolV2 { reserveB: data.fields[5] as bigint, baseFee: { feeANumerator: data.fields[6] as bigint, - feeBNumerator: data.fields[7] as bigint + feeBNumerator: data.fields[7] as bigint, }, feeSharingNumerator: feeSharingNumerator, - allowDynamicFee: allowDynamicFee + allowDynamicFee: allowDynamicFee, }; } } diff --git a/src/utils/address-utils.internal.ts b/src/utils/address-utils.internal.ts index 10b7a62..0cc1255 100644 --- a/src/utils/address-utils.internal.ts +++ b/src/utils/address-utils.internal.ts @@ -1,4 +1,4 @@ -import { C } from "lucid-cardano"; +import { C } from "@minswap/lucid-cardano"; export function getScriptHashFromAddress(addr: string): string | null { try { diff --git a/src/utils/job.ts b/src/utils/job.ts new file mode 100644 index 0000000..2fb8e9d --- /dev/null +++ b/src/utils/job.ts @@ -0,0 +1,43 @@ +export type RunRecurringJobParams = { + name: string; + interval: number; + job: () => Promise; +}; + +/** + * Run job with consideration of job taking longer than interval. + * + * If job finish less than interval, wait (interval - execution time) until next run. + * + * If job finish longer than interval, start immediately + */ +export async function runRecurringJob({ + name, + job, + interval, +}: RunRecurringJobParams): Promise { + while (true) { + const startTime = Date.now(); + + try { + await job(); + } catch (err) { + console.error(`Job ${name} fail: ${err}`); + } + + const timeTook = Date.now() - startTime; + console.log(`done job ${name}, took ${timeTook / 1000}s`); + + if (timeTook < interval) { + await sleep(interval - timeTook); + } + } +} + +async function sleep(durationInMs: number): Promise { + return new Promise((resolve) => { + setTimeout(() => { + resolve({ error: false, message: `Slept for ${durationInMs} ms` }); + }, durationInMs); + }); +} diff --git a/src/utils/lucid.ts b/src/utils/lucid.ts new file mode 100644 index 0000000..18d5471 --- /dev/null +++ b/src/utils/lucid.ts @@ -0,0 +1,23 @@ +import { Address, Blockfrost, Lucid, Network } from "@minswap/lucid-cardano"; + +/** + * Initialize Lucid Instance for Backend Environment + * @param network Network you're working on + * @param projectId Blockfrost API KEY + * @param blockfrostUrl Blockfrost URL + * @param address Your own address + * @returns + */ +export async function getBackendLucidInstance( + network: Network, + projectId: string, + blockfrostUrl: string, + address: Address +): Promise { + const provider = new Blockfrost(blockfrostUrl, projectId); + const lucid = await Lucid.new(provider, network); + lucid.selectWalletFrom({ + address: address, + }); + return lucid; +} diff --git a/src/utils/network.internal.ts b/src/utils/network.internal.ts index 28260f6..45a5741 100644 --- a/src/utils/network.internal.ts +++ b/src/utils/network.internal.ts @@ -1,4 +1,4 @@ -import { Network } from "lucid-cardano"; +import { Network } from "@minswap/lucid-cardano"; import { NetworkEnvironment } from "../types/network"; diff --git a/src/utils/tx.internal.ts b/src/utils/tx.internal.ts index e8456c8..f71addf 100644 --- a/src/utils/tx.internal.ts +++ b/src/utils/tx.internal.ts @@ -1,4 +1,4 @@ -import { Address, Assets, Lucid, OutputData } from "lucid-cardano"; +import { Address, Assets, Lucid, OutputData } from "@minswap/lucid-cardano"; /** * Return a Output that pay back to @sender and include @datum diff --git a/test/address.test.ts b/test/address.test.ts index b201312..afd6395 100644 --- a/test/address.test.ts +++ b/test/address.test.ts @@ -1,4 +1,4 @@ -import { Credential, Data } from "lucid-cardano"; +import { Credential, Data } from "@minswap/lucid-cardano"; import { AddressPlutusData, diff --git a/test/batcher-fee.test.ts b/test/batcher-fee.test.ts index e0d847a..d3e640c 100644 --- a/test/batcher-fee.test.ts +++ b/test/batcher-fee.test.ts @@ -5,7 +5,7 @@ import { BatcherFeeConfig, DexVersion, } from "../src/batcher-fee-reduction/configs.internal"; -import { Assets } from "lucid-cardano"; +import { Assets } from "@minswap/lucid-cardano"; function compareAssets(a1: Assets, a2: Assets): boolean { if (Object.keys(a1).length !== Object.keys(a2).length) { diff --git a/test/order.test.ts b/test/order.test.ts index d96a0ca..9f577ee 100644 --- a/test/order.test.ts +++ b/test/order.test.ts @@ -1,5 +1,5 @@ import invariant from "@minswap/tiny-invariant"; -import { Address, Data, getAddressDetails } from "lucid-cardano"; +import { Address, Data, getAddressDetails } from "@minswap/lucid-cardano"; import { FIXED_BATCHER_FEE } from "../src/batcher-fee-reduction/configs.internal"; import { Asset } from "../src/types/asset"; diff --git a/test/pool.test.ts b/test/pool.test.ts index 96cc6a6..2c56ed7 100644 --- a/test/pool.test.ts +++ b/test/pool.test.ts @@ -1,5 +1,5 @@ import JSONBig from "json-bigint"; -import { Data } from "lucid-cardano"; +import { Data } from "@minswap/lucid-cardano"; import { NetworkId } from "../src"; import { ADA, Asset } from "../src/types/asset";