@indigo-labs/indigo-sdk 0.2.42 → 0.3.1

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 (202) hide show
  1. package/.github/workflows/ci.yml +4 -2
  2. package/README.md +88 -15
  3. package/dist/index.d.mts +3012 -2194
  4. package/dist/index.d.ts +3012 -2194
  5. package/dist/index.js +9849 -6198
  6. package/dist/index.mjs +8733 -4933
  7. package/package.json +14 -3
  8. package/src/contracts/cdp/helpers.ts +68 -72
  9. package/src/contracts/cdp/scripts.ts +50 -13
  10. package/src/contracts/cdp/transactions.ts +841 -546
  11. package/src/contracts/cdp/types-new.ts +256 -0
  12. package/src/contracts/cdp/types.ts +26 -144
  13. package/src/contracts/cdp-creator/scripts.ts +15 -9
  14. package/src/contracts/cdp-creator/types-new.ts +50 -0
  15. package/src/contracts/cdp-creator/types.ts +5 -31
  16. package/src/contracts/collector/scripts.ts +1 -1
  17. package/src/contracts/collector/transactions.ts +23 -13
  18. package/src/contracts/collector/types-new.ts +17 -0
  19. package/src/contracts/execute/scripts.ts +19 -10
  20. package/src/contracts/execute/types-new.ts +44 -0
  21. package/src/contracts/execute/types.ts +5 -38
  22. package/src/contracts/gov/helpers.ts +187 -51
  23. package/src/contracts/gov/scripts.ts +17 -10
  24. package/src/contracts/gov/transactions.ts +599 -271
  25. package/src/contracts/gov/types-new.ts +253 -100
  26. package/src/contracts/gov/types.ts +4 -71
  27. package/src/contracts/iasset/helpers.ts +172 -0
  28. package/src/contracts/iasset/scripts.ts +38 -0
  29. package/src/contracts/iasset/types.ts +154 -0
  30. package/src/contracts/initialize/actions.ts +768 -0
  31. package/src/contracts/initialize/helpers.ts +611 -36
  32. package/src/contracts/initialize/types.ts +102 -28
  33. package/src/contracts/interest-collection/helpers.ts +19 -0
  34. package/src/contracts/interest-collection/scripts.ts +44 -0
  35. package/src/contracts/interest-collection/transactions.ts +436 -0
  36. package/src/contracts/interest-collection/types-new.ts +50 -0
  37. package/src/contracts/interest-collection/types.ts +26 -0
  38. package/src/contracts/interest-oracle/helpers.ts +2 -30
  39. package/src/contracts/interest-oracle/scripts.ts +1 -1
  40. package/src/contracts/interest-oracle/transactions.ts +21 -16
  41. package/src/contracts/interest-oracle/types-new.ts +32 -0
  42. package/src/contracts/interest-oracle/types.ts +1 -40
  43. package/src/contracts/one-shot/transactions.ts +1 -2
  44. package/src/contracts/poll/helpers.ts +5 -23
  45. package/src/contracts/poll/scripts.ts +12 -13
  46. package/src/contracts/poll/types-poll-manager.ts +1 -19
  47. package/src/contracts/poll/types-poll-new.ts +170 -0
  48. package/src/contracts/poll/types-poll-shard.ts +2 -24
  49. package/src/contracts/price-oracle/helpers.ts +1 -4
  50. package/src/contracts/price-oracle/scripts.ts +3 -8
  51. package/src/contracts/price-oracle/transactions.ts +32 -25
  52. package/src/contracts/price-oracle/types-new.ts +50 -0
  53. package/src/contracts/price-oracle/types.ts +2 -36
  54. package/src/contracts/pyth-feed/helpers.ts +58 -0
  55. package/src/contracts/pyth-feed/scripts.ts +15 -0
  56. package/src/contracts/pyth-feed/types.ts +181 -0
  57. package/src/contracts/rob/helpers.ts +405 -0
  58. package/src/contracts/rob/scripts.ts +35 -0
  59. package/src/contracts/rob/transactions.ts +410 -0
  60. package/src/contracts/rob/types-new.ts +128 -0
  61. package/src/contracts/rob/types.ts +16 -0
  62. package/src/contracts/rob-leverage/helpers.ts +424 -0
  63. package/src/contracts/{leverage → rob-leverage}/transactions.ts +68 -48
  64. package/src/contracts/stability-pool/helpers.ts +714 -230
  65. package/src/contracts/stability-pool/scripts.ts +20 -15
  66. package/src/contracts/stability-pool/transactions.ts +628 -496
  67. package/src/contracts/stability-pool/types-new.ts +247 -100
  68. package/src/contracts/stability-pool/types.ts +5 -22
  69. package/src/contracts/stableswap/helpers.ts +22 -0
  70. package/src/contracts/stableswap/scripts.ts +37 -0
  71. package/src/contracts/stableswap/transactions.ts +647 -0
  72. package/src/contracts/stableswap/types-new.ts +131 -0
  73. package/src/contracts/stableswap/types.ts +17 -0
  74. package/src/contracts/staking/helpers.ts +49 -34
  75. package/src/contracts/staking/scripts.ts +1 -1
  76. package/src/contracts/staking/transactions.ts +85 -130
  77. package/src/contracts/staking/types-new.ts +60 -28
  78. package/src/contracts/staking/types.ts +1 -28
  79. package/src/contracts/treasury/helpers.ts +21 -0
  80. package/src/contracts/treasury/scripts.ts +16 -26
  81. package/src/contracts/treasury/transactions.ts +256 -27
  82. package/src/contracts/treasury/types-new.ts +69 -0
  83. package/src/contracts/treasury/types.ts +2 -43
  84. package/src/contracts/version-registry/scripts.ts +2 -2
  85. package/src/contracts/version-registry/types-new.ts +6 -7
  86. package/src/index.ts +37 -20
  87. package/src/scripts/auth-token-policy.ts +3 -2
  88. package/src/scripts/iasset-policy.ts +3 -2
  89. package/src/types/evolution-schema-options.ts +3 -3
  90. package/src/types/generic.ts +17 -89
  91. package/src/types/multisig.ts +48 -0
  92. package/src/types/on-chain-decimal.ts +14 -7
  93. package/src/types/rational.ts +61 -0
  94. package/src/types/system-params.ts +237 -41
  95. package/src/utils/array-utils.ts +70 -1
  96. package/src/utils/bigint-utils.ts +12 -0
  97. package/src/utils/indigo-helpers.ts +8 -10
  98. package/src/utils/lucid-utils.ts +47 -40
  99. package/src/utils/oracle-helpers.ts +62 -0
  100. package/src/utils/pyth/decode.ts +223 -0
  101. package/src/utils/pyth/encode.ts +262 -0
  102. package/src/utils/pyth/index.ts +14 -0
  103. package/src/utils/pyth/types.ts +87 -0
  104. package/src/validators/always-succeed-validator.ts +6 -0
  105. package/src/validators/cdp-creator-validator.ts +2 -2
  106. package/src/validators/cdp-redeem-validator.ts +7 -0
  107. package/src/validators/cdp-validator.ts +2 -2
  108. package/src/validators/collector-validator.ts +2 -2
  109. package/src/validators/execute-validator.ts +2 -2
  110. package/src/validators/governance-validator.ts +2 -2
  111. package/src/validators/iasset-validator.ts +7 -0
  112. package/src/validators/interest-collection-validator.ts +7 -0
  113. package/src/validators/interest-oracle-validator.ts +2 -2
  114. package/src/validators/poll-manager-validator.ts +2 -2
  115. package/src/validators/poll-shard-validator.ts +2 -2
  116. package/src/validators/price-oracle-validator.ts +7 -0
  117. package/src/validators/pyth-feed-validator.ts +7 -0
  118. package/src/validators/rob-validator.ts +7 -0
  119. package/src/validators/stability-pool-validator.ts +2 -2
  120. package/src/validators/stableswap-validator.ts +7 -0
  121. package/src/validators/staking-validator.ts +2 -2
  122. package/src/validators/treasury-validator.ts +2 -2
  123. package/src/validators/version-record-policy.ts +2 -2
  124. package/src/validators/version-registry-validator.ts +2 -2
  125. package/tests/always-succeed/script.ts +7 -0
  126. package/tests/bigint-utils.test.ts +41 -0
  127. package/tests/cdp/actions.ts +610 -0
  128. package/tests/cdp/cdp-helpers.ts +55 -0
  129. package/tests/cdp/cdp-queries.ts +440 -0
  130. package/tests/cdp/cdp.test.ts +6087 -0
  131. package/tests/cdp/transactions-mutated.ts +1729 -0
  132. package/tests/data/system-params.json +177 -34
  133. package/tests/datums.test.ts +209 -210
  134. package/tests/endpoints/initialize.ts +68 -0
  135. package/tests/endpoints/interest-collector.ts +37 -0
  136. package/tests/endpoints/treasury.ts +70 -0
  137. package/tests/gov/actions.ts +406 -0
  138. package/tests/gov/gov.test.ts +4450 -0
  139. package/tests/{queries → gov}/governance-queries.ts +6 -3
  140. package/tests/hash-checks.test.ts +38 -11
  141. package/tests/indigo-test-helpers.ts +100 -0
  142. package/tests/initialize.test.ts +61 -9
  143. package/tests/interest-collection/interest-collection.test.ts +892 -0
  144. package/tests/interest-collection/interest-collector-queries.ts +49 -0
  145. package/tests/interest-collection/transactions-mutated.ts +260 -0
  146. package/tests/interest-oracle.test.ts +43 -35
  147. package/tests/mock/assets-mock.ts +234 -23
  148. package/tests/mock/protocol-params-mock.ts +21 -0
  149. package/tests/price-oracle/actions.ts +163 -0
  150. package/tests/price-oracle/price-oracle-queries.ts +12 -0
  151. package/tests/price-oracle/price-oracle.test.ts +240 -0
  152. package/tests/price-oracle/transactions-mutated.ts +62 -0
  153. package/tests/pyth/endpoints.ts +96 -0
  154. package/tests/pyth/helpers.ts +37 -0
  155. package/tests/pyth/pyth-encoding.test.ts +376 -0
  156. package/tests/pyth/pyth-indigo.test.ts +509 -0
  157. package/tests/pyth/pyth.test.ts +300 -0
  158. package/tests/queries/execute-queries.ts +6 -5
  159. package/tests/queries/iasset-queries.ts +175 -5
  160. package/tests/queries/interest-oracle-queries.ts +4 -2
  161. package/tests/queries/poll-queries.ts +8 -9
  162. package/tests/queries/stability-pool-queries.ts +95 -48
  163. package/tests/queries/staking-queries.ts +4 -2
  164. package/tests/queries/treasury-queries.ts +80 -5
  165. package/tests/rob/actions.ts +58 -0
  166. package/tests/{lrp-leverage.test.ts → rob/rob-leverage.test.ts} +393 -296
  167. package/tests/rob/rob-queries.ts +95 -0
  168. package/tests/rob/rob.test.ts +3762 -0
  169. package/tests/rob/transactions-mutated.ts +853 -0
  170. package/tests/script-size.test.ts +240 -0
  171. package/tests/setup.ts +135 -0
  172. package/tests/stability-pool/actions.ts +220 -0
  173. package/tests/stability-pool.test.ts +6121 -667
  174. package/tests/stableswap/stableswap-actions.ts +84 -0
  175. package/tests/stableswap/stableswap-queries.ts +89 -0
  176. package/tests/stableswap/stableswap.test.ts +3891 -0
  177. package/tests/stableswap/transactions-mutated.ts +348 -0
  178. package/tests/staking.test.ts +82 -99
  179. package/tests/test-helpers.ts +58 -11
  180. package/tests/treasury.test.ts +242 -0
  181. package/tests/utils/asserts.ts +74 -0
  182. package/tests/utils/benchmark-utils.ts +81 -0
  183. package/tests/utils/index.ts +122 -4
  184. package/tsconfig.json +9 -1
  185. package/vitest.config.ts +3 -1
  186. package/src/contracts/collector/types.ts +0 -16
  187. package/src/contracts/initialize/transactions.ts +0 -891
  188. package/src/contracts/leverage/helpers.ts +0 -424
  189. package/src/contracts/lrp/helpers.ts +0 -294
  190. package/src/contracts/lrp/scripts.ts +0 -27
  191. package/src/contracts/lrp/transactions.ts +0 -250
  192. package/src/contracts/lrp/types.ts +0 -131
  193. package/src/contracts/poll/types-poll.ts +0 -88
  194. package/src/contracts/vesting/helpers.ts +0 -218
  195. package/src/utils/value-helpers.ts +0 -37
  196. package/src/validators/lrp-validator.ts +0 -7
  197. package/tests/cdp.test.ts +0 -1528
  198. package/tests/gov.test.ts +0 -2011
  199. package/tests/lrp.test.ts +0 -673
  200. package/tests/queries/cdp-queries.ts +0 -220
  201. package/tests/queries/lrp-queries.ts +0 -76
  202. package/tests/queries/price-oracle-queries.ts +0 -10
@@ -0,0 +1,892 @@
1
+ import { beforeEach, describe, expect, test } from 'vitest';
2
+ import { IndigoTestContext, repeat, runAndAwaitTx } from '../test-helpers';
3
+ import { expectScriptFailure } from '../utils/asserts';
4
+ import {
5
+ createIndigoTestContext,
6
+ EXAMPLE_TOKEN_1,
7
+ EXAMPLE_TOKEN_2,
8
+ EXAMPLE_TOKEN_3,
9
+ } from '../indigo-test-helpers';
10
+ import {
11
+ findAdminInterestCollectors as findAdminInterestCollector,
12
+ findAdminInterestCollectors,
13
+ findAllInterestCollectors,
14
+ findRandomNonAdminInterestCollector,
15
+ } from './interest-collector-queries';
16
+ import { benchmarkAndAwaitTx } from '../utils/benchmark-utils';
17
+ import {
18
+ batchCollectInterest,
19
+ distributeInterest,
20
+ updatePermissions,
21
+ } from '../../src/contracts/interest-collection/transactions';
22
+ import {
23
+ adaAssetClass,
24
+ assetClassValueOf,
25
+ matchSingle,
26
+ mkAssetsOf,
27
+ mkLovelacesOf,
28
+ } from '@3rd-eye-labs/cardano-offchain-common';
29
+ import {
30
+ addAssets,
31
+ fromHex,
32
+ paymentCredentialOf,
33
+ stakeCredentialOf,
34
+ } from '@lucid-evolution/lucid';
35
+ import {
36
+ testCollectInterest,
37
+ testDistributeInterest,
38
+ } from './transactions-mutated';
39
+ import { signersAllOf, fromSystemParamsAsset } from '../../src';
40
+ import {
41
+ findAllActiveCdps,
42
+ findAllNecessaryOrefs,
43
+ findPriceOracleFromCollateralAsset,
44
+ } from '../cdp/cdp-queries';
45
+ import { feedPriceOracleTx } from '../../src/contracts/price-oracle/transactions';
46
+ import { createUtxosAtInterestCollector } from '../endpoints/interest-collector';
47
+ import { runOpenCdp } from '../cdp/actions';
48
+ import { runFeedPriceToOracle } from '../price-oracle/actions';
49
+ import { runTestDepositCdpWithInterestVar } from '../cdp/transactions-mutated';
50
+ import { findGov } from '../gov/governance-queries';
51
+ import { toDataMultisig } from '../../src/types/multisig';
52
+ import { createMultipleUtxosAtTreasury } from '../endpoints/treasury';
53
+ import { rationalFromInt } from '../../src/types/rational';
54
+
55
+ describe('Interest Collection', () => {
56
+ beforeEach<IndigoTestContext>(async (context: IndigoTestContext) => {
57
+ await createIndigoTestContext(context);
58
+ });
59
+
60
+ test<IndigoTestContext>('Collect Interest - Cannot collect without interacting with a CDP', async (context: IndigoTestContext) => {
61
+ const interestCollectionUtxo = await findRandomNonAdminInterestCollector(
62
+ context.lucid,
63
+ context.systemParams.validatorHashes.interestCollectionHash,
64
+ fromSystemParamsAsset(
65
+ context.systemParams.interestCollectionParams.multisigUtxoNft,
66
+ ),
67
+ );
68
+
69
+ await expectScriptFailure(
70
+ 'Single CDP input in the transaction.',
71
+ testCollectInterest(
72
+ mkLovelacesOf(1000000n),
73
+ context.lucid,
74
+ context.systemParams,
75
+ context.lucid.newTx(),
76
+ interestCollectionUtxo,
77
+ { kind: 'CollectWithoutCDP' },
78
+ ),
79
+ );
80
+ });
81
+
82
+ test<IndigoTestContext>('Collect Interest - Cannot collect from interest admin', async (context: IndigoTestContext) => {
83
+ const adminInterestCollectorUtxo = await findAdminInterestCollectors(
84
+ context.lucid,
85
+ context.systemParams.validatorHashes.interestCollectionHash,
86
+ fromSystemParamsAsset(
87
+ context.systemParams.interestCollectionParams.multisigUtxoNft,
88
+ ),
89
+ );
90
+
91
+ const [iAssetConfig] = context.assetConfigs;
92
+
93
+ context.lucid.selectWallet.fromSeed(context.users.user.seedPhrase);
94
+
95
+ await runAndAwaitTx(
96
+ context.lucid,
97
+ runOpenCdp(
98
+ context,
99
+ context.systemParams,
100
+ 'iUSD',
101
+ adaAssetClass,
102
+ 10_000_000n,
103
+ 500_000n,
104
+ ),
105
+ );
106
+
107
+ context.emulator.awaitSlot(6500);
108
+
109
+ await runFeedPriceToOracle(
110
+ context,
111
+ context.systemParams,
112
+ iAssetConfig,
113
+ adaAssetClass,
114
+ rationalFromInt(1n),
115
+ );
116
+
117
+ context.lucid.selectWallet.fromSeed(context.users.user.seedPhrase);
118
+
119
+ await expectScriptFailure(
120
+ 'Spent UTxO cannot have admin NFT',
121
+ runTestDepositCdpWithInterestVar(
122
+ context,
123
+ context.systemParams,
124
+ 'iUSD',
125
+ adaAssetClass,
126
+ adminInterestCollectorUtxo,
127
+ {
128
+ kind: 'CollectFromInterestAdmin',
129
+ },
130
+ ),
131
+ );
132
+ });
133
+
134
+ test<IndigoTestContext>('Collect Interest - Cannot collect from multiple interest collectors', async (context: IndigoTestContext) => {
135
+ const [iAssetConfig] = context.assetConfigs;
136
+
137
+ context.lucid.selectWallet.fromSeed(context.users.user.seedPhrase);
138
+
139
+ await runAndAwaitTx(
140
+ context.lucid,
141
+ runOpenCdp(
142
+ context,
143
+ context.systemParams,
144
+ 'iUSD',
145
+ adaAssetClass,
146
+ 10_000_000n,
147
+ 500_000n,
148
+ ),
149
+ );
150
+
151
+ context.emulator.awaitSlot(6500);
152
+
153
+ await runFeedPriceToOracle(
154
+ context,
155
+ context.systemParams,
156
+ iAssetConfig,
157
+ adaAssetClass,
158
+ rationalFromInt(1n),
159
+ );
160
+
161
+ const interestCollectors = await findAllInterestCollectors(
162
+ context.lucid,
163
+ context.systemParams.validatorHashes.interestCollectionHash,
164
+ );
165
+
166
+ const interestCollectorsUtxos = interestCollectors.filter(
167
+ (utxo) =>
168
+ assetClassValueOf(
169
+ utxo.assets,
170
+ fromSystemParamsAsset(
171
+ context.systemParams.interestCollectionParams.multisigUtxoNft,
172
+ ),
173
+ ) === 0n,
174
+ );
175
+ if (interestCollectorsUtxos.length < 2) {
176
+ throw new Error('Expected at least 2 interest collectors');
177
+ }
178
+
179
+ context.lucid.selectWallet.fromSeed(context.users.user.seedPhrase);
180
+
181
+ // This can fail in the CDP script or the interest collection script as the
182
+ // check of single interest collector is redundant.
183
+ await expectScriptFailure(
184
+ 'crashed',
185
+ runTestDepositCdpWithInterestVar(
186
+ context,
187
+ context.systemParams,
188
+ 'iUSD',
189
+ adaAssetClass,
190
+ interestCollectorsUtxos[0],
191
+ {
192
+ kind: 'CollectFromMultipleInterestCollectors',
193
+ utxo: interestCollectorsUtxos[1],
194
+ },
195
+ ),
196
+ );
197
+ });
198
+
199
+ test<IndigoTestContext>('Collect Interest - ADA and 3 assets', async (context: IndigoTestContext) => {
200
+ context.lucid.selectWallet.fromSeed(context.users.user.seedPhrase);
201
+
202
+ const [iAssetConfig] = context.assetConfigs;
203
+
204
+ await runAndAwaitTx(
205
+ context.lucid,
206
+ runOpenCdp(
207
+ context,
208
+ context.systemParams,
209
+ 'iUSD',
210
+ adaAssetClass,
211
+ 10_000_000n,
212
+ 500_000n,
213
+ ),
214
+ );
215
+
216
+ context.emulator.awaitSlot(6500);
217
+
218
+ await runFeedPriceToOracle(
219
+ context,
220
+ context.systemParams,
221
+ iAssetConfig,
222
+ adaAssetClass,
223
+ rationalFromInt(1n),
224
+ );
225
+
226
+ const interestCollectionUtxo = await findRandomNonAdminInterestCollector(
227
+ context.lucid,
228
+ context.systemParams.validatorHashes.interestCollectionHash,
229
+ fromSystemParamsAsset(
230
+ context.systemParams.interestCollectionParams.multisigUtxoNft,
231
+ ),
232
+ );
233
+
234
+ context.lucid.selectWallet.fromSeed(context.users.user.seedPhrase);
235
+
236
+ await expectScriptFailure(
237
+ 'E',
238
+ runTestDepositCdpWithInterestVar(
239
+ context,
240
+ context.systemParams,
241
+ 'iUSD',
242
+ adaAssetClass,
243
+ interestCollectionUtxo,
244
+ {
245
+ kind: 'CollectCustomValue',
246
+ value: addAssets(
247
+ mkLovelacesOf(1000000n),
248
+ mkAssetsOf(EXAMPLE_TOKEN_1, 1_000n),
249
+ mkAssetsOf(EXAMPLE_TOKEN_2, 1_000n),
250
+ mkAssetsOf(EXAMPLE_TOKEN_3, 1_000n),
251
+ ),
252
+ },
253
+ ),
254
+ );
255
+ });
256
+
257
+ // This test settles the biggest possible batch of CDPs
258
+ test<IndigoTestContext>('Batch collect - 13 CDPs', async (context: IndigoTestContext) => {
259
+ context.lucid.selectWallet.fromSeed(context.users.user.seedPhrase);
260
+
261
+ await createMultipleUtxosAtTreasury(
262
+ mkLovelacesOf(2n),
263
+ 10n,
264
+ context.systemParams,
265
+ context,
266
+ );
267
+
268
+ const [iAssetConfig] = context.assetConfigs;
269
+
270
+ const numberOfCdps = 13;
271
+
272
+ await repeat(numberOfCdps, async () => {
273
+ await runAndAwaitTx(
274
+ context.lucid,
275
+ runOpenCdp(
276
+ context,
277
+ context.systemParams,
278
+ iAssetConfig.iassetTokenNameAscii,
279
+ adaAssetClass,
280
+ 12_000_000n,
281
+ 6_000_000n,
282
+ ),
283
+ );
284
+ });
285
+
286
+ context.emulator.awaitSlot(
287
+ Number(
288
+ context.systemParams.interestCollectionParams
289
+ .interestSettlementCooldown,
290
+ ) / 1_000,
291
+ );
292
+
293
+ const orefs = await findAllNecessaryOrefs(
294
+ context.lucid,
295
+ context.systemParams,
296
+ 'iUSD',
297
+ adaAssetClass,
298
+ );
299
+
300
+ const priceOracleUtxo = await findPriceOracleFromCollateralAsset(
301
+ context.lucid,
302
+ orefs.collateralAsset,
303
+ );
304
+
305
+ const cdpsInfo = await findAllActiveCdps(
306
+ context.lucid,
307
+ context.systemParams,
308
+ 'iUSD',
309
+ stakeCredentialOf(context.users.user.address),
310
+ );
311
+
312
+ expect(
313
+ cdpsInfo.length === numberOfCdps,
314
+ `Expected ${numberOfCdps} cdps`,
315
+ ).toBeTruthy();
316
+
317
+ context.lucid.selectWallet.fromSeed(context.users.admin.seedPhrase);
318
+
319
+ await runAndAwaitTx(
320
+ context.lucid,
321
+ feedPriceOracleTx(
322
+ context.lucid,
323
+ priceOracleUtxo!,
324
+ rationalFromInt(1n),
325
+ iAssetConfig.collateralAssets[0].oracleParams!,
326
+ context.emulator.slot,
327
+ ),
328
+ );
329
+
330
+ await benchmarkAndAwaitTx(
331
+ 'Interest Collection - Batch Collect 13 CDPs',
332
+ await batchCollectInterest(
333
+ orefs.collateralAsset.utxo,
334
+ orefs.interestCollectorUtxo,
335
+ orefs.interestOracleUtxo,
336
+ cdpsInfo.map((cdp) => cdp.utxo),
337
+ context.systemParams,
338
+ context.lucid,
339
+ context.emulator.slot,
340
+ ),
341
+ context.lucid,
342
+ context.emulator,
343
+ );
344
+ });
345
+
346
+ test<IndigoTestContext>('Batch collect fails when no cooldown elapsed', async (context: IndigoTestContext) => {
347
+ context.lucid.selectWallet.fromSeed(context.users.user.seedPhrase);
348
+
349
+ await createMultipleUtxosAtTreasury(
350
+ mkLovelacesOf(2n),
351
+ 10n,
352
+ context.systemParams,
353
+ context,
354
+ );
355
+
356
+ const [iAssetConfig] = context.assetConfigs;
357
+
358
+ const numberOfCdps = 10;
359
+
360
+ await repeat(numberOfCdps, async () => {
361
+ await runAndAwaitTx(
362
+ context.lucid,
363
+ runOpenCdp(
364
+ context,
365
+ context.systemParams,
366
+ iAssetConfig.iassetTokenNameAscii,
367
+ adaAssetClass,
368
+ 12_000_000n,
369
+ 6_000_000n,
370
+ ),
371
+ );
372
+ });
373
+
374
+ // NOTE: Awaiting the cooldown period minus 39 seconds makes the transaction succeed,
375
+ // this is probably due to the awaitTx time.
376
+ context.emulator.awaitSlot(
377
+ Number(
378
+ context.systemParams.interestCollectionParams
379
+ .interestSettlementCooldown,
380
+ ) /
381
+ 1_000 -
382
+ 40,
383
+ );
384
+
385
+ const orefs = await findAllNecessaryOrefs(
386
+ context.lucid,
387
+ context.systemParams,
388
+ 'iUSD',
389
+ adaAssetClass,
390
+ );
391
+
392
+ const priceOracleUtxo = await findPriceOracleFromCollateralAsset(
393
+ context.lucid,
394
+ orefs.collateralAsset,
395
+ );
396
+
397
+ const cdpsInfo = await findAllActiveCdps(
398
+ context.lucid,
399
+ context.systemParams,
400
+ 'iUSD',
401
+ stakeCredentialOf(context.users.user.address),
402
+ );
403
+
404
+ expect(
405
+ cdpsInfo.length === numberOfCdps,
406
+ `Expected ${numberOfCdps} cdps`,
407
+ ).toBeTruthy();
408
+
409
+ context.lucid.selectWallet.fromSeed(context.users.admin.seedPhrase);
410
+
411
+ await runAndAwaitTx(
412
+ context.lucid,
413
+ feedPriceOracleTx(
414
+ context.lucid,
415
+ priceOracleUtxo!,
416
+ rationalFromInt(1n),
417
+ iAssetConfig.collateralAssets[0].oracleParams!,
418
+ context.emulator.slot,
419
+ ),
420
+ );
421
+
422
+ await expectScriptFailure(
423
+ 'It is too soon to settle interest',
424
+ batchCollectInterest(
425
+ orefs.collateralAsset.utxo,
426
+ orefs.interestCollectorUtxo,
427
+ orefs.interestOracleUtxo,
428
+ cdpsInfo.map((cdp) => cdp.utxo),
429
+ context.systemParams,
430
+ context.lucid,
431
+ context.emulator.slot,
432
+ ),
433
+ );
434
+ });
435
+
436
+ test<IndigoTestContext>('Distribute', async (context: IndigoTestContext) => {
437
+ context.lucid.selectWallet.fromSeed(context.users.user.seedPhrase);
438
+
439
+ await createUtxosAtInterestCollector(
440
+ 1,
441
+ addAssets(mkLovelacesOf(1000000n), mkAssetsOf(EXAMPLE_TOKEN_1, 1_000n)),
442
+ context.systemParams,
443
+ context,
444
+ );
445
+
446
+ context.lucid.selectWallet.fromSeed(context.users.admin.seedPhrase);
447
+
448
+ const interestDistributeUtxo = matchSingle(
449
+ (
450
+ await findAllInterestCollectors(
451
+ context.lucid,
452
+ context.systemParams.validatorHashes.interestCollectionHash,
453
+ )
454
+ ).filter((utxo) => assetClassValueOf(utxo.assets, EXAMPLE_TOKEN_1)),
455
+ (_) => new Error('Expected a single interest distribute UTXO'),
456
+ );
457
+
458
+ const interestAdminUtxo = await findAdminInterestCollector(
459
+ context.lucid,
460
+ context.systemParams.validatorHashes.interestCollectionHash,
461
+ fromSystemParamsAsset(
462
+ context.systemParams.interestCollectionParams.multisigUtxoNft,
463
+ ),
464
+ );
465
+
466
+ await benchmarkAndAwaitTx(
467
+ 'Interest Collection - Distribute',
468
+ await distributeInterest(
469
+ [interestDistributeUtxo],
470
+ interestAdminUtxo,
471
+ context.systemParams,
472
+ context.lucid,
473
+ ),
474
+ context.lucid,
475
+ context.emulator,
476
+ );
477
+ });
478
+
479
+ test<IndigoTestContext>('Distribute from multiple collectors - 58', async (context: IndigoTestContext) => {
480
+ context.lucid.selectWallet.fromSeed(context.users.user.seedPhrase);
481
+
482
+ const numberOfInterestCollectionUtxos = 58;
483
+
484
+ await createUtxosAtInterestCollector(
485
+ numberOfInterestCollectionUtxos,
486
+ addAssets(mkLovelacesOf(1000000n), mkAssetsOf(EXAMPLE_TOKEN_1, 1_000n)),
487
+ context.systemParams,
488
+ context,
489
+ );
490
+
491
+ context.lucid.selectWallet.fromSeed(context.users.admin.seedPhrase);
492
+
493
+ const interestDistributeUtxos = (
494
+ await findAllInterestCollectors(
495
+ context.lucid,
496
+ context.systemParams.validatorHashes.interestCollectionHash,
497
+ )
498
+ ).filter((utxo) => assetClassValueOf(utxo.assets, EXAMPLE_TOKEN_1));
499
+
500
+ const interestAdminUtxo = await findAdminInterestCollector(
501
+ context.lucid,
502
+ context.systemParams.validatorHashes.interestCollectionHash,
503
+ fromSystemParamsAsset(
504
+ context.systemParams.interestCollectionParams.multisigUtxoNft,
505
+ ),
506
+ );
507
+
508
+ await benchmarkAndAwaitTx(
509
+ 'Interest collection - Distribute from multiple collectors, 58',
510
+ await distributeInterest(
511
+ interestDistributeUtxos,
512
+ interestAdminUtxo,
513
+ context.systemParams,
514
+ context.lucid,
515
+ ),
516
+ context.lucid,
517
+ context.emulator,
518
+ );
519
+ });
520
+
521
+ test<IndigoTestContext>('Distribute - No admin signature', async (context: IndigoTestContext) => {
522
+ context.lucid.selectWallet.fromSeed(context.users.user.seedPhrase);
523
+
524
+ await createUtxosAtInterestCollector(
525
+ 1,
526
+ addAssets(mkLovelacesOf(1000000n), mkAssetsOf(EXAMPLE_TOKEN_1, 1_000n)),
527
+ context.systemParams,
528
+ context,
529
+ );
530
+
531
+ context.lucid.selectWallet.fromSeed(context.users.admin.seedPhrase);
532
+
533
+ const interestDistributeUtxo = matchSingle(
534
+ (
535
+ await findAllInterestCollectors(
536
+ context.lucid,
537
+ context.systemParams.validatorHashes.interestCollectionHash,
538
+ )
539
+ ).filter((utxo) => assetClassValueOf(utxo.assets, EXAMPLE_TOKEN_1)),
540
+ (_) => new Error('Expected a single interest distribute UTXO'),
541
+ );
542
+
543
+ const interestAdminUtxo = await findAdminInterestCollector(
544
+ context.lucid,
545
+ context.systemParams.validatorHashes.interestCollectionHash,
546
+ fromSystemParamsAsset(
547
+ context.systemParams.interestCollectionParams.multisigUtxoNft,
548
+ ),
549
+ );
550
+
551
+ await expectScriptFailure(
552
+ 'Admin multisig must be satisfied',
553
+ testDistributeInterest(
554
+ interestDistributeUtxo,
555
+ interestAdminUtxo,
556
+ context.users.user.address,
557
+ undefined,
558
+ context.systemParams,
559
+ context.lucid,
560
+ { kind: 'DistributeInterestNoAdmin' },
561
+ ),
562
+ );
563
+ });
564
+
565
+ test<IndigoTestContext>('Update Permissions', async (context: IndigoTestContext) => {
566
+ const interestAdminUtxo = await findAdminInterestCollector(
567
+ context.lucid,
568
+ context.systemParams.validatorHashes.interestCollectionHash,
569
+ fromSystemParamsAsset(
570
+ context.systemParams.interestCollectionParams.multisigUtxoNft,
571
+ ),
572
+ );
573
+
574
+ const govUtxo = await findGov(
575
+ context.lucid,
576
+ context.systemParams.validatorHashes.govHash,
577
+ fromSystemParamsAsset(
578
+ context.systemParams.interestCollectionParams.govAuthTk,
579
+ ),
580
+ );
581
+
582
+ const newAdminPermissions = {
583
+ Signature: {
584
+ keyHash: fromHex(paymentCredentialOf(context.users.user.address).hash),
585
+ },
586
+ };
587
+
588
+ await benchmarkAndAwaitTx(
589
+ 'Interest Collection - Update Permissions',
590
+ await updatePermissions(
591
+ interestAdminUtxo,
592
+ govUtxo.utxo,
593
+ newAdminPermissions,
594
+ [
595
+ ...signersAllOf(govUtxo.datum.protocolParams.foundationMultisig),
596
+ ...signersAllOf(newAdminPermissions),
597
+ ],
598
+ context.systemParams,
599
+ context.lucid,
600
+ ),
601
+ context.lucid,
602
+ context.emulator,
603
+ [context.users.user.seedPhrase],
604
+ );
605
+ });
606
+
607
+ test<IndigoTestContext>('Update Permissions - all of multiple signers', async (context: IndigoTestContext) => {
608
+ const interestAdminUtxo = await findAdminInterestCollector(
609
+ context.lucid,
610
+ context.systemParams.validatorHashes.interestCollectionHash,
611
+ fromSystemParamsAsset(
612
+ context.systemParams.interestCollectionParams.multisigUtxoNft,
613
+ ),
614
+ );
615
+
616
+ const govUtxo = await findGov(
617
+ context.lucid,
618
+ context.systemParams.validatorHashes.govHash,
619
+ fromSystemParamsAsset(
620
+ context.systemParams.interestCollectionParams.govAuthTk,
621
+ ),
622
+ );
623
+
624
+ const newAdminPermissions = {
625
+ AtLeast: {
626
+ required: 1n,
627
+ authSignatories: [
628
+ toDataMultisig({
629
+ Signature: {
630
+ keyHash: fromHex(
631
+ paymentCredentialOf(context.users.user.address).hash,
632
+ ),
633
+ },
634
+ }),
635
+ toDataMultisig({
636
+ Signature: {
637
+ keyHash: fromHex(
638
+ paymentCredentialOf(context.users.user2.address).hash,
639
+ ),
640
+ },
641
+ }),
642
+ ],
643
+ },
644
+ };
645
+
646
+ await benchmarkAndAwaitTx(
647
+ 'Interest Collection - Update Permissions - all of multiple signers',
648
+ await updatePermissions(
649
+ interestAdminUtxo,
650
+ govUtxo.utxo,
651
+ newAdminPermissions,
652
+ [
653
+ ...signersAllOf(govUtxo.datum.protocolParams.foundationMultisig),
654
+ ...signersAllOf(newAdminPermissions),
655
+ ],
656
+ context.systemParams,
657
+ context.lucid,
658
+ ),
659
+ context.lucid,
660
+ context.emulator,
661
+ [context.users.user.seedPhrase, context.users.user2.seedPhrase],
662
+ );
663
+ });
664
+
665
+ test<IndigoTestContext>('Update Permissions - some of multiple signers', async (context: IndigoTestContext) => {
666
+ const interestAdminUtxo = await findAdminInterestCollector(
667
+ context.lucid,
668
+ context.systemParams.validatorHashes.interestCollectionHash,
669
+ fromSystemParamsAsset(
670
+ context.systemParams.interestCollectionParams.multisigUtxoNft,
671
+ ),
672
+ );
673
+
674
+ const govUtxo = await findGov(
675
+ context.lucid,
676
+ context.systemParams.validatorHashes.govHash,
677
+ fromSystemParamsAsset(
678
+ context.systemParams.interestCollectionParams.govAuthTk,
679
+ ),
680
+ );
681
+
682
+ const newAdminPermissions = {
683
+ AtLeast: {
684
+ required: 2n,
685
+ authSignatories: [
686
+ toDataMultisig({
687
+ Signature: {
688
+ keyHash: fromHex(
689
+ paymentCredentialOf(context.users.admin.address).hash,
690
+ ),
691
+ },
692
+ }),
693
+ toDataMultisig({
694
+ Signature: {
695
+ keyHash: fromHex(
696
+ paymentCredentialOf(context.users.user.address).hash,
697
+ ),
698
+ },
699
+ }),
700
+ toDataMultisig({
701
+ Signature: {
702
+ keyHash: fromHex(
703
+ paymentCredentialOf(context.users.user2.address).hash,
704
+ ),
705
+ },
706
+ }),
707
+ ],
708
+ },
709
+ };
710
+
711
+ await runAndAwaitTx(
712
+ context.lucid,
713
+ updatePermissions(
714
+ interestAdminUtxo,
715
+ govUtxo.utxo,
716
+ newAdminPermissions,
717
+ [
718
+ ...signersAllOf(govUtxo.datum.protocolParams.foundationMultisig),
719
+ ...[paymentCredentialOf(context.users.user.address).hash],
720
+ ],
721
+ context.systemParams,
722
+ context.lucid,
723
+ ),
724
+ [context.users.user.seedPhrase],
725
+ );
726
+ });
727
+
728
+ test<IndigoTestContext>('Update Permissions - nested multisig', async (context: IndigoTestContext) => {
729
+ const interestAdminUtxo = await findAdminInterestCollector(
730
+ context.lucid,
731
+ context.systemParams.validatorHashes.interestCollectionHash,
732
+ fromSystemParamsAsset(
733
+ context.systemParams.interestCollectionParams.multisigUtxoNft,
734
+ ),
735
+ );
736
+
737
+ const govUtxo = await findGov(
738
+ context.lucid,
739
+ context.systemParams.validatorHashes.govHash,
740
+ fromSystemParamsAsset(
741
+ context.systemParams.interestCollectionParams.govAuthTk,
742
+ ),
743
+ );
744
+
745
+ const newAdminPermissions = {
746
+ AtLeast: {
747
+ required: 2n,
748
+ authSignatories: [
749
+ toDataMultisig({
750
+ Signature: {
751
+ keyHash: fromHex(
752
+ paymentCredentialOf(context.users.admin.address).hash,
753
+ ),
754
+ },
755
+ }),
756
+ toDataMultisig({
757
+ AtLeast: {
758
+ required: 1n,
759
+ authSignatories: [
760
+ toDataMultisig({
761
+ Signature: {
762
+ keyHash: fromHex(
763
+ paymentCredentialOf(context.users.user.address).hash,
764
+ ),
765
+ },
766
+ }),
767
+ toDataMultisig({
768
+ Signature: {
769
+ keyHash: fromHex(
770
+ paymentCredentialOf(context.users.user2.address).hash,
771
+ ),
772
+ },
773
+ }),
774
+ ],
775
+ },
776
+ }),
777
+ ],
778
+ },
779
+ };
780
+
781
+ await runAndAwaitTx(
782
+ context.lucid,
783
+ updatePermissions(
784
+ interestAdminUtxo,
785
+ govUtxo.utxo,
786
+ newAdminPermissions,
787
+ [
788
+ ...signersAllOf(govUtxo.datum.protocolParams.foundationMultisig),
789
+ ...[paymentCredentialOf(context.users.user.address).hash],
790
+ ],
791
+ context.systemParams,
792
+ context.lucid,
793
+ ),
794
+ [context.users.user.seedPhrase],
795
+ );
796
+ });
797
+
798
+ test<IndigoTestContext>('Update Permissions - Fail when new admin is not signed', async (context: IndigoTestContext) => {
799
+ const interestAdminUtxo = await findAdminInterestCollector(
800
+ context.lucid,
801
+ context.systemParams.validatorHashes.interestCollectionHash,
802
+ fromSystemParamsAsset(
803
+ context.systemParams.interestCollectionParams.multisigUtxoNft,
804
+ ),
805
+ );
806
+
807
+ const govUtxo = await findGov(
808
+ context.lucid,
809
+ context.systemParams.validatorHashes.govHash,
810
+ fromSystemParamsAsset(
811
+ context.systemParams.interestCollectionParams.govAuthTk,
812
+ ),
813
+ );
814
+
815
+ const newAdminPermissions = {
816
+ Signature: {
817
+ keyHash: fromHex(paymentCredentialOf(context.users.user.address).hash),
818
+ },
819
+ };
820
+
821
+ await expectScriptFailure(
822
+ 'New admin multisig must be satisfied',
823
+ updatePermissions(
824
+ interestAdminUtxo,
825
+ govUtxo.utxo,
826
+ newAdminPermissions,
827
+ signersAllOf(govUtxo.datum.protocolParams.foundationMultisig),
828
+ context.systemParams,
829
+ context.lucid,
830
+ ),
831
+ );
832
+ });
833
+
834
+ test<IndigoTestContext>('Update Permissions - Fail when not enough signers of new admin', async (context: IndigoTestContext) => {
835
+ const interestAdminUtxo = await findAdminInterestCollector(
836
+ context.lucid,
837
+ context.systemParams.validatorHashes.interestCollectionHash,
838
+ fromSystemParamsAsset(
839
+ context.systemParams.interestCollectionParams.multisigUtxoNft,
840
+ ),
841
+ );
842
+
843
+ const govUtxo = await findGov(
844
+ context.lucid,
845
+ context.systemParams.validatorHashes.govHash,
846
+ fromSystemParamsAsset(
847
+ context.systemParams.interestCollectionParams.govAuthTk,
848
+ ),
849
+ );
850
+
851
+ const newAdminPermissions = {
852
+ AtLeast: {
853
+ required: 2n,
854
+ authSignatories: [
855
+ toDataMultisig({
856
+ Signature: {
857
+ keyHash: fromHex(
858
+ paymentCredentialOf(context.users.admin.address).hash,
859
+ ),
860
+ },
861
+ }),
862
+ toDataMultisig({
863
+ Signature: {
864
+ keyHash: fromHex(
865
+ paymentCredentialOf(context.users.user.address).hash,
866
+ ),
867
+ },
868
+ }),
869
+ toDataMultisig({
870
+ Signature: {
871
+ keyHash: fromHex(
872
+ paymentCredentialOf(context.users.user2.address).hash,
873
+ ),
874
+ },
875
+ }),
876
+ ],
877
+ },
878
+ };
879
+
880
+ await expectScriptFailure(
881
+ 'New admin multisig must be satisfied',
882
+ updatePermissions(
883
+ interestAdminUtxo,
884
+ govUtxo.utxo,
885
+ newAdminPermissions,
886
+ signersAllOf(govUtxo.datum.protocolParams.foundationMultisig),
887
+ context.systemParams,
888
+ context.lucid,
889
+ ),
890
+ );
891
+ });
892
+ });