@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,610 @@
1
+ import {
2
+ TxBuilder,
3
+ Credential,
4
+ stakeCredentialOf,
5
+ toHex,
6
+ UTxO,
7
+ toText,
8
+ fromText,
9
+ } from '@lucid-evolution/lucid';
10
+ import {
11
+ addrDetails,
12
+ burnCdp,
13
+ closeCdp,
14
+ depositCdp,
15
+ freezeCdp,
16
+ fromSystemParamsAsset,
17
+ liquidateCdp,
18
+ mintCdp,
19
+ openCdp,
20
+ redeemCdp,
21
+ SystemParams,
22
+ withdrawCdp,
23
+ } from '../../src';
24
+ import {
25
+ findAllActiveCdps,
26
+ findAllNecessaryOrefs,
27
+ findCdp,
28
+ findFrozenCDPs,
29
+ findPrice,
30
+ findPriceOracleFromCollateralAsset,
31
+ } from './cdp-queries';
32
+ import {
33
+ LucidContext,
34
+ repeat,
35
+ runAndAwaitTx,
36
+ runAndAwaitTxBuilder,
37
+ } from '../test-helpers';
38
+ import { AssetInfo } from '../endpoints/initialize';
39
+ import { expect } from 'vitest';
40
+ import { feedPriceOracleTx } from '../../src/contracts/price-oracle/transactions';
41
+ import {
42
+ AssetClass,
43
+ assetClassToUnit,
44
+ getInlineDatumOrThrow,
45
+ matchSingle,
46
+ } from '@3rd-eye-labs/cardano-offchain-common';
47
+ import { parseCdpDatumOrThrow } from '../../src/contracts/cdp/types-new';
48
+ import { match, P } from 'ts-pattern';
49
+ import { findPriceOracle } from '../price-oracle/price-oracle-queries';
50
+ import { findCollateralAsset } from '../queries/iasset-queries';
51
+ import { runFeedPriceToOracle } from '../price-oracle/actions';
52
+ import { rationalFromInt, rationalMul } from '../../src/types/rational';
53
+
54
+ // Selects users wallet and opens a CDP with the given initial collateral and mint amount
55
+ export async function runOpenCdp(
56
+ context: LucidContext,
57
+ sysParams: SystemParams,
58
+ asset: string,
59
+ collateralAsset: AssetClass,
60
+ initialCollateral: bigint,
61
+ initialMint: bigint,
62
+ pythMessage?: string,
63
+ ): Promise<TxBuilder> {
64
+ const orefs = await findAllNecessaryOrefs(
65
+ context.lucid,
66
+ sysParams,
67
+ asset,
68
+ collateralAsset,
69
+ );
70
+
71
+ const priceOracleUtxo = await findPriceOracleFromCollateralAsset(
72
+ context.lucid,
73
+ orefs.collateralAsset,
74
+ );
75
+
76
+ const pythStateOref = pythMessage
77
+ ? await context.lucid.utxoByUnit(
78
+ assetClassToUnit(
79
+ fromSystemParamsAsset(sysParams.pythConfig.pythStateAssetClass),
80
+ ),
81
+ )
82
+ : undefined;
83
+
84
+ return openCdp(
85
+ initialCollateral,
86
+ initialMint,
87
+ sysParams,
88
+ orefs.cdpCreatorUtxo,
89
+ orefs.iasset.utxo,
90
+ orefs.collateralAsset.utxo,
91
+ priceOracleUtxo,
92
+ orefs.interestOracleUtxo,
93
+ orefs.treasuryUtxo,
94
+ context.lucid,
95
+ context.emulator.slot,
96
+ pythMessage,
97
+ pythStateOref,
98
+ );
99
+ }
100
+
101
+ export async function runDepositCdp(
102
+ context: LucidContext,
103
+ sysParams: SystemParams,
104
+ asset: string,
105
+ collateralAsset: AssetClass,
106
+ amount: bigint = 1_000_000n,
107
+ ): Promise<TxBuilder> {
108
+ const [pkh, skh] = await addrDetails(context.lucid);
109
+
110
+ const cdp = await findCdp(
111
+ context.lucid,
112
+ sysParams.validatorHashes.cdpHash,
113
+ fromSystemParamsAsset(sysParams.cdpParams.cdpAuthToken),
114
+ pkh.hash,
115
+ skh,
116
+ );
117
+ const orefs = await findAllNecessaryOrefs(
118
+ context.lucid,
119
+ sysParams,
120
+ asset,
121
+ collateralAsset,
122
+ );
123
+
124
+ return await depositCdp(
125
+ amount,
126
+ cdp.utxo,
127
+ orefs.iasset.utxo,
128
+ orefs.collateralAsset.utxo,
129
+ orefs.interestOracleUtxo,
130
+ orefs.treasuryUtxo,
131
+ orefs.interestCollectorUtxo,
132
+ sysParams,
133
+ context.lucid,
134
+ context.emulator.slot,
135
+ );
136
+ }
137
+
138
+ export async function runWithdrawCdp(
139
+ context: LucidContext,
140
+ sysParams: SystemParams,
141
+ asset: string,
142
+ collateralAsset: AssetClass,
143
+ amount: bigint = 1_000_000n,
144
+ pythMessage?: string,
145
+ ): Promise<TxBuilder> {
146
+ const [pkh, skh] = await addrDetails(context.lucid);
147
+
148
+ const cdp = await findCdp(
149
+ context.lucid,
150
+ sysParams.validatorHashes.cdpHash,
151
+ fromSystemParamsAsset(sysParams.cdpParams.cdpAuthToken),
152
+ pkh.hash,
153
+ skh,
154
+ );
155
+ const orefs = await findAllNecessaryOrefs(
156
+ context.lucid,
157
+ sysParams,
158
+ asset,
159
+ collateralAsset,
160
+ );
161
+
162
+ const priceOracleUtxo = await match(orefs.collateralAsset.datum.priceInfo)
163
+ .with({ OracleNft: P.select() }, (oracleNft) =>
164
+ findPriceOracle(context.lucid, oracleNft),
165
+ )
166
+ .otherwise(() => undefined);
167
+
168
+ const pythStateOref = pythMessage
169
+ ? await context.lucid.utxoByUnit(
170
+ sysParams.pythConfig.pythStateAssetClass[0].unCurrencySymbol +
171
+ fromText('Pyth State'),
172
+ )
173
+ : undefined;
174
+
175
+ return await withdrawCdp(
176
+ amount,
177
+ cdp.utxo,
178
+ orefs.iasset.utxo,
179
+ orefs.collateralAsset.utxo,
180
+ priceOracleUtxo,
181
+ orefs.interestOracleUtxo,
182
+ orefs.treasuryUtxo,
183
+ orefs.interestCollectorUtxo,
184
+ sysParams,
185
+ context.lucid,
186
+ context.emulator.slot,
187
+ pythMessage,
188
+ pythStateOref,
189
+ );
190
+ }
191
+
192
+ export async function runMintCdp(
193
+ context: LucidContext,
194
+ sysParams: SystemParams,
195
+ asset: string,
196
+ collateralAsset: AssetClass,
197
+ amount: bigint = 100_000n,
198
+ pythMessage?: string,
199
+ ): Promise<TxBuilder> {
200
+ const [pkh, skh] = await addrDetails(context.lucid);
201
+
202
+ const cdp = await findCdp(
203
+ context.lucid,
204
+ sysParams.validatorHashes.cdpHash,
205
+ fromSystemParamsAsset(sysParams.cdpParams.cdpAuthToken),
206
+ pkh.hash,
207
+ skh,
208
+ );
209
+ const orefs = await findAllNecessaryOrefs(
210
+ context.lucid,
211
+ sysParams,
212
+ asset,
213
+ collateralAsset,
214
+ );
215
+
216
+ const priceOracleUtxo = await match(orefs.collateralAsset.datum.priceInfo)
217
+ .with({ OracleNft: P.select() }, (oracleNft) =>
218
+ findPriceOracle(context.lucid, oracleNft),
219
+ )
220
+ .otherwise(() => undefined);
221
+
222
+ const pythStateOref = pythMessage
223
+ ? await context.lucid.utxoByUnit(
224
+ sysParams.pythConfig.pythStateAssetClass[0].unCurrencySymbol +
225
+ fromText('Pyth State'),
226
+ )
227
+ : undefined;
228
+
229
+ return await mintCdp(
230
+ amount,
231
+ cdp.utxo,
232
+ orefs.iasset.utxo,
233
+ orefs.collateralAsset.utxo,
234
+ priceOracleUtxo,
235
+ orefs.interestOracleUtxo,
236
+ orefs.treasuryUtxo,
237
+ orefs.interestCollectorUtxo,
238
+ sysParams,
239
+ context.lucid,
240
+ context.emulator.slot,
241
+ pythMessage,
242
+ pythStateOref,
243
+ );
244
+ }
245
+
246
+ export async function runBurnCdp(
247
+ context: LucidContext,
248
+ sysParams: SystemParams,
249
+ asset: string,
250
+ collateralAsset: AssetClass,
251
+ amount: bigint = 100_000n,
252
+ ): Promise<TxBuilder> {
253
+ const [pkh, skh] = await addrDetails(context.lucid);
254
+
255
+ const cdp = await findCdp(
256
+ context.lucid,
257
+ sysParams.validatorHashes.cdpHash,
258
+ fromSystemParamsAsset(sysParams.cdpParams.cdpAuthToken),
259
+ pkh.hash,
260
+ skh,
261
+ );
262
+ const orefs = await findAllNecessaryOrefs(
263
+ context.lucid,
264
+ sysParams,
265
+ asset,
266
+ collateralAsset,
267
+ );
268
+
269
+ return await burnCdp(
270
+ amount,
271
+ cdp.utxo,
272
+ orefs.iasset.utxo,
273
+ orefs.collateralAsset.utxo,
274
+ orefs.interestOracleUtxo,
275
+ orefs.treasuryUtxo,
276
+ orefs.interestCollectorUtxo,
277
+ sysParams,
278
+ context.lucid,
279
+ context.emulator.slot,
280
+ );
281
+ }
282
+
283
+ export async function runCloseCdp(
284
+ context: LucidContext,
285
+ sysParams: SystemParams,
286
+ asset: string,
287
+ collateralAsset: AssetClass,
288
+ ): Promise<TxBuilder> {
289
+ const [pkh, skh] = await addrDetails(context.lucid);
290
+
291
+ const cdp = await findCdp(
292
+ context.lucid,
293
+ sysParams.validatorHashes.cdpHash,
294
+ fromSystemParamsAsset(sysParams.cdpParams.cdpAuthToken),
295
+ pkh.hash,
296
+ skh,
297
+ );
298
+ const orefs = await findAllNecessaryOrefs(
299
+ context.lucid,
300
+ sysParams,
301
+ asset,
302
+ collateralAsset,
303
+ );
304
+
305
+ return await closeCdp(
306
+ cdp.utxo,
307
+ orefs.collateralAsset.utxo,
308
+ orefs.interestOracleUtxo,
309
+ orefs.interestCollectorUtxo,
310
+ sysParams,
311
+ context.lucid,
312
+ context.emulator.slot,
313
+ );
314
+ }
315
+
316
+ export async function runRedeemCdp(
317
+ context: LucidContext,
318
+ sysParams: SystemParams,
319
+ iusdAssetInfo: AssetInfo,
320
+ collateralAsset: AssetClass,
321
+ pkh: string,
322
+ skh: Credential | undefined,
323
+ ): Promise<TxBuilder> {
324
+ const cdp = await findCdp(
325
+ context.lucid,
326
+ sysParams.validatorHashes.cdpHash,
327
+ fromSystemParamsAsset(sysParams.cdpParams.cdpAuthToken),
328
+ pkh,
329
+ skh,
330
+ );
331
+
332
+ const orefs = await findAllNecessaryOrefs(
333
+ context.lucid,
334
+ sysParams,
335
+ iusdAssetInfo.iassetTokenNameAscii,
336
+ collateralAsset,
337
+ );
338
+
339
+ const priceOracleUtxo = await match(orefs.collateralAsset.datum.priceInfo)
340
+ .with({ OracleNft: P.select() }, (oracleNft) =>
341
+ findPriceOracle(context.lucid, oracleNft),
342
+ )
343
+ .otherwise(() => undefined);
344
+
345
+ return await redeemCdp(
346
+ cdp.datum.mintedAmt,
347
+ cdp.utxo,
348
+ orefs.iasset.utxo,
349
+ orefs.collateralAsset.utxo,
350
+ priceOracleUtxo,
351
+ orefs.interestOracleUtxo,
352
+ orefs.interestCollectorUtxo,
353
+ orefs.treasuryUtxo,
354
+ orefs.govUtxo,
355
+ sysParams,
356
+ context.lucid,
357
+ context.emulator.slot,
358
+ );
359
+ }
360
+
361
+ export async function runFreezeCdp(
362
+ context: LucidContext,
363
+ sysParams: SystemParams,
364
+ asset: string,
365
+ collateralAsset: AssetClass,
366
+ pkh: string,
367
+ skh: Credential | undefined,
368
+ pythMessage?: string,
369
+ ): Promise<TxBuilder> {
370
+ const cdp = await findCdp(
371
+ context.lucid,
372
+ sysParams.validatorHashes.cdpHash,
373
+ fromSystemParamsAsset(sysParams.cdpParams.cdpAuthToken),
374
+ pkh,
375
+ skh,
376
+ );
377
+
378
+ const orefs = await findAllNecessaryOrefs(
379
+ context.lucid,
380
+ sysParams,
381
+ asset,
382
+ collateralAsset,
383
+ );
384
+
385
+ const priceOracleUtxo = await match(orefs.collateralAsset.datum.priceInfo)
386
+ .with({ OracleNft: P.select() }, (oracleNft) =>
387
+ findPriceOracle(context.lucid, oracleNft),
388
+ )
389
+ .otherwise(() => undefined);
390
+
391
+ const pythStateOref = pythMessage
392
+ ? await context.lucid.utxoByUnit(
393
+ sysParams.pythConfig.pythStateAssetClass[0].unCurrencySymbol +
394
+ fromText('Pyth State'),
395
+ )
396
+ : undefined;
397
+ return freezeCdp(
398
+ cdp.utxo,
399
+ orefs.iasset.utxo,
400
+ orefs.collateralAsset.utxo,
401
+ priceOracleUtxo,
402
+ orefs.interestOracleUtxo,
403
+ sysParams,
404
+ context.lucid,
405
+ context.emulator.slot,
406
+ pythMessage,
407
+ pythStateOref,
408
+ );
409
+ }
410
+
411
+ export async function runCreateAndFreezeCdps(
412
+ context: LucidContext,
413
+ sysParams: SystemParams,
414
+ assetInfo: AssetInfo,
415
+ numberOfCdps: number,
416
+ iasset: string,
417
+ collateralAsset: AssetClass,
418
+ ): Promise<void> {
419
+ const collateralAssetOutput = await findCollateralAsset(
420
+ context.lucid,
421
+ sysParams,
422
+ fromSystemParamsAsset(sysParams.cdpParams.collateralAssetAuthToken),
423
+ iasset,
424
+ collateralAsset,
425
+ );
426
+
427
+ let priceOracleUtxo = await findPriceOracleFromCollateralAsset(
428
+ context.lucid,
429
+ collateralAssetOutput,
430
+ );
431
+
432
+ await repeat(numberOfCdps, async () => {
433
+ const orefs = await findAllNecessaryOrefs(
434
+ context.lucid,
435
+ sysParams,
436
+ iasset,
437
+ collateralAsset,
438
+ );
439
+
440
+ await runAndAwaitTx(
441
+ context.lucid,
442
+ openCdp(
443
+ 12_000_000n,
444
+ 6_000_000n,
445
+ sysParams,
446
+ orefs.cdpCreatorUtxo,
447
+ orefs.iasset.utxo,
448
+ orefs.collateralAsset.utxo,
449
+ priceOracleUtxo,
450
+ orefs.interestOracleUtxo,
451
+ orefs.treasuryUtxo,
452
+ context.lucid,
453
+ context.emulator.slot,
454
+ ),
455
+ );
456
+ });
457
+
458
+ await runAndAwaitTx(
459
+ context.lucid,
460
+ feedPriceOracleTx(
461
+ context.lucid,
462
+ priceOracleUtxo!,
463
+ { numerator: 18n, denominator: 10n }, // 1.8
464
+ assetInfo.collateralAssets[0].oracleParams!,
465
+ context.emulator.slot,
466
+ ),
467
+ );
468
+
469
+ priceOracleUtxo = await findPriceOracleFromCollateralAsset(
470
+ context.lucid,
471
+ collateralAssetOutput,
472
+ );
473
+
474
+ {
475
+ const activeCdps = await findAllActiveCdps(
476
+ context.lucid,
477
+ sysParams,
478
+ iasset,
479
+ stakeCredentialOf(context.users.admin.address),
480
+ );
481
+
482
+ expect(
483
+ activeCdps.length === numberOfCdps,
484
+ `Expected ${numberOfCdps} cdps`,
485
+ ).toBeTruthy();
486
+
487
+ for (const cdp of activeCdps) {
488
+ const orefs = await findAllNecessaryOrefs(
489
+ context.lucid,
490
+ sysParams,
491
+ iasset,
492
+ collateralAsset,
493
+ );
494
+
495
+ await runAndAwaitTx(
496
+ context.lucid,
497
+ freezeCdp(
498
+ cdp.utxo,
499
+ orefs.iasset.utxo,
500
+ orefs.collateralAsset.utxo,
501
+ priceOracleUtxo,
502
+ orefs.interestOracleUtxo,
503
+ sysParams,
504
+ context.lucid,
505
+ context.emulator.slot,
506
+ ),
507
+ );
508
+ }
509
+ }
510
+ }
511
+
512
+ export async function runLiquidateCdp(
513
+ context: LucidContext,
514
+ sysParams: SystemParams,
515
+ frozenCdpUtxo: UTxO,
516
+ ): Promise<TxBuilder> {
517
+ const cdpDatum = parseCdpDatumOrThrow(getInlineDatumOrThrow(frozenCdpUtxo));
518
+ const orefs = await findAllNecessaryOrefs(
519
+ context.lucid,
520
+ sysParams,
521
+ toText(toHex(cdpDatum.iasset)),
522
+ cdpDatum.collateralAsset,
523
+ );
524
+ return liquidateCdp(
525
+ frozenCdpUtxo,
526
+ orefs.stabilityPoolUtxo,
527
+ orefs.interestCollectorUtxo,
528
+ orefs.treasuryUtxo,
529
+ sysParams,
530
+ context.lucid,
531
+ );
532
+ }
533
+
534
+ /**
535
+ * Expecting price double will make CDP liquidatable.
536
+ */
537
+ export async function executeLiquidation(
538
+ context: LucidContext,
539
+ sysParams: SystemParams,
540
+ liquidatedDebt: bigint,
541
+ liquidatedCollateral: bigint,
542
+ collateralAsset: AssetClass,
543
+ assetInfo: AssetInfo,
544
+ liquidateWrapper: (liquidateTx: TxBuilder) => Promise<void> = async (tx) => {
545
+ await runAndAwaitTxBuilder(context.lucid, tx);
546
+ },
547
+ ) {
548
+ const price = await findPrice(
549
+ context.lucid,
550
+ sysParams,
551
+ assetInfo.iassetTokenNameAscii,
552
+ collateralAsset,
553
+ );
554
+
555
+ const [pkh, skh] = await addrDetails(context.lucid);
556
+
557
+ await runAndAwaitTx(
558
+ context.lucid,
559
+ runOpenCdp(
560
+ context,
561
+ sysParams,
562
+ assetInfo.iassetTokenNameAscii,
563
+ collateralAsset,
564
+ liquidatedCollateral,
565
+ liquidatedDebt,
566
+ ),
567
+ );
568
+
569
+ await runFeedPriceToOracle(
570
+ context,
571
+ sysParams,
572
+ assetInfo,
573
+ collateralAsset,
574
+ rationalMul(price, rationalFromInt(2n)),
575
+ );
576
+
577
+ await runAndAwaitTx(
578
+ context.lucid,
579
+ runFreezeCdp(
580
+ context,
581
+ sysParams,
582
+ assetInfo.iassetTokenNameAscii,
583
+ collateralAsset,
584
+ pkh.hash,
585
+ skh,
586
+ ),
587
+ );
588
+
589
+ const frozenCdp = matchSingle(
590
+ await findFrozenCDPs(
591
+ context.lucid,
592
+ sysParams.validatorHashes.cdpHash,
593
+ fromSystemParamsAsset(sysParams.cdpParams.cdpAuthToken),
594
+ assetInfo.iassetTokenNameAscii,
595
+ ),
596
+ (_) => new Error('Expected only single frozen CDP'),
597
+ );
598
+
599
+ await liquidateWrapper(
600
+ await runLiquidateCdp(context, sysParams, frozenCdp.utxo),
601
+ );
602
+
603
+ await runFeedPriceToOracle(
604
+ context,
605
+ sysParams,
606
+ assetInfo,
607
+ collateralAsset,
608
+ price,
609
+ );
610
+ }
@@ -0,0 +1,55 @@
1
+ import { match, P } from 'ts-pattern';
2
+ import { CDPContent } from '../../src/contracts/cdp/types-new';
3
+ import { calculateAccruedInterest } from '../../src/contracts/interest-oracle/helpers';
4
+ import { LucidContext } from '../test-helpers';
5
+ import { slotToUnixTime, toHex, toText } from '@lucid-evolution/lucid';
6
+ import { findCollateralAsset } from '../queries/iasset-queries';
7
+ import {
8
+ fromSystemParamsAsset,
9
+ getInlineDatumOrThrow,
10
+ SystemParams,
11
+ } from '../../src';
12
+ import { findInterestOracle } from '../queries/interest-oracle-queries';
13
+ import { parseInterestOracleDatum } from '../../src/contracts/interest-oracle/types-new';
14
+
15
+ export async function calculateCdpInterest(
16
+ cdp: CDPContent,
17
+ context: LucidContext,
18
+ sysParams: SystemParams,
19
+ ): Promise<bigint> {
20
+ const currentTime = BigInt(
21
+ slotToUnixTime(context.lucid.config().network!, context.emulator.slot),
22
+ );
23
+
24
+ const collateralAsset = await findCollateralAsset(
25
+ context.lucid,
26
+ sysParams,
27
+ fromSystemParamsAsset(sysParams.cdpParams.collateralAssetAuthToken),
28
+ toText(toHex(cdp.iasset)),
29
+ cdp.collateralAsset,
30
+ );
31
+
32
+ const interestOracleUtxo = await findInterestOracle(
33
+ context.lucid,
34
+ collateralAsset.datum.interestOracleNft,
35
+ );
36
+
37
+ const interestOracleDatum = parseInterestOracleDatum(
38
+ getInlineDatumOrThrow(interestOracleUtxo),
39
+ );
40
+
41
+ return match(cdp.cdpFees)
42
+ .with({ FrozenCDPAccumulatedFees: P.select() }, (fees) => {
43
+ return fees.iassetInterest;
44
+ })
45
+ .with({ ActiveCDPInterestTracking: P.select() }, (interest) => {
46
+ return calculateAccruedInterest(
47
+ currentTime,
48
+ interest.unitaryInterestSnapshot,
49
+ cdp.mintedAmt,
50
+ interest.lastSettled,
51
+ interestOracleDatum,
52
+ );
53
+ })
54
+ .exhaustive();
55
+ }