@indigo-labs/indigo-sdk 0.3.15 → 0.3.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/.github/workflows/ci.yml +2 -4
  2. package/dist/index.d.mts +40 -8
  3. package/dist/index.d.ts +40 -8
  4. package/dist/index.js +125 -69
  5. package/dist/index.mjs +124 -71
  6. package/package.json +2 -1
  7. package/scripts/bench.sh +62 -0
  8. package/src/contracts/iasset/helpers.ts +1 -1
  9. package/src/contracts/poll/types-poll-new.ts +10 -5
  10. package/src/contracts/rob/helpers.ts +122 -43
  11. package/src/contracts/rob/transactions.ts +12 -3
  12. package/src/contracts/rob-leverage/helpers.ts +4 -1
  13. package/src/contracts/stability-pool/types-new.ts +11 -5
  14. package/src/contracts/stableswap/transactions.ts +1 -5
  15. package/src/contracts/staking/types-new.ts +5 -3
  16. package/src/contracts/treasury/transactions.ts +8 -2
  17. package/src/validators/cdp-creator-validator.ts +1 -1
  18. package/src/validators/cdp-redeem-validator.ts +1 -1
  19. package/src/validators/cdp-validator.ts +1 -1
  20. package/src/validators/collector-validator.ts +1 -1
  21. package/src/validators/execute-validator.ts +1 -1
  22. package/src/validators/governance-validator.ts +1 -1
  23. package/src/validators/iasset-validator.ts +1 -1
  24. package/src/validators/interest-collection-validator.ts +1 -1
  25. package/src/validators/interest-oracle-validator.ts +1 -1
  26. package/src/validators/poll-manager-validator.ts +1 -1
  27. package/src/validators/poll-shard-validator.ts +1 -1
  28. package/src/validators/price-oracle-validator.ts +1 -1
  29. package/src/validators/pyth-feed-validator.ts +1 -1
  30. package/src/validators/rob-validator.ts +1 -1
  31. package/src/validators/stability-pool-validator.ts +1 -1
  32. package/src/validators/stableswap-validator.ts +1 -1
  33. package/src/validators/staking-validator.ts +1 -1
  34. package/src/validators/treasury-validator.ts +1 -1
  35. package/src/validators/version-record-policy.ts +1 -1
  36. package/tests/cdp/actions.ts +1 -1
  37. package/tests/cdp/cdp-queries.ts +1 -1
  38. package/tests/cdp/cdp.test.ts +1 -1
  39. package/tests/cdp/transactions-mutated.ts +1 -1
  40. package/tests/gov/gov.test.ts +78 -12
  41. package/tests/interest-collection/interest-collection.test.ts +5 -5
  42. package/tests/rob/rob-leverage.test.ts +12 -27
  43. package/tests/rob/rob.test.ts +56 -52
  44. package/tests/stability-pool.test.ts +7 -4
  45. package/tests/stableswap/stableswap.test.ts +1 -1
  46. package/tests/treasury/actions.ts +67 -0
  47. package/tests/{queries → treasury}/treasury-queries.ts +11 -2
  48. package/tests/treasury/treasury.test.ts +342 -0
  49. package/vitest.config.ts +1 -1
  50. package/tests/treasury.test.ts +0 -242
@@ -1126,8 +1126,8 @@ describe('ROB', () => {
1126
1126
  );
1127
1127
 
1128
1128
  const amtToSpendBefore = robCollateralAmtToSpend(
1129
- robBefore.utxo,
1130
- robBefore.datum,
1129
+ robBefore.utxo.assets,
1130
+ robBefore.datum.orderType,
1131
1131
  );
1132
1132
 
1133
1133
  await runAndAwaitTx(
@@ -1149,8 +1149,8 @@ describe('ROB', () => {
1149
1149
  );
1150
1150
 
1151
1151
  const amtToSpendAfter = robCollateralAmtToSpend(
1152
- adjustedUtxo1.utxo,
1153
- adjustedUtxo1.datum,
1152
+ adjustedUtxo1.utxo.assets,
1153
+ adjustedUtxo1.datum.orderType,
1154
1154
  );
1155
1155
 
1156
1156
  assert(amtToSpendBefore - amtToSpendAfter === 1_000_000n);
@@ -1170,8 +1170,8 @@ describe('ROB', () => {
1170
1170
  );
1171
1171
 
1172
1172
  const amtToSpendBefore = robCollateralAmtToSpend(
1173
- robBefore.utxo,
1174
- robBefore.datum,
1173
+ robBefore.utxo.assets,
1174
+ robBefore.datum.orderType,
1175
1175
  );
1176
1176
 
1177
1177
  await runAndAwaitTx(
@@ -1193,8 +1193,8 @@ describe('ROB', () => {
1193
1193
  );
1194
1194
 
1195
1195
  const amtToSpendAfter = robCollateralAmtToSpend(
1196
- adjustedUtxo2.utxo,
1197
- adjustedUtxo2.datum,
1196
+ adjustedUtxo2.utxo.assets,
1197
+ adjustedUtxo2.datum.orderType,
1198
1198
  );
1199
1199
 
1200
1200
  strictEqual(amtToSpendAfter - amtToSpendBefore, 5_000_000n);
@@ -1271,20 +1271,26 @@ describe('ROB', () => {
1271
1271
  };
1272
1272
 
1273
1273
  assert(
1274
- robAmtToSpend(
1275
- adjustedUtxo1.utxo,
1276
- adjustedUtxo1.datum,
1277
- sysParams.cdpParams.cdpAssetSymbol,
1278
- ) ===
1274
+ robAmtToSpend(adjustedUtxo1.utxo.assets, adjustedUtxo1.datum.orderType, {
1275
+ currencySymbol: fromHex(
1276
+ sysParams.cdpParams.cdpAssetSymbol.unCurrencySymbol,
1277
+ ),
1278
+ tokenName: adjustedUtxo1.datum.iasset,
1279
+ }) ===
1279
1280
  20_000_000n - 1_000_000n,
1280
1281
  );
1281
1282
 
1282
1283
  expect(
1283
1284
  assetClassValueOf(adjustedUtxo1.utxo.assets, iassetAc) ===
1284
1285
  robAmtToSpend(
1285
- adjustedUtxo1.utxo,
1286
- adjustedUtxo1.datum,
1287
- sysParams.cdpParams.cdpAssetSymbol,
1286
+ adjustedUtxo1.utxo.assets,
1287
+ adjustedUtxo1.datum.orderType,
1288
+ {
1289
+ currencySymbol: fromHex(
1290
+ sysParams.cdpParams.cdpAssetSymbol.unCurrencySymbol,
1291
+ ),
1292
+ tokenName: adjustedUtxo1.datum.iasset,
1293
+ },
1288
1294
  ),
1289
1295
  'IAssets to spend has to equal iassets in UTXO',
1290
1296
  ).toBeTruthy();
@@ -1310,20 +1316,26 @@ describe('ROB', () => {
1310
1316
  const expectedResultAdaAmt = 20_000_000n - 1_000_000n + 5_000_000n;
1311
1317
 
1312
1318
  strictEqual(
1313
- robAmtToSpend(
1314
- adjustedUtxo2.utxo,
1315
- adjustedUtxo2.datum,
1316
- sysParams.cdpParams.cdpAssetSymbol,
1317
- ),
1319
+ robAmtToSpend(adjustedUtxo2.utxo.assets, adjustedUtxo2.datum.orderType, {
1320
+ currencySymbol: fromHex(
1321
+ sysParams.cdpParams.cdpAssetSymbol.unCurrencySymbol,
1322
+ ),
1323
+ tokenName: adjustedUtxo2.datum.iasset,
1324
+ }),
1318
1325
  expectedResultAdaAmt,
1319
1326
  );
1320
1327
 
1321
1328
  expect(
1322
1329
  assetClassValueOf(adjustedUtxo2.utxo.assets, iassetAc) >=
1323
1330
  robAmtToSpend(
1324
- adjustedUtxo2.utxo,
1325
- adjustedUtxo2.datum,
1326
- sysParams.cdpParams.cdpAssetSymbol,
1331
+ adjustedUtxo2.utxo.assets,
1332
+ adjustedUtxo2.datum.orderType,
1333
+ {
1334
+ currencySymbol: fromHex(
1335
+ sysParams.cdpParams.cdpAssetSymbol.unCurrencySymbol,
1336
+ ),
1337
+ tokenName: adjustedUtxo2.datum.iasset,
1338
+ },
1327
1339
  ),
1328
1340
  'IAssets to spend has to equal iassets in UTXO',
1329
1341
  ).toBeTruthy();
@@ -1390,8 +1402,8 @@ describe('ROB', () => {
1390
1402
  const redemptionIAssetAmt = 11_000_000n;
1391
1403
 
1392
1404
  const amtToSpendBefore = robCollateralAmtToSpend(
1393
- robUtxo.utxo,
1394
- robUtxo.datum,
1405
+ robUtxo.utxo.assets,
1406
+ robUtxo.datum.orderType,
1395
1407
  );
1396
1408
 
1397
1409
  await runAndAwaitTx(
@@ -1420,7 +1432,10 @@ describe('ROB', () => {
1420
1432
 
1421
1433
  expect(
1422
1434
  amtToSpendBefore -
1423
- robCollateralAmtToSpend(redeemedRob.utxo, redeemedRob.datum),
1435
+ robCollateralAmtToSpend(
1436
+ redeemedRob.utxo.assets,
1437
+ redeemedRob.datum.orderType,
1438
+ ),
1424
1439
  'ROB has wrong number redeemed',
1425
1440
  ).toEqual(
1426
1441
  // Since price is 1
@@ -1565,7 +1580,10 @@ describe('ROB', () => {
1565
1580
  );
1566
1581
 
1567
1582
  expect(
1568
- robCollateralAmtToSpend(redeemedRob.utxo, redeemedRob.datum),
1583
+ robCollateralAmtToSpend(
1584
+ redeemedRob.utxo.assets,
1585
+ redeemedRob.datum.orderType,
1586
+ ),
1569
1587
  'Wrong amt to spend in datum',
1570
1588
  ).toEqual(initialDeposit - expectedRedeemedAmt);
1571
1589
 
@@ -1713,11 +1731,12 @@ describe('ROB', () => {
1713
1731
  );
1714
1732
 
1715
1733
  expect(
1716
- robAmtToSpend(
1717
- redeemedRob.utxo,
1718
- redeemedRob.datum,
1719
- sysParams.cdpParams.cdpAssetSymbol,
1720
- ),
1734
+ robAmtToSpend(redeemedRob.utxo.assets, redeemedRob.datum.orderType, {
1735
+ currencySymbol: fromHex(
1736
+ sysParams.cdpParams.cdpAssetSymbol.unCurrencySymbol,
1737
+ ),
1738
+ tokenName: redeemedRob.datum.iasset,
1739
+ }),
1721
1740
  'Wrong amt to spend in datum',
1722
1741
  ).toEqual(initialDeposit - expectedRedemptionAmt);
1723
1742
 
@@ -2223,24 +2242,6 @@ describe('ROB', () => {
2223
2242
 
2224
2243
  const payoutIAssetAmt = 11_000_000n;
2225
2244
 
2226
- // const expectedRedemptionAmt =(
2227
- // {
2228
- // getOnChainInt:
2229
- // payoutCollateralAmt -
2230
- // calculateFeeFromPercentage(
2231
- // (
2232
- // await findIAssetNew(
2233
- // context,
2234
- // sysParams,
2235
- // iusdAssetInfo.iassetTokenNameAscii,
2236
- // )
2237
- // ).datum.redemptionReimbursementPercentage,
2238
- // payoutCollateralAmt,
2239
- // ),
2240
- // },
2241
- // newPrice,
2242
- // ).getOnChainInt;
2243
-
2244
2245
  await runAndAwaitTx(
2245
2246
  context.lucid,
2246
2247
  runRedeemRob(
@@ -2290,7 +2291,10 @@ describe('ROB', () => {
2290
2291
 
2291
2292
  // Since price is 1
2292
2293
  expect(
2293
- robCollateralAmtToSpend(adjustedRob.utxo, adjustedRob.datum),
2294
+ robCollateralAmtToSpend(
2295
+ adjustedRob.utxo.assets,
2296
+ adjustedRob.datum.orderType,
2297
+ ),
2294
2298
  ).toEqual(
2295
2299
  // 20mil start, -1mil adjusted, rest redeemed
2296
2300
  20_000_000n -
@@ -1924,7 +1924,7 @@ describe('Stability pool', () => {
1924
1924
  });
1925
1925
 
1926
1926
  // These are the most significant tests for benchmarking the maximum number of collateral assets supported.
1927
- describe('Liquidate', () => {
1927
+ describe.skip('Liquidate', () => {
1928
1928
  test<MyContext>('Liquidate with 10 reward assets in the pool - collecting with 2 assets in treasury', async (context: MyContext) => {
1929
1929
  context.lucid.selectWallet.fromSeed(context.users.admin.seedPhrase);
1930
1930
 
@@ -2317,7 +2317,7 @@ describe('Stability pool', () => {
2317
2317
  }
2318
2318
  });
2319
2319
 
2320
- test<MyContext>('Liquidate with 9 reward assets in the pool and increasing epoch', async (context: MyContext) => {
2320
+ test<MyContext>('Liquidate with 10 reward assets in the pool and increasing epoch', async (context: MyContext) => {
2321
2321
  context.lucid.selectWallet.fromSeed(context.users.admin.seedPhrase);
2322
2322
 
2323
2323
  const initialAssets = [
@@ -2330,9 +2330,12 @@ describe('Stability pool', () => {
2330
2330
  collateralAssetF,
2331
2331
  collateralAssetG,
2332
2332
  collateralAssetH,
2333
+ collateralAssetI,
2333
2334
  ];
2334
2335
 
2335
- expect(initialAssets.length, 'Unexpected reward assets count').toEqual(9);
2336
+ expect(initialAssets.length, 'Unexpected reward assets count').toEqual(
2337
+ 10,
2338
+ );
2336
2339
 
2337
2340
  const [sysParams, [iusdAssetInfo]] = await init(
2338
2341
  context.lucid,
@@ -2484,7 +2487,7 @@ describe('Stability pool', () => {
2484
2487
  iusdAssetInfo,
2485
2488
  async (tx) =>
2486
2489
  benchmarkAndAwaitTx(
2487
- 'Stability Pool - Liquidate with 9 reward assets in the pool and increasing epoch',
2490
+ 'Stability Pool - Liquidate with 10 reward assets in the pool and increasing epoch',
2488
2491
  tx,
2489
2492
  context.lucid,
2490
2493
  context.emulator,
@@ -60,7 +60,7 @@ import { expectScriptFailure } from '../utils/asserts';
60
60
  import {
61
61
  findRandomTreasuryUtxoWithOnlyAda,
62
62
  findRandomTreasuryUtxoWithAsset,
63
- } from '../queries/treasury-queries';
63
+ } from '../treasury/treasury-queries';
64
64
  import { createUtxoAtTreasury } from '../endpoints/treasury';
65
65
  import { rationalFromInt, rationalZero } from '../../src/types/rational';
66
66
 
@@ -0,0 +1,67 @@
1
+ import { Assets, TxBuilder } from '@lucid-evolution/lucid';
2
+ import { LucidContext } from '../test-helpers';
3
+ import { createUtxoAtTreasury } from '../endpoints/treasury';
4
+ import { SystemParams, treasuryMerge, treasurySplit } from '../../src';
5
+ import { findAllTreasuryUtxos } from './treasury-queries';
6
+ import { assert } from 'vitest';
7
+
8
+ export async function treasuryMergeTx(
9
+ context: LucidContext,
10
+ sysParams: SystemParams,
11
+ treasuryOutputs: Assets[],
12
+ ): Promise<TxBuilder> {
13
+ for (const output of treasuryOutputs) {
14
+ await createUtxoAtTreasury(output, sysParams, context);
15
+ }
16
+
17
+ const treasuryUtxos = await findAllTreasuryUtxos(context.lucid, sysParams);
18
+
19
+ // Simpler approach: for each expected output in treasuryOutputs, find one UTxO with exactly matching assets and take it
20
+ // Find UTxOs for each expected output, but remove it from the candidate list as we match
21
+ const availableUtxos = [...treasuryUtxos];
22
+ const matchedTreasuryUtxos = treasuryOutputs
23
+ .map((expectedAssets) => {
24
+ const idx = availableUtxos.findIndex((utxo) => {
25
+ const utxoAssets = utxo.assets;
26
+ const keys1 = Object.keys(utxoAssets).sort();
27
+ const keys2 = Object.keys(expectedAssets).sort();
28
+ if (keys1.length !== keys2.length) return false;
29
+ return keys1.every(
30
+ (k, i) => k === keys2[i] && utxoAssets[k] === expectedAssets[k],
31
+ );
32
+ });
33
+ if (idx !== -1) {
34
+ return availableUtxos.splice(idx, 1)[0];
35
+ } else {
36
+ return undefined;
37
+ }
38
+ })
39
+ .filter((utxo) => utxo !== undefined);
40
+
41
+ assert(
42
+ matchedTreasuryUtxos.length === treasuryOutputs.length,
43
+ 'Expected all treasury outputs to be matched',
44
+ );
45
+
46
+ return await treasuryMerge(matchedTreasuryUtxos, context.lucid, sysParams);
47
+ }
48
+
49
+ export async function treasurySplitTx(
50
+ context: LucidContext,
51
+ sysParams: SystemParams,
52
+ treasuryOutput: Assets,
53
+ ): Promise<TxBuilder> {
54
+ await createUtxoAtTreasury(treasuryOutput, sysParams, context);
55
+
56
+ const treasuryUtxos = await findAllTreasuryUtxos(context.lucid, sysParams);
57
+
58
+ const matchedTreasuryUtxo = treasuryUtxos.find((utxo) =>
59
+ Object.keys(treasuryOutput).every(
60
+ (key) => utxo.assets[key] === treasuryOutput[key],
61
+ ),
62
+ );
63
+
64
+ assert(matchedTreasuryUtxo !== undefined, 'Expected a single treasury UTXO');
65
+
66
+ return await treasurySplit(matchedTreasuryUtxo, context.lucid, sysParams);
67
+ }
@@ -1,9 +1,10 @@
1
1
  import { LucidEvolution, UTxO } from '@lucid-evolution/lucid';
2
- import { SystemParams } from '../../src';
2
+ import { fromSystemParamsAsset, SystemParams } from '../../src';
3
3
  import { option as O, function as F } from 'fp-ts';
4
4
  import {
5
5
  AssetClass,
6
6
  assetClassToUnit,
7
+ assetClassValueOf,
7
8
  getRandomElement,
8
9
  } from '@3rd-eye-labs/cardano-offchain-common';
9
10
 
@@ -85,6 +86,7 @@ export async function findAllTreasuryUtxos(
85
86
  export async function findAllTreasuryUtxosWithNonAdaAsset(
86
87
  lucid: LucidEvolution,
87
88
  sysParams: SystemParams,
89
+ includeDaoToken: boolean = true,
88
90
  ): Promise<UTxO[]> {
89
91
  // We need to consider both with staking credential and without.
90
92
  const treasuryUtxos = await lucid.utxosAt({
@@ -93,7 +95,14 @@ export async function findAllTreasuryUtxosWithNonAdaAsset(
93
95
  });
94
96
 
95
97
  const treasuryUtxosWithNonAdaAsset = treasuryUtxos.filter(
96
- (utxo) => Object.keys(utxo.assets).length !== 1,
98
+ (utxo) =>
99
+ Object.keys(utxo.assets).length !== 1 &&
100
+ (includeDaoToken
101
+ ? true
102
+ : assetClassValueOf(
103
+ utxo.assets,
104
+ fromSystemParamsAsset(sysParams.govParams.daoIdentityToken),
105
+ ) === 0n),
97
106
  );
98
107
 
99
108
  return treasuryUtxosWithNonAdaAsset;
@@ -0,0 +1,342 @@
1
+ import {
2
+ addAssets,
3
+ Emulator,
4
+ EmulatorAccount,
5
+ fromHex,
6
+ fromText,
7
+ generateEmulatorAccount,
8
+ Lucid,
9
+ } from '@lucid-evolution/lucid';
10
+ import { beforeEach, describe, test } from 'vitest';
11
+ import { LucidContext } from '../test-helpers';
12
+ import { treasuryCollect } from '../../src';
13
+ import {
14
+ EXAMPLE_TOKEN_1,
15
+ EXAMPLE_TOKEN_2,
16
+ EXAMPLE_TOKEN_3,
17
+ MAINNET_PROTOCOL_PARAMETERS,
18
+ } from '../indigo-test-helpers';
19
+ import { benchmarkAndAwaitTx } from '../utils/benchmark-utils';
20
+ import { findRandomTreasuryUtxoWithOnlyAda } from './treasury-queries';
21
+ import {
22
+ adaAssetClass,
23
+ AssetClass,
24
+ mkLovelacesOf,
25
+ } from '@3rd-eye-labs/cardano-offchain-common';
26
+ import { mkAssetsOf } from '@3rd-eye-labs/cardano-offchain-common';
27
+ import { expectScriptFailure } from '../utils/asserts';
28
+ import { treasuryMergeTx, treasurySplitTx } from './actions';
29
+ import { init } from '../endpoints/initialize';
30
+ import { iusdInitialAssetCfg } from '../mock/assets-mock';
31
+
32
+ type MyContext = LucidContext<{
33
+ admin: EmulatorAccount;
34
+ user: EmulatorAccount;
35
+ withdrawalAccount: EmulatorAccount;
36
+ }>;
37
+
38
+ const testAssetA: AssetClass = {
39
+ currencySymbol: fromHex(
40
+ // random generated
41
+ 'cc072059ae741791b7b9c23d9baea6a0b0d764dec617ce7e027a8daa',
42
+ ),
43
+ tokenName: fromHex(fromText('A')),
44
+ };
45
+ const testAssetB: AssetClass = {
46
+ currencySymbol: fromHex(
47
+ // random generated
48
+ 'cc072059ae741791b7b9c23d9baea6a0b0d764dec617ce7e027a8dab',
49
+ ),
50
+ tokenName: fromHex(fromText('B')),
51
+ };
52
+
53
+ const testAssetC: AssetClass = {
54
+ currencySymbol: fromHex(
55
+ // random generated
56
+ 'aa072059ae741791b7b9c23d9baea6a0b0d764dec617ce7e027a8dac',
57
+ ),
58
+ tokenName: fromHex(fromText('C')),
59
+ };
60
+
61
+ const testAssetD: AssetClass = {
62
+ currencySymbol: fromHex(
63
+ // random generated
64
+ 'cc072059ae741791b7b9c23d9baea6a0b0d764dec617ce7e027a8dad',
65
+ ),
66
+ tokenName: fromHex(fromText('D')),
67
+ };
68
+
69
+ const testAssetE: AssetClass = {
70
+ currencySymbol: fromHex(
71
+ // random generated
72
+ 'cc072059ae741791b7b9c23d9baea6a0b0d764dec617ce7e027a8dae',
73
+ ),
74
+ tokenName: fromHex(fromText('E')),
75
+ };
76
+
77
+ const testAssetF: AssetClass = {
78
+ currencySymbol: fromHex(
79
+ // random generated
80
+ 'cc072059ae741791b7b9c23d9baea6a0b0d764dec617ce7e027a8daf',
81
+ ),
82
+ tokenName: fromHex(fromText('F')),
83
+ };
84
+
85
+ const testAssetG: AssetClass = {
86
+ currencySymbol: fromHex(
87
+ // random generated
88
+ 'cc072059ae741791b7b9c23d9baea6a0b0d764dec617ce7e027a8dba',
89
+ ),
90
+ tokenName: fromHex(fromText('G')),
91
+ };
92
+
93
+ const testAssetH: AssetClass = {
94
+ currencySymbol: fromHex(
95
+ // random generated
96
+ 'cc072059ae741791b7b9c23d9baea6a0b0d764dec617ce7e027a8dbb',
97
+ ),
98
+ tokenName: fromHex(fromText('H')),
99
+ };
100
+
101
+ const testAssetI: AssetClass = {
102
+ currencySymbol: fromHex(
103
+ // random generated
104
+ 'cc072059ae741791b7b9c23d9baea6a0b0d764dec617ce7e027a8dbc',
105
+ ),
106
+ tokenName: fromHex(fromText('I')),
107
+ };
108
+
109
+ const testAssetJ: AssetClass = {
110
+ currencySymbol: fromHex(
111
+ // random generated
112
+ 'cc072059ae741791b7b9c23d9baea6a0b0d764dec617ce7e027a8dbd',
113
+ ),
114
+ tokenName: fromHex(fromText('J')),
115
+ };
116
+
117
+ const testAssetK: AssetClass = {
118
+ currencySymbol: fromHex(
119
+ // random generated
120
+ 'cc072059ae741791b7b9c23d9baea6a0b0d764dec617ce7e027a8dbe',
121
+ ),
122
+ tokenName: fromHex(fromText('K')),
123
+ };
124
+
125
+ // NOTE: Withdrawing and PrepareWithdrawal from Treasury is tested in gov.test.ts
126
+ describe('Treasury', () => {
127
+ beforeEach<MyContext>(async (context: MyContext) => {
128
+ context.users = {
129
+ admin: generateEmulatorAccount({
130
+ lovelace: BigInt(100_000_000_000_000),
131
+ }),
132
+ user: generateEmulatorAccount(
133
+ addAssets(
134
+ mkLovelacesOf(100_000_000_000_000n),
135
+ mkAssetsOf(EXAMPLE_TOKEN_1, 1_000_000_000_000_000n),
136
+ mkAssetsOf(EXAMPLE_TOKEN_2, 1_000_000_000_000_000n),
137
+ mkAssetsOf(EXAMPLE_TOKEN_3, 1_000_000_000_000_000n),
138
+ mkAssetsOf(testAssetA, 1_000_000_000_000_000n),
139
+ mkAssetsOf(testAssetB, 1_000_000_000_000_000n),
140
+ mkAssetsOf(testAssetC, 1_000_000_000_000_000n),
141
+ mkAssetsOf(testAssetD, 1_000_000_000_000_000n),
142
+ mkAssetsOf(testAssetE, 1_000_000_000_000_000n),
143
+ mkAssetsOf(testAssetF, 1_000_000_000_000_000n),
144
+ mkAssetsOf(testAssetG, 1_000_000_000_000_000n),
145
+ mkAssetsOf(testAssetH, 1_000_000_000_000_000n),
146
+ mkAssetsOf(testAssetI, 1_000_000_000_000_000n),
147
+ mkAssetsOf(testAssetJ, 1_000_000_000_000_000n),
148
+ mkAssetsOf(testAssetK, 1_000_000_000_000_000n),
149
+ ),
150
+ ),
151
+ withdrawalAccount: generateEmulatorAccount({}),
152
+ };
153
+
154
+ context.emulator = new Emulator(
155
+ [context.users.admin, context.users.user],
156
+ MAINNET_PROTOCOL_PARAMETERS,
157
+ );
158
+ context.lucid = await Lucid(context.emulator, 'Custom');
159
+ });
160
+
161
+ test<MyContext>('Merge (3 lovelace UTxOs)', async (context: MyContext) => {
162
+ context.lucid.selectWallet.fromSeed(context.users.user.seedPhrase);
163
+
164
+ const [sysParams, __] = await init(
165
+ context.lucid,
166
+ [iusdInitialAssetCfg()],
167
+ context.emulator.slot,
168
+ );
169
+
170
+ await benchmarkAndAwaitTx(
171
+ 'Treasury - Merge (3 lovelace UTxOs)',
172
+ await treasuryMergeTx(context, sysParams, [
173
+ mkLovelacesOf(50_000_000n),
174
+ mkLovelacesOf(50_000_000n),
175
+ mkLovelacesOf(50_000_000n),
176
+ ]),
177
+ context.lucid,
178
+ context.emulator,
179
+ );
180
+ });
181
+
182
+ test<MyContext>('Merge (3 INDY UTxOs)', async (context: MyContext) => {
183
+ context.lucid.selectWallet.fromSeed(context.users.user.seedPhrase);
184
+
185
+ const [sysParams, __] = await init(
186
+ context.lucid,
187
+ [iusdInitialAssetCfg()],
188
+ context.emulator.slot,
189
+ );
190
+
191
+ await benchmarkAndAwaitTx(
192
+ 'Treasury - Merge (3 INDY UTxOs)',
193
+ await treasuryMergeTx(context, sysParams, [
194
+ addAssets(
195
+ mkLovelacesOf(5_000_000n),
196
+ mkAssetsOf(EXAMPLE_TOKEN_1, 1_000_000_000n),
197
+ ),
198
+ addAssets(
199
+ mkLovelacesOf(5_000_000n),
200
+ mkAssetsOf(EXAMPLE_TOKEN_1, 1_000_000_000n),
201
+ ),
202
+ addAssets(
203
+ mkLovelacesOf(5_000_000n),
204
+ mkAssetsOf(EXAMPLE_TOKEN_1, 1_000_000_000n),
205
+ ),
206
+ ]),
207
+ context.lucid,
208
+ context.emulator,
209
+ );
210
+ });
211
+
212
+ test<MyContext>('Merge (fail, 1 lovelace, 2 INDY UTxOs)', async (context: MyContext) => {
213
+ context.lucid.selectWallet.fromSeed(context.users.user.seedPhrase);
214
+
215
+ const [sysParams, __] = await init(
216
+ context.lucid,
217
+ [iusdInitialAssetCfg()],
218
+ context.emulator.slot,
219
+ );
220
+
221
+ await expectScriptFailure(
222
+ 'All inputs have to contain the same merging assets',
223
+ treasuryMergeTx(context, sysParams, [
224
+ mkLovelacesOf(5_000_000n),
225
+ addAssets(
226
+ mkLovelacesOf(5_000_000n),
227
+ mkAssetsOf(EXAMPLE_TOKEN_1, 1_000_000_000n),
228
+ ),
229
+ addAssets(
230
+ mkLovelacesOf(5_000_000n),
231
+ mkAssetsOf(EXAMPLE_TOKEN_1, 1_000_000_000n),
232
+ ),
233
+ ]),
234
+ );
235
+ });
236
+
237
+ test<MyContext>('Split (12 assets)', async (context: MyContext) => {
238
+ context.lucid.selectWallet.fromSeed(context.users.user.seedPhrase);
239
+
240
+ const [sysParams, __] = await init(
241
+ context.lucid,
242
+ [iusdInitialAssetCfg()],
243
+ context.emulator.slot,
244
+ );
245
+
246
+ await benchmarkAndAwaitTx(
247
+ 'Treasury - Split (12 assets)',
248
+ await treasurySplitTx(
249
+ context,
250
+ sysParams,
251
+ addAssets(
252
+ mkLovelacesOf(5_000_000n),
253
+ mkAssetsOf(testAssetA, 1n),
254
+ mkAssetsOf(testAssetB, 1n),
255
+ mkAssetsOf(testAssetC, 1n),
256
+ mkAssetsOf(testAssetD, 1n),
257
+ mkAssetsOf(testAssetE, 1n),
258
+ mkAssetsOf(testAssetF, 1n),
259
+ mkAssetsOf(testAssetG, 1n),
260
+ mkAssetsOf(testAssetH, 1n),
261
+ mkAssetsOf(testAssetI, 1n),
262
+ mkAssetsOf(testAssetJ, 1n),
263
+ mkAssetsOf(testAssetK, 1n),
264
+ ),
265
+ ),
266
+ context.lucid,
267
+ context.emulator,
268
+ );
269
+ });
270
+
271
+ test<MyContext>('Split (fail, lovelace only)', async (context: MyContext) => {
272
+ context.lucid.selectWallet.fromSeed(context.users.user.seedPhrase);
273
+
274
+ const [sysParams, __] = await init(
275
+ context.lucid,
276
+ [iusdInitialAssetCfg()],
277
+ context.emulator.slot,
278
+ );
279
+
280
+ await expectScriptFailure(
281
+ 'All inputs must have more than 1 non-ADA asset or 1 non-ADA asset and more than 2x ADA buffer',
282
+ treasurySplitTx(context, sysParams, mkLovelacesOf(5_000_000n)),
283
+ );
284
+ });
285
+
286
+ test<MyContext>('Collect non-positive amount or negative extra lovelaces fails', async (context: MyContext) => {
287
+ context.lucid.selectWallet.fromSeed(context.users.user.seedPhrase);
288
+
289
+ const [sysParams, __] = await init(
290
+ context.lucid,
291
+ [iusdInitialAssetCfg()],
292
+ context.emulator.slot,
293
+ );
294
+
295
+ const treasuryUTxO = await findRandomTreasuryUtxoWithOnlyAda(
296
+ context.lucid,
297
+ sysParams,
298
+ );
299
+
300
+ // This tests that the amount to collect cannot be negative.
301
+ await expectScriptFailure(
302
+ 'Collected amount is positive',
303
+ treasuryCollect(
304
+ adaAssetClass,
305
+ -1_000_000n,
306
+ 0n,
307
+ context.lucid,
308
+ sysParams,
309
+ treasuryUTxO,
310
+ treasuryUTxO,
311
+ ),
312
+ );
313
+
314
+ // This tests that the amount to collect cannot be zero.
315
+ await expectScriptFailure(
316
+ 'Collected amount is positive',
317
+ treasuryCollect(
318
+ adaAssetClass,
319
+ 0n,
320
+ 0n,
321
+ context.lucid,
322
+ sysParams,
323
+ treasuryUTxO,
324
+ treasuryUTxO,
325
+ ),
326
+ );
327
+
328
+ // This tests that the extra lovelaces cannot be negative.
329
+ await expectScriptFailure(
330
+ 'Collected amount is positive',
331
+ treasuryCollect(
332
+ adaAssetClass,
333
+ 1n,
334
+ -1_000_000n,
335
+ context.lucid,
336
+ sysParams,
337
+ treasuryUTxO,
338
+ treasuryUTxO,
339
+ ),
340
+ );
341
+ });
342
+ });