UNPKG

@indigo-labs/indigo-sdk

Version:

Indigo SDK for interacting with Indigo endpoints via lucid-evolution

407 lines (369 loc) 10.3 kB
import { fromHex, fromText, OutRef, paymentCredentialOf, unixTimeToSlot, } from '@lucid-evolution/lucid'; import { addrDetails, createProposal, createShardsChunks, endProposal, executeProposal, fromSystemParamsAsset, InterestOracleParams, mergeShards, openStakingPosition, PriceOracleParams, startInterestOracle, SystemParams, vote, } from '../../src'; import { VoteOption } from '../../src/contracts/poll/types-poll-new'; import { findAllPollShards, findPollManager, findRandomPollShard, } from '../queries/poll-queries'; import { findStakingPosition } from '../queries/staking-queries'; import { LucidContext, runAndAwaitTx, runAndAwaitTxBuilder, selectWalletByAddress, } from '../test-helpers'; import { findGov } from './governance-queries'; import { array as A } from 'fp-ts'; import { expect } from 'vitest'; import { findExecute } from '../queries/execute-queries'; import { CollateralAssetInfo } from '../endpoints/initialize'; import { startPriceOracleTx } from '../../src/contracts/price-oracle/transactions'; import { AssetClass } from '@3rd-eye-labs/cardano-offchain-common'; import { findAllCollateralAssetsOfIAsset, findIAsset, } from '../queries/iasset-queries'; import { Rational, rationalFromInt } from '../../src/types/rational'; export async function runVote( pollId: bigint, option: VoteOption, sysParams: SystemParams, context: LucidContext, ): Promise<void> { const [pkh, _] = await addrDetails(context.lucid); const stakingPosOref = await findStakingPosition( context.lucid, sysParams.validatorHashes.stakingHash, fromSystemParamsAsset(sysParams.stakingParams.stakingToken), pkh.hash, ); const pollShard = await findRandomPollShard( context.lucid, sysParams.validatorHashes.pollShardHash, fromSystemParamsAsset(sysParams.pollShardParams.pollToken), pollId, ); await runAndAwaitTx( context.lucid, vote( option, pollShard.utxo, stakingPosOref.utxo, sysParams, context.lucid, context.emulator.slot, ), ); } export async function runCreateAllShards( pollId: bigint, sysParams: SystemParams, context: LucidContext, ): Promise<void> { const govUtxo = await findGov( context.lucid, sysParams.validatorHashes.govHash, fromSystemParamsAsset(sysParams.govParams.govNFT), ); for ( let i = 0; i < Math.ceil(Number(govUtxo.datum.protocolParams.totalShards) / 2); i++ ) { const pollUtxo = await findPollManager( context.lucid, sysParams.validatorHashes.pollManagerHash, fromSystemParamsAsset(sysParams.pollManagerParams.pollToken), pollId, ); await runAndAwaitTx( context.lucid, createShardsChunks( 2n, pollUtxo.utxo, sysParams, context.emulator.slot, context.lucid, ), ); } } export async function runMergeAllShards( pollId: bigint, sysParams: SystemParams, context: LucidContext, ): Promise<void> { const govUtxo = await findGov( context.lucid, sysParams.validatorHashes.govHash, fromSystemParamsAsset(sysParams.govParams.govNFT), ); for ( let i = 0; i < Math.ceil(Number(govUtxo.datum.protocolParams.totalShards) / 2); i++ ) { const pollUtxo = await findPollManager( context.lucid, sysParams.validatorHashes.pollManagerHash, fromSystemParamsAsset(sysParams.pollManagerParams.pollToken), pollId, ); const allPollShards = await findAllPollShards( context.lucid, sysParams.validatorHashes.pollShardHash, fromSystemParamsAsset(sysParams.pollShardParams.pollToken), pollUtxo.datum.pollId, ); await runAndAwaitTx( context.lucid, mergeShards( pollUtxo.utxo, A.takeLeft(2)(allPollShards).map((u) => u.utxo), sysParams, context.lucid, context.emulator.slot, ), ); } } export async function runEndProposal( pollId: bigint, sysParams: SystemParams, context: LucidContext, ): Promise<void> { const pollUtxo = await findPollManager( context.lucid, sysParams.validatorHashes.pollManagerHash, fromSystemParamsAsset(sysParams.pollManagerParams.pollToken), pollId, ); const govUtxo = await findGov( context.lucid, sysParams.validatorHashes.govHash, fromSystemParamsAsset(sysParams.govParams.govNFT), ); await runAndAwaitTx( context.lucid, endProposal( pollUtxo.utxo, govUtxo.utxo, sysParams, context.lucid, context.emulator.slot, ), ); } export async function waitForVotingEnd( pollId: bigint, sysParams: SystemParams, context: LucidContext, ): Promise<void> { const pollUtxo = await findPollManager( context.lucid, sysParams.validatorHashes.pollManagerHash, fromSystemParamsAsset(sysParams.pollManagerParams.pollToken), pollId, ); const targetSlot = unixTimeToSlot( context.lucid.config().network!, Number(pollUtxo.datum.votingEndTime), ); if (targetSlot > context.emulator.slot) { expect(targetSlot).toBeGreaterThan(context.emulator.slot); context.emulator.awaitSlot(targetSlot - context.emulator.slot + 1); } } export async function runExecuteProposal( pollId: bigint, treasuryWithdrawalOref: OutRef | null, allIAssetOrefs: OutRef[] | null, iAssetOref: OutRef | null, allCollateralAssetsOrefsOfIAsset: OutRef[] | null, collateralAssetOref: OutRef | null, stableswapPoolOrCdpCreatorOref: OutRef | null, sysParams: SystemParams, context: LucidContext, ): Promise<void> { const executeUtxo = await findExecute( context.lucid, sysParams.validatorHashes.executeHash, fromSystemParamsAsset(sysParams.executeParams.upgradeToken), pollId, ); await runAndAwaitTx( context.lucid, executeProposal( executeUtxo.utxo, ( await findGov( context.lucid, sysParams.validatorHashes.govHash, fromSystemParamsAsset(sysParams.govParams.govNFT), ) ).utxo, treasuryWithdrawalOref, allIAssetOrefs, iAssetOref, allCollateralAssetsOrefsOfIAsset, collateralAssetOref, stableswapPoolOrCdpCreatorOref, sysParams, context.lucid, context.emulator.slot, ), ); } export async function processSuccessfulProposal( pollId: bigint, treasuryWithdrawalOref: OutRef | null, allIAssetOrefs: OutRef[] | null, iAssetOref: OutRef | null, allCollateralAssetsOrefsOfIAsset: OutRef[] | null, collateralAssetOref: OutRef | null, stableswapPoolOrCdpCreatorOref: OutRef | null, sysParams: SystemParams, context: LucidContext, createStakingPos: boolean = true, ): Promise<void> { await runCreateAllShards(pollId, sysParams, context); if (createStakingPos) { await runAndAwaitTx( context.lucid, openStakingPosition(100_000_000_000n, sysParams, context.lucid), ); } await runVote(pollId, 'Yes', sysParams, context); await waitForVotingEnd(pollId, sysParams, context); await runMergeAllShards(pollId, sysParams, context); await runEndProposal(pollId, sysParams, context); await runExecuteProposal( pollId, treasuryWithdrawalOref, allIAssetOrefs, iAssetOref, allCollateralAssetsOrefsOfIAsset, collateralAssetOref, stableswapPoolOrCdpCreatorOref, sysParams, context, ); } export async function whitelistCollateralAsset( context: LucidContext, sysParams: SystemParams, iassetAscii: string, newCollateralAsset: AssetClass, initialPrice: Rational, initialInterest: bigint, createStakingPos: boolean, ): Promise<CollateralAssetInfo> { const prevAddr = await context.lucid.wallet().address(); context.lucid.selectWallet.fromSeed(context.users.admin.seedPhrase); const interestOracleParams: InterestOracleParams = { biasTime: 120_000n, owner: paymentCredentialOf(context.users.admin.address).hash, }; const [startInterestTx, interestOracleNft] = await startInterestOracle( 0n, initialInterest, 0n, interestOracleParams, context.lucid, ); await runAndAwaitTxBuilder(context.lucid, startInterestTx); const oracleParams: PriceOracleParams = { biasTime: 120_000n, expirationPeriod: 1_800_000n, owner: paymentCredentialOf(context.users.admin.address).hash, }; const [priceOracleTx, priceOranceNft] = await startPriceOracleTx( context.lucid, 'COLLATERAL_ORACLE', initialPrice, oracleParams, context.emulator.slot, ); await runAndAwaitTxBuilder(context.lucid, priceOracleTx); const [tx, pollId] = await createProposal( { AddCollateralAsset: { correspondingIAsset: fromHex(fromText(iassetAscii)), collateralAsset: newCollateralAsset, assetExtraDecimals: 0n, assetPriceInfo: { OracleNft: priceOranceNft }, interestOracleNft: interestOracleNft, redemptionRatio: rationalFromInt(2n), maintenanceRatio: { numerator: 15n, denominator: 10n }, liquidationRatio: { numerator: 12n, denominator: 10n }, minCollateralAmt: 1_000_000n, }, }, null, sysParams, context.lucid, context.emulator.slot, ( await findGov( context.lucid, sysParams.validatorHashes.govHash, fromSystemParamsAsset(sysParams.govParams.govNFT), ) ).utxo, [], ); await runAndAwaitTxBuilder(context.lucid, tx); const iassetOutput = await findIAsset( context.lucid, sysParams.validatorHashes.iassetHash, fromSystemParamsAsset(sysParams.executeParams.iAssetToken), iassetAscii, ); await processSuccessfulProposal( pollId, null, null, iassetOutput.utxo, ( await findAllCollateralAssetsOfIAsset( context.lucid, sysParams.validatorHashes.iassetHash, fromSystemParamsAsset(sysParams.executeParams.collateralAssetToken), fromHex(fromText(iassetAscii)), ) ).map((o) => o.utxo), null, null, sysParams, context, createStakingPos, ); selectWalletByAddress(context, prevAddr); return { collateralAsset: newCollateralAsset, interestOracleNft: interestOracleNft, oracleParams: oracleParams, interestOracleParams, }; }