@indigo-labs/indigo-sdk
Version:
Indigo SDK for interacting with Indigo endpoints via lucid-evolution
1,759 lines (1,507 loc) • 119 kB
text/typescript
import { assert, beforeEach, test } from 'vitest';
import {
IndigoTestContext,
repeat,
runAndAwaitTx,
runAndAwaitTxBuilder,
} from '../test-helpers';
import {
createIndigoTestContext,
EXAMPLE_TOKEN_1,
} from '../indigo-test-helpers';
import { benchmarkAndAwaitTx } from '../utils/benchmark-utils';
import {
batchProcessStableswapOrders,
cancelStableswapOrder,
createStableswapOrder,
updateStableswapPoolFees,
} from '../../src/contracts/stableswap/transactions';
import {
createScriptAddress,
fromSystemParamsAsset,
mkTreasuryAddr,
} from '../../src';
import {
addAssets,
Assets,
credentialToAddress,
fromHex,
fromText,
paymentCredentialOf,
UTxO,
} from '@lucid-evolution/lucid';
import {
findAllNecessaryOrefs,
findPriceOracleFromCollateralAsset,
findStableswapPool,
} from '../cdp/cdp-queries';
import {
findSingleStableswapOrder,
findStableswapOrders,
} from './stableswap-queries';
import { feedPriceOracleTx } from '../../src/contracts/price-oracle/transactions';
import {
addressFromBech32,
assetClassValueOf,
lovelacesAmt,
mkLovelacesOf,
negateAssets,
} from '@3rd-eye-labs/cardano-offchain-common';
import { runCreateStableswapPool } from './stableswap-actions';
import { getValueChangeAtAddressAfterAction } from '../utils';
import { array as A } from 'fp-ts';
import { runOpenCdp } from '../cdp/actions';
import { Data } from '@evolution-sdk/evolution';
import { serialiseStableswapOrderDatum } from '../../src/contracts/stableswap/types-new';
import { BASE_MAX_EXECUTION_FEE } from '../../src/contracts/stableswap/helpers';
import { StableswapPoolContent } from '../../src/contracts/cdp/types-new';
import { mutatedBatchProcessStableswapOrders } from './transactions-mutated';
import { expectScriptFailure } from '../utils/asserts';
import {
findRandomTreasuryUtxoWithOnlyAda,
findRandomTreasuryUtxoWithAsset,
} from '../treasury/treasury-queries';
import { createUtxoAtTreasury } from '../endpoints/treasury';
import { rationalFromInt, rationalZero } from '../../src/types/rational';
beforeEach<IndigoTestContext>(async (context: IndigoTestContext) => {
await createIndigoTestContext(context);
});
test<IndigoTestContext>('Stableswap - Create Order', async (context: IndigoTestContext) => {
context.lucid.selectWallet.fromSeed(context.users.admin.seedPhrase);
await runCreateStableswapPool(
context.assetConfigs[0].iassetTokenNameAscii,
EXAMPLE_TOKEN_1,
context,
);
const stableswapPool = await findStableswapPool(
context.lucid,
context.systemParams.validatorHashes.cdpHash,
fromSystemParamsAsset(context.systemParams.stableswapParams.cdpToken),
fromText(context.assetConfigs[0].iassetTokenNameAscii),
EXAMPLE_TOKEN_1,
);
context.lucid.selectWallet.fromSeed(context.users.user.seedPhrase);
await benchmarkAndAwaitTx(
'Stableswap - Create Order',
await createStableswapOrder(
context.assetConfigs[0].iassetTokenNameAscii,
EXAMPLE_TOKEN_1,
10_000_000n,
true,
stableswapPool.datum,
context.systemParams,
context.lucid,
),
context.lucid,
context.emulator,
);
});
test<IndigoTestContext>('Stableswap - Cancel Order', async (context: IndigoTestContext) => {
context.lucid.selectWallet.fromSeed(context.users.admin.seedPhrase);
await runCreateStableswapPool(
context.assetConfigs[0].iassetTokenNameAscii,
EXAMPLE_TOKEN_1,
context,
);
const stableswapPool = await findStableswapPool(
context.lucid,
context.systemParams.validatorHashes.cdpHash,
fromSystemParamsAsset(context.systemParams.stableswapParams.cdpToken),
fromText(context.assetConfigs[0].iassetTokenNameAscii),
EXAMPLE_TOKEN_1,
);
context.lucid.selectWallet.fromSeed(context.users.user.seedPhrase);
await runAndAwaitTx(
context.lucid,
createStableswapOrder(
context.assetConfigs[0].iassetTokenNameAscii,
EXAMPLE_TOKEN_1,
10_000_000n,
true,
stableswapPool.datum,
context.systemParams,
context.lucid,
),
);
const stableswapOrder = await findSingleStableswapOrder(
context.lucid,
context.systemParams.validatorHashes.stableswapHash,
fromText(context.assetConfigs[0].iassetTokenNameAscii),
EXAMPLE_TOKEN_1,
);
await benchmarkAndAwaitTx(
'Stableswap - Cancel Order',
await cancelStableswapOrder(
stableswapOrder.utxo,
context.systemParams,
context.lucid,
),
context.lucid,
context.emulator,
);
});
test<IndigoTestContext>('Stableswap - Batch a single order to mint', async (context: IndigoTestContext) => {
context.lucid.selectWallet.fromSeed(context.users.admin.seedPhrase);
await runCreateStableswapPool(
context.assetConfigs[0].iassetTokenNameAscii,
EXAMPLE_TOKEN_1,
context,
);
let stableswapPool = await findStableswapPool(
context.lucid,
context.systemParams.validatorHashes.cdpHash,
fromSystemParamsAsset(context.systemParams.stableswapParams.cdpToken),
fromText(context.assetConfigs[0].iassetTokenNameAscii),
EXAMPLE_TOKEN_1,
);
context.lucid.selectWallet.fromSeed(context.users.user.seedPhrase);
const initialUserValue = A.reduce<UTxO, Assets>({}, (acc, utxo) =>
addAssets(acc, utxo.assets),
)(await context.lucid.utxosAt(context.users.user.address));
await runAndAwaitTx(
context.lucid,
createStableswapOrder(
context.assetConfigs[0].iassetTokenNameAscii,
EXAMPLE_TOKEN_1,
10_000_000n,
true,
stableswapPool.datum,
context.systemParams,
context.lucid,
),
);
const stableswapOrder = await findSingleStableswapOrder(
context.lucid,
context.systemParams.validatorHashes.stableswapHash,
fromText(context.assetConfigs[0].iassetTokenNameAscii),
EXAMPLE_TOKEN_1,
);
await createUtxoAtTreasury(
mkLovelacesOf(2_000_000n),
context.systemParams,
context,
);
const treasuryUtxo = await findRandomTreasuryUtxoWithOnlyAda(
context.lucid,
context.systemParams,
);
context.lucid.selectWallet.fromSeed(context.users.admin.seedPhrase);
const [__, treasuryValChange] = await getValueChangeAtAddressAfterAction(
context.lucid,
mkTreasuryAddr(context.lucid, context.systemParams),
async () =>
benchmarkAndAwaitTx(
'Stableswap - Batch a single order to mint',
await batchProcessStableswapOrders(
[stableswapOrder.utxo],
stableswapPool.utxo,
treasuryUtxo,
context.systemParams,
context.lucid,
),
context.lucid,
context.emulator,
),
);
///////////////////////////////////
// Checks after last transaction //
///////////////////////////////////
stableswapPool = await findStableswapPool(
context.lucid,
context.systemParams.validatorHashes.cdpHash,
fromSystemParamsAsset(context.systemParams.stableswapParams.cdpToken),
fromText(context.assetConfigs[0].iassetTokenNameAscii),
EXAMPLE_TOKEN_1,
);
const finalUserValue = A.reduce<UTxO, Assets>({}, (acc, utxo) =>
addAssets(acc, utxo.assets),
)(await context.lucid.utxosAt(context.users.user.address));
const userValueDiff = addAssets(
finalUserValue,
negateAssets(initialUserValue),
);
const iassetAc = {
currencySymbol: fromHex(
context.systemParams.stableswapParams.iassetSymbol.unCurrencySymbol,
),
tokenName: stableswapOrder.datum.iasset,
};
assert(
assetClassValueOf(treasuryValChange, iassetAc) == 50_000n,
'Unexpected iAsset value received by the treasury',
);
assert(
assetClassValueOf(stableswapPool.utxo.assets, EXAMPLE_TOKEN_1) ==
10_000_000n,
'Unexpected value held by stableswap pool',
);
assert(
assetClassValueOf(userValueDiff, iassetAc) == 10_000_000n - 50_000n,
'Unexpected value received by order owner',
);
});
test<IndigoTestContext>('Stableswap - Batch a single order to mint with no minting fee', async (context: IndigoTestContext) => {
context.lucid.selectWallet.fromSeed(context.users.admin.seedPhrase);
await runCreateStableswapPool(
context.assetConfigs[0].iassetTokenNameAscii,
EXAMPLE_TOKEN_1,
context,
rationalFromInt(1n),
// 0% minting fee.
rationalZero,
);
let stableswapPool = await findStableswapPool(
context.lucid,
context.systemParams.validatorHashes.cdpHash,
fromSystemParamsAsset(context.systemParams.stableswapParams.cdpToken),
fromText(context.assetConfigs[0].iassetTokenNameAscii),
EXAMPLE_TOKEN_1,
);
context.lucid.selectWallet.fromSeed(context.users.user.seedPhrase);
const initialUserValue = A.reduce<UTxO, Assets>({}, (acc, utxo) =>
addAssets(acc, utxo.assets),
)(await context.lucid.utxosAt(context.users.user.address));
await runAndAwaitTx(
context.lucid,
createStableswapOrder(
context.assetConfigs[0].iassetTokenNameAscii,
EXAMPLE_TOKEN_1,
10_000_000n,
true,
stableswapPool.datum,
context.systemParams,
context.lucid,
),
);
const stableswapOrder = await findSingleStableswapOrder(
context.lucid,
context.systemParams.validatorHashes.stableswapHash,
fromText(context.assetConfigs[0].iassetTokenNameAscii),
EXAMPLE_TOKEN_1,
);
await createUtxoAtTreasury(
mkLovelacesOf(2_000_000n),
context.systemParams,
context,
);
const treasuryUtxo = await findRandomTreasuryUtxoWithOnlyAda(
context.lucid,
context.systemParams,
);
const [__, treasuryValChange] = await getValueChangeAtAddressAfterAction(
context.lucid,
mkTreasuryAddr(context.lucid, context.systemParams),
async () =>
await runAndAwaitTx(
context.lucid,
batchProcessStableswapOrders(
[stableswapOrder.utxo],
stableswapPool.utxo,
treasuryUtxo,
context.systemParams,
context.lucid,
),
),
);
///////////////////////////////////
// Checks after last transaction //
///////////////////////////////////
stableswapPool = await findStableswapPool(
context.lucid,
context.systemParams.validatorHashes.cdpHash,
fromSystemParamsAsset(context.systemParams.stableswapParams.cdpToken),
fromText(context.assetConfigs[0].iassetTokenNameAscii),
EXAMPLE_TOKEN_1,
);
const finalUserValue = A.reduce<UTxO, Assets>({}, (acc, utxo) =>
addAssets(acc, utxo.assets),
)(await context.lucid.utxosAt(context.users.user.address));
const userValueDiff = addAssets(
finalUserValue,
negateAssets(initialUserValue),
);
const iassetAc = {
currencySymbol: fromHex(
context.systemParams.stableswapParams.iassetSymbol.unCurrencySymbol,
),
tokenName: stableswapOrder.datum.iasset,
};
assert(
assetClassValueOf(treasuryValChange, iassetAc) == 0n,
'Unexpected iAsset value received by the treasury',
);
assert(
assetClassValueOf(stableswapPool.utxo.assets, EXAMPLE_TOKEN_1) ==
10_000_000n,
'Unexpected value held by stableswap pool',
);
assert(
assetClassValueOf(userValueDiff, iassetAc) == 10_000_000n,
'Unexpected value received by order owner',
);
});
test<IndigoTestContext>('Stableswap - Batch a single order to mint with collateral asset in the pool', async (context: IndigoTestContext) => {
context.lucid.selectWallet.fromSeed(context.users.admin.seedPhrase);
await runCreateStableswapPool(
context.assetConfigs[0].iassetTokenNameAscii,
EXAMPLE_TOKEN_1,
context,
);
let stableswapPool = await findStableswapPool(
context.lucid,
context.systemParams.validatorHashes.cdpHash,
fromSystemParamsAsset(context.systemParams.stableswapParams.cdpToken),
fromText(context.assetConfigs[0].iassetTokenNameAscii),
EXAMPLE_TOKEN_1,
);
context.lucid.selectWallet.fromSeed(context.users.user.seedPhrase);
await runAndAwaitTx(
context.lucid,
createStableswapOrder(
context.assetConfigs[0].iassetTokenNameAscii,
EXAMPLE_TOKEN_1,
10_000_000n,
true,
stableswapPool.datum,
context.systemParams,
context.lucid,
),
);
let stableswapOrder = await findSingleStableswapOrder(
context.lucid,
context.systemParams.validatorHashes.stableswapHash,
fromText(context.assetConfigs[0].iassetTokenNameAscii),
EXAMPLE_TOKEN_1,
);
await createUtxoAtTreasury(
mkLovelacesOf(2_000_000n),
context.systemParams,
context,
);
let treasuryUtxo = await findRandomTreasuryUtxoWithOnlyAda(
context.lucid,
context.systemParams,
);
context.lucid.selectWallet.fromSeed(context.users.admin.seedPhrase);
await runAndAwaitTx(
context.lucid,
batchProcessStableswapOrders(
[stableswapOrder.utxo],
stableswapPool.utxo,
treasuryUtxo,
context.systemParams,
context.lucid,
),
);
context.lucid.selectWallet.fromSeed(context.users.user.seedPhrase);
const initialUserValue = A.reduce<UTxO, Assets>({}, (acc, utxo) =>
addAssets(acc, utxo.assets),
)(await context.lucid.utxosAt(context.users.user.address));
await runAndAwaitTx(
context.lucid,
createStableswapOrder(
context.assetConfigs[0].iassetTokenNameAscii,
EXAMPLE_TOKEN_1,
10_000_000n,
true,
stableswapPool.datum,
context.systemParams,
context.lucid,
),
);
stableswapOrder = await findSingleStableswapOrder(
context.lucid,
context.systemParams.validatorHashes.stableswapHash,
fromText(context.assetConfigs[0].iassetTokenNameAscii),
EXAMPLE_TOKEN_1,
);
const iassetAc = {
currencySymbol: fromHex(
context.systemParams.stableswapParams.iassetSymbol.unCurrencySymbol,
),
tokenName: stableswapOrder.datum.iasset,
};
treasuryUtxo = await findRandomTreasuryUtxoWithAsset(
context.lucid,
context.systemParams,
iassetAc,
);
context.lucid.selectWallet.fromSeed(context.users.admin.seedPhrase);
const initialAdminValue = A.reduce<UTxO, Assets>({}, (acc, utxo) =>
addAssets(acc, utxo.assets),
)(await context.lucid.utxosAt(context.users.admin.address));
stableswapPool = await findStableswapPool(
context.lucid,
context.systemParams.validatorHashes.cdpHash,
fromSystemParamsAsset(context.systemParams.stableswapParams.cdpToken),
fromText(context.assetConfigs[0].iassetTokenNameAscii),
EXAMPLE_TOKEN_1,
);
const [__, treasuryValChange] = await getValueChangeAtAddressAfterAction(
context.lucid,
mkTreasuryAddr(context.lucid, context.systemParams),
async () =>
benchmarkAndAwaitTx(
'Stableswap - Batch a single order to mint with collateral in the pool',
await batchProcessStableswapOrders(
[stableswapOrder.utxo],
stableswapPool.utxo,
treasuryUtxo,
context.systemParams,
context.lucid,
),
context.lucid,
context.emulator,
),
);
///////////////////////////////////
// Checks after last transaction //
///////////////////////////////////
stableswapPool = await findStableswapPool(
context.lucid,
context.systemParams.validatorHashes.cdpHash,
fromSystemParamsAsset(context.systemParams.stableswapParams.cdpToken),
fromText(context.assetConfigs[0].iassetTokenNameAscii),
EXAMPLE_TOKEN_1,
);
const finalUserValue = A.reduce<UTxO, Assets>({}, (acc, utxo) =>
addAssets(acc, utxo.assets),
)(await context.lucid.utxosAt(context.users.user.address));
const userValueDiff = addAssets(
finalUserValue,
negateAssets(initialUserValue),
);
const finalAdminValue = A.reduce<UTxO, Assets>({}, (acc, utxo) =>
addAssets(acc, utxo.assets),
)(await context.lucid.utxosAt(context.users.admin.address));
const adminValueDiff = addAssets(
finalAdminValue,
negateAssets(initialAdminValue),
);
assert(
lovelacesAmt(adminValueDiff) >= 0n &&
lovelacesAmt(adminValueDiff) < 100_000n,
);
assert(
assetClassValueOf(treasuryValChange, iassetAc) == 50_000n,
'Unexpected iAsset value received by the treasury',
);
assert(
assetClassValueOf(stableswapPool.utxo.assets, EXAMPLE_TOKEN_1) ==
20_000_000n,
'Unexpected value held by stableswap pool',
);
assert(
assetClassValueOf(userValueDiff, iassetAc) == 10_000_000n - 50_000n,
'Unexpected value received by order owner',
);
});
test<IndigoTestContext>('Stableswap - Batch a single order to redeem', async (context: IndigoTestContext) => {
context.lucid.selectWallet.fromSeed(context.users.admin.seedPhrase);
await runCreateStableswapPool(
context.assetConfigs[0].iassetTokenNameAscii,
EXAMPLE_TOKEN_1,
context,
);
let stableswapPool = await findStableswapPool(
context.lucid,
context.systemParams.validatorHashes.cdpHash,
fromSystemParamsAsset(context.systemParams.stableswapParams.cdpToken),
fromText(context.assetConfigs[0].iassetTokenNameAscii),
EXAMPLE_TOKEN_1,
);
context.lucid.selectWallet.fromSeed(context.users.user.seedPhrase);
const initialUserValue = A.reduce<UTxO, Assets>({}, (acc, utxo) =>
addAssets(acc, utxo.assets),
)(await context.lucid.utxosAt(context.users.user.address));
// Mint iAsset to supply the pool with collateral asset.
// It also provides the treasury with a UTxO with iAsset.
await runAndAwaitTx(
context.lucid,
createStableswapOrder(
context.assetConfigs[0].iassetTokenNameAscii,
EXAMPLE_TOKEN_1,
10_000_000n,
true,
stableswapPool.datum,
context.systemParams,
context.lucid,
),
);
let stableswapOrder = await findSingleStableswapOrder(
context.lucid,
context.systemParams.validatorHashes.stableswapHash,
fromText(context.assetConfigs[0].iassetTokenNameAscii),
EXAMPLE_TOKEN_1,
);
await createUtxoAtTreasury(
mkLovelacesOf(2_000_000n),
context.systemParams,
context,
);
let treasuryUtxo = await findRandomTreasuryUtxoWithOnlyAda(
context.lucid,
context.systemParams,
);
await runAndAwaitTx(
context.lucid,
batchProcessStableswapOrders(
[stableswapOrder.utxo],
stableswapPool.utxo,
treasuryUtxo,
context.systemParams,
context.lucid,
),
);
// Redeem part of the collateral asset previously supplied to the pool.
await runAndAwaitTx(
context.lucid,
createStableswapOrder(
context.assetConfigs[0].iassetTokenNameAscii,
EXAMPLE_TOKEN_1,
5_000_000n,
false,
stableswapPool.datum,
context.systemParams,
context.lucid,
),
);
stableswapOrder = await findSingleStableswapOrder(
context.lucid,
context.systemParams.validatorHashes.stableswapHash,
fromText(context.assetConfigs[0].iassetTokenNameAscii),
EXAMPLE_TOKEN_1,
);
stableswapPool = await findStableswapPool(
context.lucid,
context.systemParams.validatorHashes.cdpHash,
fromSystemParamsAsset(context.systemParams.stableswapParams.cdpToken),
fromText(context.assetConfigs[0].iassetTokenNameAscii),
EXAMPLE_TOKEN_1,
);
const iassetAc = {
currencySymbol: fromHex(
context.systemParams.stableswapParams.iassetSymbol.unCurrencySymbol,
),
tokenName: stableswapOrder.datum.iasset,
};
treasuryUtxo = await findRandomTreasuryUtxoWithAsset(
context.lucid,
context.systemParams,
iassetAc,
);
context.lucid.selectWallet.fromSeed(context.users.admin.seedPhrase);
const initialAdminValue = A.reduce<UTxO, Assets>({}, (acc, utxo) =>
addAssets(acc, utxo.assets),
)(await context.lucid.utxosAt(context.users.admin.address));
const [__, treasuryValChange] = await getValueChangeAtAddressAfterAction(
context.lucid,
mkTreasuryAddr(context.lucid, context.systemParams),
async () =>
benchmarkAndAwaitTx(
'Stableswap - Batch a single order to redeem',
await batchProcessStableswapOrders(
[stableswapOrder.utxo],
stableswapPool.utxo,
treasuryUtxo,
context.systemParams,
context.lucid,
),
context.lucid,
context.emulator,
),
);
///////////////////////////////////
// Checks after last transaction //
///////////////////////////////////
stableswapPool = await findStableswapPool(
context.lucid,
context.systemParams.validatorHashes.cdpHash,
fromSystemParamsAsset(context.systemParams.stableswapParams.cdpToken),
fromText(context.assetConfigs[0].iassetTokenNameAscii),
EXAMPLE_TOKEN_1,
);
const finalUserValue = A.reduce<UTxO, Assets>({}, (acc, utxo) =>
addAssets(acc, utxo.assets),
)(await context.lucid.utxosAt(context.users.user.address));
const userValueDiff = addAssets(
finalUserValue,
negateAssets(initialUserValue),
);
const finalAdminValue = A.reduce<UTxO, Assets>({}, (acc, utxo) =>
addAssets(acc, utxo.assets),
)(await context.lucid.utxosAt(context.users.admin.address));
const adminValueDiff = addAssets(
finalAdminValue,
negateAssets(initialAdminValue),
);
assert(
lovelacesAmt(adminValueDiff) >= 0n &&
lovelacesAmt(adminValueDiff) < 100_000n,
);
assert(
assetClassValueOf(treasuryValChange, iassetAc) == 25_000n &&
0n <= lovelacesAmt(treasuryValChange) &&
lovelacesAmt(treasuryValChange) <= 9_000n,
'Unexpected value received by the treasury',
);
assert(
assetClassValueOf(stableswapPool.utxo.assets, EXAMPLE_TOKEN_1) ==
10_000_000n - (5_000_000n - 25_000n),
'Unexpected value held by stableswap pool',
);
assert(
assetClassValueOf(userValueDiff, iassetAc) ==
10_000_000n - 50_000n - 5_000_000n &&
assetClassValueOf(userValueDiff, EXAMPLE_TOKEN_1) ==
-10_000_000n + (5_000_000n - 25_000n),
'Unexpected value received by order owner',
);
});
test<IndigoTestContext>('Stableswap - Batch a single order to redeem with no redemption fee', async (context: IndigoTestContext) => {
context.lucid.selectWallet.fromSeed(context.users.admin.seedPhrase);
await runCreateStableswapPool(
context.assetConfigs[0].iassetTokenNameAscii,
EXAMPLE_TOKEN_1,
context,
rationalFromInt(1n),
// 0% minting fee.
rationalZero,
// 0% redemption fee.
rationalZero,
);
let stableswapPool = await findStableswapPool(
context.lucid,
context.systemParams.validatorHashes.cdpHash,
fromSystemParamsAsset(context.systemParams.stableswapParams.cdpToken),
fromText(context.assetConfigs[0].iassetTokenNameAscii),
EXAMPLE_TOKEN_1,
);
context.lucid.selectWallet.fromSeed(context.users.user.seedPhrase);
const initialUserValue = A.reduce<UTxO, Assets>({}, (acc, utxo) =>
addAssets(acc, utxo.assets),
)(await context.lucid.utxosAt(context.users.user.address));
// Mint iAsset to supply the pool with collateral asset.
await runAndAwaitTx(
context.lucid,
createStableswapOrder(
context.assetConfigs[0].iassetTokenNameAscii,
EXAMPLE_TOKEN_1,
10_000_000n,
true,
stableswapPool.datum,
context.systemParams,
context.lucid,
),
);
let stableswapOrder = await findSingleStableswapOrder(
context.lucid,
context.systemParams.validatorHashes.stableswapHash,
fromText(context.assetConfigs[0].iassetTokenNameAscii),
EXAMPLE_TOKEN_1,
);
await createUtxoAtTreasury(
mkLovelacesOf(2_000_000n),
context.systemParams,
context,
);
let treasuryUtxo = await findRandomTreasuryUtxoWithOnlyAda(
context.lucid,
context.systemParams,
);
await runAndAwaitTx(
context.lucid,
batchProcessStableswapOrders(
[stableswapOrder.utxo],
stableswapPool.utxo,
treasuryUtxo,
context.systemParams,
context.lucid,
),
);
// Redeem part of the collateral asset previously supplied to the pool.
await runAndAwaitTx(
context.lucid,
createStableswapOrder(
context.assetConfigs[0].iassetTokenNameAscii,
EXAMPLE_TOKEN_1,
5_000_000n,
false,
stableswapPool.datum,
context.systemParams,
context.lucid,
),
);
stableswapOrder = await findSingleStableswapOrder(
context.lucid,
context.systemParams.validatorHashes.stableswapHash,
fromText(context.assetConfigs[0].iassetTokenNameAscii),
EXAMPLE_TOKEN_1,
);
stableswapPool = await findStableswapPool(
context.lucid,
context.systemParams.validatorHashes.cdpHash,
fromSystemParamsAsset(context.systemParams.stableswapParams.cdpToken),
fromText(context.assetConfigs[0].iassetTokenNameAscii),
EXAMPLE_TOKEN_1,
);
const iassetAc = {
currencySymbol: fromHex(
context.systemParams.stableswapParams.iassetSymbol.unCurrencySymbol,
),
tokenName: stableswapOrder.datum.iasset,
};
// This will not be used in the transaction, but is passed only as a placeholder.
treasuryUtxo = await findRandomTreasuryUtxoWithOnlyAda(
context.lucid,
context.systemParams,
);
context.lucid.selectWallet.fromSeed(context.users.admin.seedPhrase);
const initialAdminValue = A.reduce<UTxO, Assets>({}, (acc, utxo) =>
addAssets(acc, utxo.assets),
)(await context.lucid.utxosAt(context.users.admin.address));
const [__, treasuryValChange] = await getValueChangeAtAddressAfterAction(
context.lucid,
mkTreasuryAddr(context.lucid, context.systemParams),
async () =>
runAndAwaitTx(
context.lucid,
batchProcessStableswapOrders(
[stableswapOrder.utxo],
stableswapPool.utxo,
treasuryUtxo,
context.systemParams,
context.lucid,
),
),
);
///////////////////////////////////
// Checks after last transaction //
///////////////////////////////////
stableswapPool = await findStableswapPool(
context.lucid,
context.systemParams.validatorHashes.cdpHash,
fromSystemParamsAsset(context.systemParams.stableswapParams.cdpToken),
fromText(context.assetConfigs[0].iassetTokenNameAscii),
EXAMPLE_TOKEN_1,
);
const finalUserValue = A.reduce<UTxO, Assets>({}, (acc, utxo) =>
addAssets(acc, utxo.assets),
)(await context.lucid.utxosAt(context.users.user.address));
const userValueDiff = addAssets(
finalUserValue,
negateAssets(initialUserValue),
);
const finalAdminValue = A.reduce<UTxO, Assets>({}, (acc, utxo) =>
addAssets(acc, utxo.assets),
)(await context.lucid.utxosAt(context.users.admin.address));
const adminValueDiff = addAssets(
finalAdminValue,
negateAssets(initialAdminValue),
);
// This one will result in a bigger gain for the admin as the tx fee is lower
assert(lovelacesAmt(adminValueDiff) >= 0n);
assert(
assetClassValueOf(treasuryValChange, iassetAc) == 0n,
'Unexpected value received by the treasury',
);
assert(
assetClassValueOf(stableswapPool.utxo.assets, EXAMPLE_TOKEN_1) ==
10_000_000n - 5_000_000n,
'Unexpected value held by stableswap pool',
);
assert(
assetClassValueOf(userValueDiff, iassetAc) == 10_000_000n - 5_000_000n &&
assetClassValueOf(userValueDiff, EXAMPLE_TOKEN_1) ==
-10_000_000n + 5_000_000n,
'Unexpected value received by order owner',
);
});
test<IndigoTestContext>('Stableswap - Batch a single order to redeem emptying the pool', async (context: IndigoTestContext) => {
context.lucid.selectWallet.fromSeed(context.users.admin.seedPhrase);
await runCreateStableswapPool(
context.assetConfigs[0].iassetTokenNameAscii,
EXAMPLE_TOKEN_1,
context,
);
let stableswapPool = await findStableswapPool(
context.lucid,
context.systemParams.validatorHashes.cdpHash,
fromSystemParamsAsset(context.systemParams.stableswapParams.cdpToken),
fromText(context.assetConfigs[0].iassetTokenNameAscii),
EXAMPLE_TOKEN_1,
);
const orefs = await findAllNecessaryOrefs(
context.lucid,
context.systemParams,
context.assetConfigs[0].iassetTokenNameAscii,
context.assetConfigs[0].collateralAssets[0].collateralAsset,
);
const priceOracleUtxo = await findPriceOracleFromCollateralAsset(
context.lucid,
orefs.collateralAsset,
);
await runAndAwaitTx(
context.lucid,
feedPriceOracleTx(
context.lucid,
priceOracleUtxo!,
rationalFromInt(1n),
context.assetConfigs[0].collateralAssets[0].oracleParams!,
context.emulator.slot,
),
);
context.lucid.selectWallet.fromSeed(context.users.user.seedPhrase);
// Mint extra iAsset to have enough to empty the pool.
await runAndAwaitTx(
context.lucid,
runOpenCdp(
context,
context.systemParams,
context.assetConfigs[0].iassetTokenNameAscii,
context.assetConfigs[0].collateralAssets[0].collateralAsset,
10_000_000n,
5_000_000n,
),
);
const initialUserValue = A.reduce<UTxO, Assets>({}, (acc, utxo) =>
addAssets(acc, utxo.assets),
)(await context.lucid.utxosAt(context.users.user.address));
// Mint iAsset to supply the pool with collateral asset
// It also provides the treasury with a UTxO with iAsset.
await runAndAwaitTx(
context.lucid,
createStableswapOrder(
context.assetConfigs[0].iassetTokenNameAscii,
EXAMPLE_TOKEN_1,
10_000_000n,
true,
stableswapPool.datum,
context.systemParams,
context.lucid,
),
);
let stableswapOrder = await findSingleStableswapOrder(
context.lucid,
context.systemParams.validatorHashes.stableswapHash,
fromText(context.assetConfigs[0].iassetTokenNameAscii),
EXAMPLE_TOKEN_1,
);
await createUtxoAtTreasury(
mkLovelacesOf(2_000_000n),
context.systemParams,
context,
);
let treasuryUtxo = await findRandomTreasuryUtxoWithOnlyAda(
context.lucid,
context.systemParams,
);
await runAndAwaitTx(
context.lucid,
batchProcessStableswapOrders(
[stableswapOrder.utxo],
stableswapPool.utxo,
treasuryUtxo,
context.systemParams,
context.lucid,
),
);
// Redeem all the assets left in the pool.
await runAndAwaitTx(
context.lucid,
createStableswapOrder(
context.assetConfigs[0].iassetTokenNameAscii,
EXAMPLE_TOKEN_1,
// After taking a 0.5% fee, the effective amount is 10_000_000.
10_050_251n,
false,
stableswapPool.datum,
context.systemParams,
context.lucid,
),
);
stableswapOrder = await findSingleStableswapOrder(
context.lucid,
context.systemParams.validatorHashes.stableswapHash,
fromText(context.assetConfigs[0].iassetTokenNameAscii),
EXAMPLE_TOKEN_1,
);
stableswapPool = await findStableswapPool(
context.lucid,
context.systemParams.validatorHashes.cdpHash,
fromSystemParamsAsset(context.systemParams.stableswapParams.cdpToken),
fromText(context.assetConfigs[0].iassetTokenNameAscii),
EXAMPLE_TOKEN_1,
);
const iassetAc = {
currencySymbol: fromHex(
context.systemParams.stableswapParams.iassetSymbol.unCurrencySymbol,
),
tokenName: stableswapOrder.datum.iasset,
};
treasuryUtxo = await findRandomTreasuryUtxoWithAsset(
context.lucid,
context.systemParams,
iassetAc,
);
context.lucid.selectWallet.fromSeed(context.users.admin.seedPhrase);
const initialAdminValue = A.reduce<UTxO, Assets>({}, (acc, utxo) =>
addAssets(acc, utxo.assets),
)(await context.lucid.utxosAt(context.users.admin.address));
const [__, treasuryValChange] = await getValueChangeAtAddressAfterAction(
context.lucid,
mkTreasuryAddr(context.lucid, context.systemParams),
async () =>
runAndAwaitTx(
context.lucid,
batchProcessStableswapOrders(
[stableswapOrder.utxo],
stableswapPool.utxo,
treasuryUtxo,
context.systemParams,
context.lucid,
),
),
);
///////////////////////////////////
// Checks after last transaction //
///////////////////////////////////
stableswapPool = await findStableswapPool(
context.lucid,
context.systemParams.validatorHashes.cdpHash,
fromSystemParamsAsset(context.systemParams.stableswapParams.cdpToken),
fromText(context.assetConfigs[0].iassetTokenNameAscii),
EXAMPLE_TOKEN_1,
);
const finalUserValue = A.reduce<UTxO, Assets>({}, (acc, utxo) =>
addAssets(acc, utxo.assets),
)(await context.lucid.utxosAt(context.users.user.address));
const userValueDiff = addAssets(
finalUserValue,
negateAssets(initialUserValue),
);
const finalAdminValue = A.reduce<UTxO, Assets>({}, (acc, utxo) =>
addAssets(acc, utxo.assets),
)(await context.lucid.utxosAt(context.users.admin.address));
const adminValueDiff = addAssets(
finalAdminValue,
negateAssets(initialAdminValue),
);
assert(
lovelacesAmt(adminValueDiff) >= 0n &&
lovelacesAmt(adminValueDiff) < 100_000n,
);
assert(
assetClassValueOf(treasuryValChange, iassetAc) == 50_251n &&
0n <= lovelacesAmt(treasuryValChange) &&
lovelacesAmt(treasuryValChange) <= 9_000n,
'Unexpected value received by the treasury',
);
assert(
assetClassValueOf(stableswapPool.utxo.assets, EXAMPLE_TOKEN_1) == 0n,
'Unexpected value held by stableswap pool',
);
assert(
assetClassValueOf(userValueDiff, iassetAc) ==
10_000_000n - 50_000n - 10_050_251n &&
assetClassValueOf(userValueDiff, EXAMPLE_TOKEN_1) ==
-10_000_000n + 10_000_000n,
'Unexpected value received by order owner',
);
});
test<IndigoTestContext>('Stableswap - Batch a single order to mint assets with smaller scale', async (context: IndigoTestContext) => {
context.lucid.selectWallet.fromSeed(context.users.admin.seedPhrase);
await runCreateStableswapPool(
context.assetConfigs[0].iassetTokenNameAscii,
EXAMPLE_TOKEN_1,
context,
rationalFromInt(1_000n),
);
let stableswapPool = await findStableswapPool(
context.lucid,
context.systemParams.validatorHashes.cdpHash,
fromSystemParamsAsset(context.systemParams.stableswapParams.cdpToken),
fromText(context.assetConfigs[0].iassetTokenNameAscii),
EXAMPLE_TOKEN_1,
);
context.lucid.selectWallet.fromSeed(context.users.user.seedPhrase);
const initialUserValue = A.reduce<UTxO, Assets>({}, (acc, utxo) =>
addAssets(acc, utxo.assets),
)(await context.lucid.utxosAt(context.users.user.address));
await runAndAwaitTx(
context.lucid,
createStableswapOrder(
context.assetConfigs[0].iassetTokenNameAscii,
EXAMPLE_TOKEN_1,
10_000_000n,
true,
stableswapPool.datum,
context.systemParams,
context.lucid,
),
);
const stableswapOrder = await findSingleStableswapOrder(
context.lucid,
context.systemParams.validatorHashes.stableswapHash,
fromText(context.assetConfigs[0].iassetTokenNameAscii),
EXAMPLE_TOKEN_1,
);
await createUtxoAtTreasury(
mkLovelacesOf(2_000_000n),
context.systemParams,
context,
);
const treasuryUtxo = await findRandomTreasuryUtxoWithOnlyAda(
context.lucid,
context.systemParams,
);
const [__, treasuryValChange] = await getValueChangeAtAddressAfterAction(
context.lucid,
mkTreasuryAddr(context.lucid, context.systemParams),
async () =>
runAndAwaitTx(
context.lucid,
batchProcessStableswapOrders(
[stableswapOrder.utxo],
stableswapPool.utxo,
treasuryUtxo,
context.systemParams,
context.lucid,
),
),
);
///////////////////////////////////
// Checks after last transaction //
///////////////////////////////////
stableswapPool = await findStableswapPool(
context.lucid,
context.systemParams.validatorHashes.cdpHash,
fromSystemParamsAsset(context.systemParams.stableswapParams.cdpToken),
fromText(context.assetConfigs[0].iassetTokenNameAscii),
EXAMPLE_TOKEN_1,
);
const finalUserValue = A.reduce<UTxO, Assets>({}, (acc, utxo) =>
addAssets(acc, utxo.assets),
)(await context.lucid.utxosAt(context.users.user.address));
const userValueDiff = addAssets(
finalUserValue,
negateAssets(initialUserValue),
);
const iassetAc = {
currencySymbol: fromHex(
context.systemParams.stableswapParams.iassetSymbol.unCurrencySymbol,
),
tokenName: stableswapOrder.datum.iasset,
};
assert(
assetClassValueOf(treasuryValChange, iassetAc) == 50n,
'Unexpected iAsset value received by the treasury',
);
assert(
assetClassValueOf(stableswapPool.utxo.assets, EXAMPLE_TOKEN_1) ==
10_000_000n,
'Unexpected value held by stableswap pool',
);
assert(
assetClassValueOf(userValueDiff, iassetAc) == 10_000n - 50n,
'Unexpected value received by order owner',
);
});
test<IndigoTestContext>('Stableswap - Batch a single order to mint assets with bigger scale', async (context: IndigoTestContext) => {
context.lucid.selectWallet.fromSeed(context.users.admin.seedPhrase);
await runCreateStableswapPool(
context.assetConfigs[0].iassetTokenNameAscii,
EXAMPLE_TOKEN_1,
context,
{ numerator: 1n, denominator: 1_000n },
);
let stableswapPool = await findStableswapPool(
context.lucid,
context.systemParams.validatorHashes.cdpHash,
fromSystemParamsAsset(context.systemParams.stableswapParams.cdpToken),
fromText(context.assetConfigs[0].iassetTokenNameAscii),
EXAMPLE_TOKEN_1,
);
context.lucid.selectWallet.fromSeed(context.users.user.seedPhrase);
const initialUserValue = A.reduce<UTxO, Assets>({}, (acc, utxo) =>
addAssets(acc, utxo.assets),
)(await context.lucid.utxosAt(context.users.user.address));
await runAndAwaitTx(
context.lucid,
createStableswapOrder(
context.assetConfigs[0].iassetTokenNameAscii,
EXAMPLE_TOKEN_1,
10_000_000n,
true,
stableswapPool.datum,
context.systemParams,
context.lucid,
),
);
const stableswapOrder = await findSingleStableswapOrder(
context.lucid,
context.systemParams.validatorHashes.stableswapHash,
fromText(context.assetConfigs[0].iassetTokenNameAscii),
EXAMPLE_TOKEN_1,
);
await createUtxoAtTreasury(
mkLovelacesOf(2_000_000n),
context.systemParams,
context,
);
const treasuryUtxo = await findRandomTreasuryUtxoWithOnlyAda(
context.lucid,
context.systemParams,
);
const [__, treasuryValChange] = await getValueChangeAtAddressAfterAction(
context.lucid,
mkTreasuryAddr(context.lucid, context.systemParams),
async () =>
runAndAwaitTx(
context.lucid,
batchProcessStableswapOrders(
[stableswapOrder.utxo],
stableswapPool.utxo,
treasuryUtxo,
context.systemParams,
context.lucid,
),
),
);
///////////////////////////////////
// Checks after last transaction //
///////////////////////////////////
stableswapPool = await findStableswapPool(
context.lucid,
context.systemParams.validatorHashes.cdpHash,
fromSystemParamsAsset(context.systemParams.stableswapParams.cdpToken),
fromText(context.assetConfigs[0].iassetTokenNameAscii),
EXAMPLE_TOKEN_1,
);
const finalUserValue = A.reduce<UTxO, Assets>({}, (acc, utxo) =>
addAssets(acc, utxo.assets),
)(await context.lucid.utxosAt(context.users.user.address));
const userValueDiff = addAssets(
finalUserValue,
negateAssets(initialUserValue),
);
const iassetAc = {
currencySymbol: fromHex(
context.systemParams.stableswapParams.iassetSymbol.unCurrencySymbol,
),
tokenName: stableswapOrder.datum.iasset,
};
assert(
assetClassValueOf(treasuryValChange, iassetAc) == 50_000_000n,
'Unexpected iAsset value received by the treasury',
);
assert(
assetClassValueOf(stableswapPool.utxo.assets, EXAMPLE_TOKEN_1) ==
10_000_000n,
'Unexpected value held by stableswap pool',
);
assert(
assetClassValueOf(userValueDiff, iassetAc) == 10_000_000_000n - 50_000_000n,
'Unexpected value received by order owner',
);
});
test<IndigoTestContext>('Stableswap - Batch a single order to redeem assets with smaller scale', async (context: IndigoTestContext) => {
context.lucid.selectWallet.fromSeed(context.users.admin.seedPhrase);
await runCreateStableswapPool(
context.assetConfigs[0].iassetTokenNameAscii,
EXAMPLE_TOKEN_1,
context,
rationalFromInt(1_000n),
);
let stableswapPool = await findStableswapPool(
context.lucid,
context.systemParams.validatorHashes.cdpHash,
fromSystemParamsAsset(context.systemParams.stableswapParams.cdpToken),
fromText(context.assetConfigs[0].iassetTokenNameAscii),
EXAMPLE_TOKEN_1,
);
context.lucid.selectWallet.fromSeed(context.users.user.seedPhrase);
const initialUserValue = A.reduce<UTxO, Assets>({}, (acc, utxo) =>
addAssets(acc, utxo.assets),
)(await context.lucid.utxosAt(context.users.user.address));
// Mint iAsset to supply the pool with collateral asset.
// It also provides the treasury with a UTxO with iAsset.
await runAndAwaitTx(
context.lucid,
createStableswapOrder(
context.assetConfigs[0].iassetTokenNameAscii,
EXAMPLE_TOKEN_1,
10_000_000n,
true,
stableswapPool.datum,
context.systemParams,
context.lucid,
),
);
let stableswapOrder = await findSingleStableswapOrder(
context.lucid,
context.systemParams.validatorHashes.stableswapHash,
fromText(context.assetConfigs[0].iassetTokenNameAscii),
EXAMPLE_TOKEN_1,
);
await createUtxoAtTreasury(
mkLovelacesOf(2_000_000n),
context.systemParams,
context,
);
let treasuryUtxo = await findRandomTreasuryUtxoWithOnlyAda(
context.lucid,
context.systemParams,
);
await runAndAwaitTx(
context.lucid,
batchProcessStableswapOrders(
[stableswapOrder.utxo],
stableswapPool.utxo,
treasuryUtxo,
context.systemParams,
context.lucid,
),
);
// Redeem part of the collateral asset previously supplied to the pool.
await runAndAwaitTx(
context.lucid,
createStableswapOrder(
context.assetConfigs[0].iassetTokenNameAscii,
EXAMPLE_TOKEN_1,
5_000n,
false,
stableswapPool.datum,
context.systemParams,
context.lucid,
),
);
stableswapOrder = await findSingleStableswapOrder(
context.lucid,
context.systemParams.validatorHashes.stableswapHash,
fromText(context.assetConfigs[0].iassetTokenNameAscii),
EXAMPLE_TOKEN_1,
);
stableswapPool = await findStableswapPool(
context.lucid,
context.systemParams.validatorHashes.cdpHash,
fromSystemParamsAsset(context.systemParams.stableswapParams.cdpToken),
fromText(context.assetConfigs[0].iassetTokenNameAscii),
EXAMPLE_TOKEN_1,
);
const iassetAc = {
currencySymbol: fromHex(
context.systemParams.stableswapParams.iassetSymbol.unCurrencySymbol,
),
tokenName: stableswapOrder.datum.iasset,
};
treasuryUtxo = await findRandomTreasuryUtxoWithAsset(
context.lucid,
context.systemParams,
iassetAc,
);
const [__, treasuryValChange] = await getValueChangeAtAddressAfterAction(
context.lucid,
mkTreasuryAddr(context.lucid, context.systemParams),
async () =>
runAndAwaitTx(
context.lucid,
batchProcessStableswapOrders(
[stableswapOrder.utxo],
stableswapPool.utxo,
treasuryUtxo,
context.systemParams,
context.lucid,
),
),
);
///////////////////////////////////
// Checks after last transaction //
///////////////////////////////////
stableswapPool = await findStableswapPool(
context.lucid,
context.systemParams.validatorHashes.cdpHash,
fromSystemParamsAsset(context.systemParams.stableswapParams.cdpToken),
fromText(context.assetConfigs[0].iassetTokenNameAscii),
EXAMPLE_TOKEN_1,
);
const finalUserValue = A.reduce<UTxO, Assets>({}, (acc, utxo) =>
addAssets(acc, utxo.assets),
)(await context.lucid.utxosAt(context.users.user.address));
const userValueDiff = addAssets(
finalUserValue,
negateAssets(initialUserValue),
);
assert(
assetClassValueOf(treasuryValChange, iassetAc) == 25n &&
0n <= lovelacesAmt(treasuryValChange) &&
lovelacesAmt(treasuryValChange) <= 9_000n,
'Unexpected value received by the treasury',
);
assert(
assetClassValueOf(stableswapPool.utxo.assets, EXAMPLE_TOKEN_1) ==
10_000_000n - (5_000_000n - 25_000n),
'Unexpected value held by stableswap pool',
);
assert(
assetClassValueOf(userValueDiff, iassetAc) == 10_000n - 50n - 5_000n &&
assetClassValueOf(userValueDiff, EXAMPLE_TOKEN_1) ==
-10_000_000n + (5_000_000n - 25_000n),
'Unexpected value received by order owner',
);
});
test<IndigoTestContext>('Stableswap - Batch a single order to redeem assets with bigger scale', async (context: IndigoTestContext) => {
context.lucid.selectWallet.fromSeed(context.users.admin.seedPhrase);
await runCreateStableswapPool(
context.assetConfigs[0].iassetTokenNameAscii,
EXAMPLE_TOKEN_1,
context,
{ numerator: 1n, denominator: 1_000n },
);
let stableswapPool = await findStableswapPool(
context.lucid,
context.systemParams.validatorHashes.cdpHash,
fromSystemParamsAsset(context.systemParams.stableswapParams.cdpToken),
fromText(context.assetConfigs[0].iassetTokenNameAscii),
EXAMPLE_TOKEN_1,
);
context.lucid.selectWallet.fromSeed(context.users.user.seedPhrase);
const initialUserValue = A.reduce<UTxO, Assets>({}, (acc, utxo) =>
addAssets(acc, utxo.assets),
)(await context.lucid.utxosAt(context.users.user.address));
// Mint iAsset to supply the pool with collateral asset.
// It also provides the treasury with a UTxO with iAsset.
await runAndAwaitTx(
context.lucid,
createStableswapOrder(
context.assetConfigs[0].iassetTokenNameAscii,
EXAMPLE_TOKEN_1,
10_000_000n,
true,
stableswapPool.datum,
context.systemParams,
context.lucid,
),
);
let stableswapOrder = await findSingleStableswapOrder(
context.lucid,
context.systemParams.validatorHashes.stableswapHash,
fromText(context.assetConfigs[0].iassetTokenNameAscii),
EXAMPLE_TOKEN_1,
);
await createUtxoAtTreasury(
mkLovelacesOf(2_000_000n),
context.systemParams,
context,
);
let treasuryUtxo = await findRandomTreasuryUtxoWithOnlyAda(
context.lucid,
context.systemParams,
);
await runAndAwaitTx(
context.lucid,
batchProcessStableswapOrders(
[stableswapOrder.utxo],
stableswapPool.utxo,
treasuryUtxo,
context.systemParams,
context.lucid,
),
);
// Redeem part of the collateral asset previously supplied to the pool.
await runAndAwaitTx(
context.lucid,
createStableswapOrder(
context.assetConfigs[0].iassetTokenNameAscii,
EXAMPLE_TOKEN_1,
5_000_000_000n,
false,
stableswapPool.datum,
context.systemParams,
context.lucid,
),
);
stableswapOrder = await findSingleStableswapOrder(
context.lucid,
context.systemParams.validatorHashes.stableswapHash,
fromText(context.assetConfigs[0].iassetTokenNameAscii),
EXAMPLE_TOKEN_1,
);
stableswapPool = await findStableswapPool(
context.lucid,
context.systemParams.validatorHashes.cdpHash,
fromSystemParamsAsset(context.systemParams.stableswapParams.cdpToken),
fromText(context.assetConfigs[0].iassetTokenNameAscii),
EXAMPLE_TOKEN_1,
);
const iassetAc = {
currencySymbol: fromHex(
context.systemParams.stableswapParams.iassetSymbol.unCurrencySymbol,
),
tokenName: stableswapOrder.datum.iasset,
};
treasuryUtxo = await findRandomTreasuryUtxoWithAsset(
context.lucid,
context.systemParams,
iassetAc,
);
const [__, treasuryValChange] = await getValueChangeAtAddressAfterAction(
context.lucid,
mkTreasuryAddr(context.lucid, context.systemParams),
async () =>
runAndAwaitTx(
context.lucid,
batchProcessStableswapOrders(
[stableswapOrder.utxo],
stableswapPool.utxo,
treasuryUtxo,
context.systemParams,
context.lucid,
),
),
);
///////////////////////////////////
// Checks after last transaction //
///////////////////////////////////
stableswapPool = await findStableswapPool(
context.lucid,
context.systemParams.validatorHashes.cdpHash,
fromSystemParamsAsset(context.systemParams.stableswapParams.cdpToken),
fromText(context.assetConfigs[0].iassetTokenNameAscii),
EXAMPLE_TOKEN_1,
);
const finalUserValue = A.reduce<UTxO, Assets>({}, (acc, utxo) =>
addAssets(acc, utxo.assets),
)(await context.lucid.utxosAt(context.users.user.address));
const userValueDiff = addAssets(
finalUserValue,
negateAssets(initialUserValue),
);
assert(
assetClassValueOf(treasuryValChange, iassetAc) == 25_000_000n &&
0n <= lovelacesAmt(treasuryValChange) &&
lovelacesAmt(treasuryValChange) <= 9_000n,
'Unexpected value received by the treasury',
);
assert(
assetClassValueOf(stableswapPool.utxo.assets, EXAMPLE_TOKEN_1) ==
10_000_000n - (5_000_000n - 25_000n),
'Unexpected value held by stableswap pool',
);
assert(
assetClassValueOf(userValueDiff, iassetAc) ==
10_000_000_000n - 50_000_000n - 5_000_000_000n &&
assetClassValueOf(userValueDiff, EXAMPLE_TOKEN_1) ==
-10_000_000n + (5_000_000n - 25_000n),
'Unexpected value received by order owner',
);
});
test<IndigoTestContext>('Stableswap - Batch multiple orders to mint from same owner, 11', async (context: IndigoTestContext) => {
context.lucid.selectWallet.fromSeed(context.users.admin.seedPhrase);
await runCreateStableswapPool(
context.assetConfigs[0].iassetTokenNameAscii,
EXAMPLE_TOKEN_1,
context,
);
let stableswapPool = await findStableswapPool(
context.lucid,