@indigo-labs/indigo-sdk 0.2.1 → 0.2.4

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.
package/tests/lrp.test.ts CHANGED
@@ -1,20 +1,17 @@
1
- import { assert, describe, expect, it } from 'vitest';
1
+ import { assert, beforeEach, describe, expect, test } from 'vitest';
2
2
  import {
3
+ addAssets,
4
+ Credential,
3
5
  Emulator,
6
+ EmulatorAccount,
4
7
  fromText,
5
8
  generateEmulatorAccount,
6
9
  Lucid,
7
- LucidEvolution,
8
- Network,
9
10
  paymentCredentialOf,
10
11
  toText,
11
12
  UTxO,
12
- validatorToScriptHash,
13
13
  } from '@lucid-evolution/lucid';
14
- import { LRPParams, parseLrpDatum } from '../src/contracts/lrp/types';
15
- import { mkLrpValidator } from '../src/contracts/lrp/scripts';
16
- import { runCreateScriptRefTx } from '../src/utils/helper-txs';
17
- import { runOneShotMintTx } from '../src/contracts/one-shot/transactions';
14
+ import { parseLrpDatumOrThrow } from '../src/contracts/lrp/types';
18
15
  import {
19
16
  adjustLrp,
20
17
  cancelLrp,
@@ -24,872 +21,653 @@ import {
24
21
  } from '../src/contracts/lrp/transactions';
25
22
  import { findLrp } from './queries/lrp-queries';
26
23
  import { addrDetails, getInlineDatumOrThrow } from '../src/utils/lucid-utils';
27
- import { runAndAwaitTx, runAndAwaitTxBuilder } from './test-helpers';
24
+ import { LucidContext, runAndAwaitTx } from './test-helpers';
28
25
  import { matchSingle } from '../src/utils/utils';
29
- import { runCreateIAsset } from './indigo-test-helpers';
30
- import { mkPriceOracleValidator } from '../src/contracts/price-oracle/scripts';
31
- import { AssetClass, OracleAssetNft, PriceOracleParams } from '../src';
32
- import { alwaysFailValidator } from '../src/scripts/always-fail-validator';
26
+ import { AssetClass, openCdp, SystemParams } from '../src';
33
27
  import {
34
- OCD_ONE,
35
- OCD_ZERO,
36
- OnChainDecimal,
37
- } from '../src/types/on-chain-decimal';
38
- import { findPriceOracle } from './queries/price-oracle-queries';
39
- import { findIAsset } from './queries/iasset-queries';
40
- import { assetClassValueOf, lovelacesAmt } from '../src/utils/value-helpers';
28
+ assetClassValueOf,
29
+ lovelacesAmt,
30
+ mkLovelacesOf,
31
+ } from '../src/utils/value-helpers';
41
32
  import { strictEqual } from 'assert';
42
- import { startPriceOracleTx } from '../src/contracts/price-oracle/transactions';
43
-
44
- type LRPTestContext = {
45
- iassetAc: AssetClass;
46
- oracleNft: OracleAssetNft;
47
- iassetNft: AssetClass;
48
- iassetValHash: string;
49
- oracleParams: PriceOracleParams;
50
- oracleValHash: string;
51
- };
52
-
53
- async function initTest(
54
- /** The admin account lucid instance */
55
- lucid: LucidEvolution,
56
- network: Network,
57
- iassetTokenName: string,
58
- initialMint: bigint,
59
- iassetPrice: OnChainDecimal,
60
- ): Promise<LRPTestContext> {
61
- const utxos = await lucid.wallet().getUtxos();
62
- const iassetPolicyId = await runOneShotMintTx(lucid, {
63
- referenceOutRef: {
64
- txHash: utxos[0].txHash,
65
- outputIdx: BigInt(utxos[0].outputIndex),
66
- },
67
- mintAmounts: [{ tokenName: iassetTokenName, amount: initialMint }],
68
- });
69
-
70
- const [ownPkh, _] = await addrDetails(lucid);
71
-
72
- const priceOracleParams: PriceOracleParams = {
73
- owner: ownPkh.hash,
74
- // 1 minute
75
- biasTime: 1n * 60n * 1000n,
76
- // 10 minutes
77
- expiration: 10n * 60n * 1000n,
78
- };
79
- const oracleValidator = mkPriceOracleValidator(priceOracleParams);
80
- const oracleValidatorHash = validatorToScriptHash(oracleValidator);
81
- const [tx, oracleNft] = await startPriceOracleTx(
82
- lucid,
83
- 'ORACLE_IBTC',
84
- iassetPrice,
85
- priceOracleParams,
33
+ import { init } from './endpoints/initialize';
34
+ import { iusdInitialAssetCfg } from './mock/assets-mock';
35
+ import { findAllNecessaryOrefs } from './queries/cdp-queries';
36
+
37
+ type MyContext = LucidContext<{
38
+ admin: EmulatorAccount;
39
+ user: EmulatorAccount;
40
+ }>;
41
+
42
+ async function findSingleLrp(
43
+ context: MyContext,
44
+ sysParams: SystemParams,
45
+ iasset: string,
46
+ pkh: Credential,
47
+ ): Promise<UTxO> {
48
+ return matchSingle(
49
+ await findLrp(
50
+ context.lucid,
51
+ sysParams.validatorHashes.lrpHash,
52
+ pkh.hash,
53
+ iasset,
54
+ ),
55
+ (res) => new Error('Expected a single LRP UTXO.: ' + JSON.stringify(res)),
86
56
  );
87
-
88
- await runAndAwaitTxBuilder(lucid, tx);
89
-
90
- const iassetValHash = validatorToScriptHash(alwaysFailValidator);
91
- const iassetNft = await runCreateIAsset(lucid, network, iassetValHash, {
92
- assetName: iassetTokenName,
93
- price: { Oracle: { content: oracleNft } },
94
- interestOracleNft: { currencySymbol: '', tokenName: '' },
95
- redemptionRatio: OCD_ONE,
96
- maintenanceRatio: OCD_ONE,
97
- liquidationRatio: OCD_ONE,
98
- debtMintingFeePercentage: OCD_ZERO,
99
- liquidationProcessingFeePercentage: OCD_ZERO,
100
- stabilityPoolWithdrawalFeePercentage: OCD_ZERO,
101
- redemptionReimbursementPercentage: OCD_ONE,
102
- redemptionProcessingFeePercentage: OCD_ZERO,
103
- interestCollectorPortionPercentage: OCD_ZERO,
104
- firstIAsset: true,
105
- nextIAsset: null,
106
- });
107
-
108
- return {
109
- oracleNft: oracleNft,
110
- iassetAc: { currencySymbol: iassetPolicyId, tokenName: iassetTokenName },
111
- iassetNft: iassetNft,
112
- iassetValHash: iassetValHash,
113
- oracleParams: priceOracleParams,
114
- oracleValHash: oracleValidatorHash,
115
- };
116
57
  }
117
58
 
118
59
  describe('LRP', () => {
119
- it('adjust positive and negative', async () => {
120
- const network: Network = 'Custom';
121
- const account1 = generateEmulatorAccount({
122
- lovelace: 80_000_000_000n, // 80,000 ADA
123
- });
124
-
125
- const emulator = new Emulator([account1]);
126
- const lucid = await Lucid(emulator, network);
127
-
128
- lucid.selectWallet.fromSeed(account1.seedPhrase);
129
-
130
- const iassetTokenName = fromText('iBTC');
131
- const testCtx = await initTest(
132
- lucid,
133
- network,
134
- iassetTokenName,
135
- 10_000_000n,
136
- OCD_ONE,
137
- );
60
+ beforeEach<MyContext>(async (context: MyContext) => {
61
+ context.users = {
62
+ admin: generateEmulatorAccount({
63
+ lovelace: BigInt(100_000_000_000_000),
64
+ }),
65
+ user: generateEmulatorAccount(addAssets(mkLovelacesOf(150_000_000n))),
66
+ };
138
67
 
139
- const [ownPkh, _] = await addrDetails(lucid);
68
+ context.emulator = new Emulator([context.users.admin, context.users.user]);
69
+ context.lucid = await Lucid(context.emulator, 'Custom');
70
+ });
140
71
 
141
- const lrpParams: LRPParams = {
142
- versionRecordToken: {
143
- currencySymbol: fromText('smth'),
144
- tokenName: fromText('version_record'),
145
- },
146
- iassetNft: testCtx.iassetNft,
147
- iassetPolicyId: testCtx.iassetAc.currencySymbol,
148
- minRedemptionLovelacesAmt: 1_000_000n,
149
- };
72
+ test<MyContext>('adjust positive and negative', async (context: MyContext) => {
73
+ context.lucid.selectWallet.fromSeed(context.users.admin.seedPhrase);
150
74
 
151
- const lrpValidator = mkLrpValidator(lrpParams);
152
- const lrpValidatorHash = validatorToScriptHash(lrpValidator);
153
- const lrpRefScriptOutRef = await runCreateScriptRefTx(
154
- lucid,
155
- lrpValidator,
156
- network,
157
- );
75
+ const [sysParams, __] = await init(context.lucid, [iusdInitialAssetCfg]);
158
76
 
159
- const findSingleOwnLrp = async (): Promise<UTxO> => {
160
- return matchSingle(
161
- await findLrp(
162
- lucid,
163
- network,
164
- lrpValidatorHash,
165
- ownPkh.hash,
166
- iassetTokenName,
167
- ),
168
- (res) =>
169
- new Error('Expected a single LRP UTXO.: ' + JSON.stringify(res)),
170
- );
171
- };
77
+ const iasset = fromText(iusdInitialAssetCfg.name);
78
+
79
+ const [ownPkh, _] = await addrDetails(context.lucid);
172
80
 
173
81
  await runAndAwaitTx(
174
- lucid,
82
+ context.lucid,
175
83
  openLrp(
176
- iassetTokenName,
84
+ iasset,
177
85
  20_000_000n,
178
86
  { getOnChainInt: 1_000_000n },
179
- lucid,
180
- lrpValidatorHash,
181
- network,
87
+ context.lucid,
88
+ sysParams,
182
89
  ),
183
90
  );
184
91
 
185
92
  await runAndAwaitTx(
186
- lucid,
187
- findSingleOwnLrp().then((lrp) =>
188
- adjustLrp(lucid, lrp, -1_000_000n, lrpRefScriptOutRef, lrpParams),
93
+ context.lucid,
94
+ findSingleLrp(context, sysParams, iasset, ownPkh).then((lrp) =>
95
+ adjustLrp(context.lucid, lrp, -1_000_000n, sysParams),
189
96
  ),
190
97
  );
191
98
 
192
- const adjustedUtxo1 = await findSingleOwnLrp();
99
+ const adjustedUtxo1 = await findSingleLrp(
100
+ context,
101
+ sysParams,
102
+ iasset,
103
+ ownPkh,
104
+ );
193
105
 
194
106
  assert(
195
- parseLrpDatum(getInlineDatumOrThrow(adjustedUtxo1)).lovelacesToSpend ===
107
+ parseLrpDatumOrThrow(getInlineDatumOrThrow(adjustedUtxo1))
108
+ .lovelacesToSpend ===
196
109
  20_000_000n - 1_000_000n,
197
110
  );
198
111
 
199
112
  expect(
200
113
  lovelacesAmt(adjustedUtxo1.assets) >=
201
- parseLrpDatum(getInlineDatumOrThrow(adjustedUtxo1)).lovelacesToSpend,
114
+ parseLrpDatumOrThrow(getInlineDatumOrThrow(adjustedUtxo1))
115
+ .lovelacesToSpend,
202
116
  'Lovelaces to spend has to be smaller than actual lovelaces in UTXO',
203
117
  ).toBeTruthy();
204
118
 
205
119
  await runAndAwaitTx(
206
- lucid,
207
- adjustLrp(
208
- lucid,
209
- adjustedUtxo1,
210
- 5_000_000n,
211
- lrpRefScriptOutRef,
212
- lrpParams,
213
- ),
120
+ context.lucid,
121
+ adjustLrp(context.lucid, adjustedUtxo1, 5_000_000n, sysParams),
214
122
  );
215
123
 
216
- const adjustedUtxo2 = matchSingle(
217
- await findLrp(
218
- lucid,
219
- network,
220
- lrpValidatorHash,
221
- ownPkh.hash,
222
- iassetTokenName,
223
- ),
224
- (res) => new Error('Expected a single LRP UTXO.: ' + JSON.stringify(res)),
124
+ const adjustedUtxo2 = await findSingleLrp(
125
+ context,
126
+ sysParams,
127
+ iasset,
128
+ ownPkh,
225
129
  );
226
130
 
227
131
  const expectedResultAdaAmt = 20_000_000n - 1_000_000n + 5_000_000n;
228
132
 
229
133
  strictEqual(
230
- parseLrpDatum(getInlineDatumOrThrow(adjustedUtxo2)).lovelacesToSpend,
134
+ parseLrpDatumOrThrow(getInlineDatumOrThrow(adjustedUtxo2))
135
+ .lovelacesToSpend,
231
136
  expectedResultAdaAmt,
232
137
  );
233
138
 
234
139
  expect(
235
140
  lovelacesAmt(adjustedUtxo2.assets) >=
236
- parseLrpDatum(getInlineDatumOrThrow(adjustedUtxo2)).lovelacesToSpend,
141
+ parseLrpDatumOrThrow(getInlineDatumOrThrow(adjustedUtxo2))
142
+ .lovelacesToSpend,
237
143
  'Lovelaces to spend has to be smaller than actual lovelaces in UTXO',
238
144
  ).toBeTruthy();
239
145
  });
240
146
 
241
- it('claim', async () => {
242
- const network: Network = 'Custom';
243
- const account1 = generateEmulatorAccount({
244
- lovelace: 80_000_000_000n, // 80,000 ADA
245
- });
246
-
247
- const emulator = new Emulator([account1]);
248
- const lucid = await Lucid(emulator, network);
147
+ test<MyContext>('claim', async (context: MyContext) => {
148
+ context.lucid.selectWallet.fromSeed(context.users.admin.seedPhrase);
249
149
 
250
- lucid.selectWallet.fromSeed(account1.seedPhrase);
150
+ const [sysParams, __] = await init(context.lucid, [iusdInitialAssetCfg]);
251
151
 
252
- const iassetTokenName = fromText('iBTC');
253
- const testCtx = await initTest(
254
- lucid,
255
- network,
256
- iassetTokenName,
257
- 10_000_000n,
258
- OCD_ONE,
259
- );
260
-
261
- const [ownPkh, _] = await addrDetails(lucid);
152
+ const iasset = fromText(iusdInitialAssetCfg.name);
262
153
 
263
- const lrpParams: LRPParams = {
264
- versionRecordToken: {
265
- currencySymbol: fromText('smth'),
266
- tokenName: fromText('version_record'),
267
- },
268
- iassetNft: testCtx.iassetNft,
269
- iassetPolicyId: testCtx.iassetAc.currencySymbol,
270
- minRedemptionLovelacesAmt: 1_000_000n,
271
- };
154
+ const [ownPkh, _] = await addrDetails(context.lucid);
272
155
 
273
- const lrpValidator = mkLrpValidator(lrpParams);
274
- const lrpValidatorHash = validatorToScriptHash(lrpValidator);
275
- const lrpRefScriptOutRef = await runCreateScriptRefTx(
276
- lucid,
277
- lrpValidator,
278
- network,
279
- );
156
+ {
157
+ const orefs = await findAllNecessaryOrefs(
158
+ context.lucid,
159
+ sysParams,
160
+ toText(iasset),
161
+ );
280
162
 
281
- const findSingleOwnLrp = async (): Promise<UTxO> => {
282
- return matchSingle(
283
- await findLrp(
284
- lucid,
285
- network,
286
- lrpValidatorHash,
287
- ownPkh.hash,
288
- iassetTokenName,
163
+ await runAndAwaitTx(
164
+ context.lucid,
165
+ openCdp(
166
+ 100_000_000n,
167
+ 30_000_000n,
168
+ sysParams,
169
+ orefs.cdpCreatorUtxo,
170
+ orefs.iasset.utxo,
171
+ orefs.priceOracleUtxo,
172
+ orefs.interestOracleUtxo,
173
+ orefs.collectorUtxo,
174
+ context.lucid,
175
+ context.emulator.slot,
289
176
  ),
290
- (res) =>
291
- new Error('Expected a single LRP UTXO.: ' + JSON.stringify(res)),
292
177
  );
293
- };
178
+ }
294
179
 
295
180
  await runAndAwaitTx(
296
- lucid,
181
+ context.lucid,
297
182
  openLrp(
298
- iassetTokenName,
183
+ iasset,
299
184
  20_000_000n,
300
185
  { getOnChainInt: 1_000_000n },
301
- lucid,
302
- lrpValidatorHash,
303
- network,
186
+ context.lucid,
187
+ sysParams,
304
188
  ),
305
189
  );
306
190
 
307
- const lrpUtxo = await findSingleOwnLrp();
191
+ const lrpUtxo = await findSingleLrp(context, sysParams, iasset, ownPkh);
308
192
 
309
193
  const redemptionAsset: AssetClass = {
310
- currencySymbol: testCtx.iassetAc.currencySymbol,
311
- tokenName: iassetTokenName,
194
+ currencySymbol: sysParams.lrpParams.iassetPolicyId.unCurrencySymbol,
195
+ tokenName: iasset,
312
196
  };
313
197
 
314
- strictEqual(
198
+ expect(
315
199
  assetClassValueOf(lrpUtxo.assets, redemptionAsset),
316
- 0n,
317
200
  'LRP should have no iassets before redemption',
318
- );
201
+ ).toBe(0n);
319
202
 
320
- const redemptionIAssetAmt = 5_000_000n;
203
+ const redemptionIAssetAmt = 11_000_000n;
321
204
 
322
- await runAndAwaitTx(
323
- lucid,
324
- redeemLrp(
325
- [[lrpUtxo, redemptionIAssetAmt]],
326
- lrpRefScriptOutRef,
327
- await findPriceOracle(lucid, testCtx.oracleNft),
328
- (
329
- await findIAsset(
330
- lucid,
331
- testCtx.iassetValHash,
332
- testCtx.iassetNft,
333
- toText(iassetTokenName),
334
- )
335
- ).utxo,
336
- lucid,
337
- lrpParams,
338
- network,
339
- ),
340
- );
205
+ {
206
+ const orefs = await findAllNecessaryOrefs(
207
+ context.lucid,
208
+ sysParams,
209
+ toText(iasset),
210
+ );
341
211
 
342
- const redeemedLrp = await findSingleOwnLrp();
212
+ await runAndAwaitTx(
213
+ context.lucid,
214
+ redeemLrp(
215
+ [[lrpUtxo, redemptionIAssetAmt]],
216
+ orefs.priceOracleUtxo,
217
+ orefs.iasset.utxo,
218
+ context.lucid,
219
+ sysParams,
220
+ ),
221
+ );
222
+ }
343
223
 
344
- strictEqual(
224
+ const redeemedLrp = await findSingleLrp(context, sysParams, iasset, ownPkh);
225
+
226
+ expect(
345
227
  assetClassValueOf(redeemedLrp.assets, redemptionAsset),
346
- redemptionIAssetAmt,
347
228
  'LRP has wrong number of iassets after redemption',
348
- );
229
+ ).toBe(redemptionIAssetAmt);
349
230
 
350
231
  await runAndAwaitTx(
351
- lucid,
352
- claimLrp(lucid, redeemedLrp, lrpRefScriptOutRef, lrpParams),
232
+ context.lucid,
233
+ claimLrp(context.lucid, redeemedLrp, sysParams),
353
234
  );
354
235
 
355
- const claimedLrp = await findSingleOwnLrp();
236
+ const claimedLrp = await findSingleLrp(context, sysParams, iasset, ownPkh);
356
237
 
357
- strictEqual(
238
+ expect(
358
239
  assetClassValueOf(claimedLrp.assets, redemptionAsset),
359
- 0n,
360
240
  'LRP has to have 0 redemption assets after claim',
361
- );
241
+ ).toBe(0n);
362
242
  });
363
243
 
364
- it('claim using adjust', async () => {
365
- const network: Network = 'Custom';
366
- const account1 = generateEmulatorAccount({
367
- lovelace: 80_000_000_000n, // 80,000 ADA
368
- });
244
+ test<MyContext>('claim using adjust', async (context: MyContext) => {
245
+ context.lucid.selectWallet.fromSeed(context.users.admin.seedPhrase);
369
246
 
370
- const emulator = new Emulator([account1]);
371
- const lucid = await Lucid(emulator, network);
247
+ const [sysParams, __] = await init(context.lucid, [iusdInitialAssetCfg]);
372
248
 
373
- lucid.selectWallet.fromSeed(account1.seedPhrase);
249
+ const iasset = fromText(iusdInitialAssetCfg.name);
374
250
 
375
- const iassetTokenName = fromText('iBTC');
376
- const testCtx = await initTest(
377
- lucid,
378
- network,
379
- iassetTokenName,
380
- 10_000_000n,
381
- OCD_ONE,
382
- );
251
+ const [ownPkh, _] = await addrDetails(context.lucid);
383
252
 
384
- const [ownPkh, _] = await addrDetails(lucid);
385
-
386
- const lrpParams: LRPParams = {
387
- versionRecordToken: {
388
- currencySymbol: fromText('smth'),
389
- tokenName: fromText('version_record'),
390
- },
391
- iassetNft: testCtx.iassetNft,
392
- iassetPolicyId: testCtx.iassetAc.currencySymbol,
393
- minRedemptionLovelacesAmt: 1_000_000n,
394
- };
395
-
396
- const lrpValidator = mkLrpValidator(lrpParams);
397
- const lrpValidatorHash = validatorToScriptHash(lrpValidator);
398
- const lrpRefScriptOutRef = await runCreateScriptRefTx(
399
- lucid,
400
- lrpValidator,
401
- network,
402
- );
253
+ {
254
+ const orefs = await findAllNecessaryOrefs(
255
+ context.lucid,
256
+ sysParams,
257
+ toText(iasset),
258
+ );
403
259
 
404
- const findSingleOwnLrp = async (): Promise<UTxO> => {
405
- return matchSingle(
406
- await findLrp(
407
- lucid,
408
- network,
409
- lrpValidatorHash,
410
- ownPkh.hash,
411
- iassetTokenName,
260
+ await runAndAwaitTx(
261
+ context.lucid,
262
+ openCdp(
263
+ 100_000_000n,
264
+ 30_000_000n,
265
+ sysParams,
266
+ orefs.cdpCreatorUtxo,
267
+ orefs.iasset.utxo,
268
+ orefs.priceOracleUtxo,
269
+ orefs.interestOracleUtxo,
270
+ orefs.collectorUtxo,
271
+ context.lucid,
272
+ context.emulator.slot,
412
273
  ),
413
- (res) =>
414
- new Error('Expected a single LRP UTXO.: ' + JSON.stringify(res)),
415
274
  );
416
- };
275
+ }
417
276
 
418
277
  await runAndAwaitTx(
419
- lucid,
278
+ context.lucid,
420
279
  openLrp(
421
- iassetTokenName,
280
+ iasset,
422
281
  20_000_000n,
423
282
  { getOnChainInt: 1_000_000n },
424
- lucid,
425
- lrpValidatorHash,
426
- network,
283
+ context.lucid,
284
+ sysParams,
427
285
  ),
428
286
  );
429
287
 
430
- const lrpUtxo = await findSingleOwnLrp();
288
+ const lrpUtxo = await findSingleLrp(context, sysParams, iasset, ownPkh);
431
289
 
432
290
  const redemptionAsset: AssetClass = {
433
- currencySymbol: testCtx.iassetAc.currencySymbol,
434
- tokenName: iassetTokenName,
291
+ currencySymbol: sysParams.lrpParams.iassetPolicyId.unCurrencySymbol,
292
+ tokenName: iasset,
435
293
  };
436
294
 
437
- strictEqual(
295
+ expect(
438
296
  assetClassValueOf(lrpUtxo.assets, redemptionAsset),
439
- 0n,
440
297
  'LRP should have no iassets before redemption',
441
- );
298
+ ).toBe(0n);
442
299
 
443
- const redemptionIAssetAmt = 5_000_000n;
300
+ const redemptionIAssetAmt = 11_000_000n;
444
301
 
445
- await runAndAwaitTx(
446
- lucid,
447
- redeemLrp(
448
- [[lrpUtxo, redemptionIAssetAmt]],
449
- lrpRefScriptOutRef,
450
- await findPriceOracle(lucid, testCtx.oracleNft),
451
- (
452
- await findIAsset(
453
- lucid,
454
- testCtx.iassetValHash,
455
- testCtx.iassetNft,
456
- toText(iassetTokenName),
457
- )
458
- ).utxo,
459
- lucid,
460
- lrpParams,
461
- network,
462
- ),
463
- );
302
+ {
303
+ const orefs = await findAllNecessaryOrefs(
304
+ context.lucid,
305
+ sysParams,
306
+ toText(iasset),
307
+ );
464
308
 
465
- const redeemedLrp = await findSingleOwnLrp();
309
+ await runAndAwaitTx(
310
+ context.lucid,
311
+ redeemLrp(
312
+ [[lrpUtxo, redemptionIAssetAmt]],
313
+ orefs.priceOracleUtxo,
314
+ orefs.iasset.utxo,
315
+ context.lucid,
316
+ sysParams,
317
+ ),
318
+ );
319
+ }
466
320
 
467
- strictEqual(
321
+ const redeemedLrp = await findSingleLrp(context, sysParams, iasset, ownPkh);
322
+
323
+ expect(
468
324
  assetClassValueOf(redeemedLrp.assets, redemptionAsset),
469
- redemptionIAssetAmt,
470
325
  'LRP has wrong number of iassets after redemption',
471
- );
326
+ ).toBe(redemptionIAssetAmt);
472
327
 
473
328
  await runAndAwaitTx(
474
- lucid,
475
- adjustLrp(lucid, redeemedLrp, -1_000_000n, lrpRefScriptOutRef, lrpParams),
329
+ context.lucid,
330
+ adjustLrp(context.lucid, redeemedLrp, -1_000_000n, sysParams),
476
331
  );
477
332
 
478
- const adjustedLrp = await findSingleOwnLrp();
333
+ const adjustedLrp = await findSingleLrp(context, sysParams, iasset, ownPkh);
479
334
 
480
- strictEqual(
335
+ expect(
481
336
  assetClassValueOf(adjustedLrp.assets, redemptionAsset),
482
- 0n,
483
337
  'LRP has to have 0 redemption assets after adjust',
484
- );
338
+ ).toBe(0n);
485
339
 
486
340
  strictEqual(
487
- parseLrpDatum(getInlineDatumOrThrow(adjustedLrp)).lovelacesToSpend,
488
- // 20mil start, 5mil redeemer at price 1:1, -1mil adjusted
489
- 14_000_000n,
341
+ parseLrpDatumOrThrow(getInlineDatumOrThrow(adjustedLrp)).lovelacesToSpend,
342
+ // 20mil start, 11mil redeemed at price 1:1, -1mil adjusted
343
+ 8_000_000n,
490
344
  );
491
345
  });
492
346
 
493
- it('single redemption and cancel', async () => {
494
- const network: Network = 'Custom';
495
- const account1 = generateEmulatorAccount({
496
- lovelace: 80_000_000_000n, // 80,000 ADA
497
- });
347
+ test<MyContext>('single redemption and cancel', async (context: MyContext) => {
348
+ context.lucid.selectWallet.fromSeed(context.users.admin.seedPhrase);
498
349
 
499
- const emulator = new Emulator([account1]);
500
- const lucid = await Lucid(emulator, network);
350
+ const [sysParams, __] = await init(context.lucid, [iusdInitialAssetCfg]);
501
351
 
502
- lucid.selectWallet.fromSeed(account1.seedPhrase);
352
+ const iasset = fromText(iusdInitialAssetCfg.name);
503
353
 
504
- const iassetTokenName = fromText('iBTC');
505
- const testCtx = await initTest(
506
- lucid,
507
- network,
508
- iassetTokenName,
509
- 10_000_000n,
510
- OCD_ONE,
511
- );
512
-
513
- const [ownPkh, _] = await addrDetails(lucid);
354
+ const [ownPkh, _] = await addrDetails(context.lucid);
514
355
 
515
- const lrpParams: LRPParams = {
516
- versionRecordToken: {
517
- currencySymbol: fromText('smth'),
518
- tokenName: fromText('version_record'),
519
- },
520
- iassetNft: testCtx.iassetNft,
521
- iassetPolicyId: testCtx.iassetAc.currencySymbol,
522
- minRedemptionLovelacesAmt: 1_000_000n,
523
- };
524
-
525
- const lrpValidator = mkLrpValidator(lrpParams);
526
- const lrpValidatorHash = validatorToScriptHash(lrpValidator);
527
- const lrpRefScriptOutRef = await runCreateScriptRefTx(
528
- lucid,
529
- lrpValidator,
530
- network,
531
- );
356
+ {
357
+ const orefs = await findAllNecessaryOrefs(
358
+ context.lucid,
359
+ sysParams,
360
+ toText(iasset),
361
+ );
532
362
 
533
- const findSingleOwnLrp = async (): Promise<UTxO> => {
534
- return matchSingle(
535
- await findLrp(
536
- lucid,
537
- network,
538
- lrpValidatorHash,
539
- ownPkh.hash,
540
- iassetTokenName,
363
+ await runAndAwaitTx(
364
+ context.lucid,
365
+ openCdp(
366
+ 100_000_000n,
367
+ 30_000_000n,
368
+ sysParams,
369
+ orefs.cdpCreatorUtxo,
370
+ orefs.iasset.utxo,
371
+ orefs.priceOracleUtxo,
372
+ orefs.interestOracleUtxo,
373
+ orefs.collectorUtxo,
374
+ context.lucid,
375
+ context.emulator.slot,
541
376
  ),
542
- (res) =>
543
- new Error('Expected a single LRP UTXO.: ' + JSON.stringify(res)),
544
377
  );
545
- };
378
+ }
546
379
 
547
380
  await runAndAwaitTx(
548
- lucid,
381
+ context.lucid,
549
382
  openLrp(
550
- iassetTokenName,
383
+ iasset,
551
384
  20_000_000n,
552
385
  { getOnChainInt: 1_000_000n },
553
- lucid,
554
- lrpValidatorHash,
555
- network,
386
+ context.lucid,
387
+ sysParams,
556
388
  ),
557
389
  );
558
390
 
559
- const lrpUtxo = await findSingleOwnLrp();
391
+ const lrpUtxo = await findSingleLrp(context, sysParams, iasset, ownPkh);
560
392
 
561
393
  const redemptionAsset: AssetClass = {
562
- currencySymbol: testCtx.iassetAc.currencySymbol,
563
- tokenName: iassetTokenName,
394
+ currencySymbol: sysParams.lrpParams.iassetPolicyId.unCurrencySymbol,
395
+ tokenName: iasset,
564
396
  };
565
397
 
566
- strictEqual(
398
+ expect(
567
399
  assetClassValueOf(lrpUtxo.assets, redemptionAsset),
568
- 0n,
569
400
  'LRP should have no iassets before redemption',
570
- );
401
+ ).toBe(0n);
571
402
 
572
- const redemptionIAssetAmt = 5_000_000n;
403
+ const redemptionIAssetAmt = 11_000_000n;
573
404
 
574
- await runAndAwaitTx(
575
- lucid,
576
- redeemLrp(
577
- [[lrpUtxo, redemptionIAssetAmt]],
578
- lrpRefScriptOutRef,
579
- await findPriceOracle(lucid, testCtx.oracleNft),
580
- (
581
- await findIAsset(
582
- lucid,
583
- testCtx.iassetValHash,
584
- testCtx.iassetNft,
585
- toText(iassetTokenName),
586
- )
587
- ).utxo,
588
- lucid,
589
- lrpParams,
590
- network,
591
- ),
592
- );
405
+ {
406
+ const orefs = await findAllNecessaryOrefs(
407
+ context.lucid,
408
+ sysParams,
409
+ toText(iasset),
410
+ );
593
411
 
594
- const redeemedLrp = await findSingleOwnLrp();
412
+ await runAndAwaitTx(
413
+ context.lucid,
414
+ redeemLrp(
415
+ [[lrpUtxo, redemptionIAssetAmt]],
416
+ orefs.priceOracleUtxo,
417
+ orefs.iasset.utxo,
418
+ context.lucid,
419
+ sysParams,
420
+ ),
421
+ );
422
+ }
595
423
 
596
- strictEqual(
424
+ const redeemedLrp = await findSingleLrp(context, sysParams, iasset, ownPkh);
425
+
426
+ expect(
597
427
  assetClassValueOf(redeemedLrp.assets, redemptionAsset),
598
- redemptionIAssetAmt,
599
428
  'LRP has wrong number of iassets after redemption',
600
- );
429
+ ).toBe(redemptionIAssetAmt);
601
430
 
602
431
  await runAndAwaitTx(
603
- lucid,
604
- cancelLrp(redeemedLrp, lrpRefScriptOutRef, lucid),
432
+ context.lucid,
433
+ cancelLrp(redeemedLrp, sysParams, context.lucid),
605
434
  );
606
435
  });
607
436
 
608
- it('redeem, redeem again and cancel', async () => {
609
- const network: Network = 'Custom';
610
- const account1 = generateEmulatorAccount({
611
- lovelace: 80_000_000_000n, // 80,000 ADA
612
- });
437
+ test<MyContext>('redeem, redeem again and cancel', async (context: MyContext) => {
438
+ context.lucid.selectWallet.fromSeed(context.users.admin.seedPhrase);
613
439
 
614
- const emulator = new Emulator([account1]);
615
- const lucid = await Lucid(emulator, network);
440
+ const [sysParams, __] = await init(context.lucid, [iusdInitialAssetCfg]);
616
441
 
617
- lucid.selectWallet.fromSeed(account1.seedPhrase);
442
+ const iasset = fromText(iusdInitialAssetCfg.name);
618
443
 
619
- const iassetTokenName = fromText('iBTC');
620
- const testCtx = await initTest(
621
- lucid,
622
- network,
623
- iassetTokenName,
624
- 10_000_000n,
625
- OCD_ONE,
626
- );
444
+ const [ownPkh, _] = await addrDetails(context.lucid);
627
445
 
628
- const [ownPkh, _] = await addrDetails(lucid);
629
-
630
- const lrpParams: LRPParams = {
631
- versionRecordToken: {
632
- currencySymbol: fromText('smth'),
633
- tokenName: fromText('version_record'),
634
- },
635
- iassetNft: testCtx.iassetNft,
636
- iassetPolicyId: testCtx.iassetAc.currencySymbol,
637
- minRedemptionLovelacesAmt: 1_000_000n,
638
- };
639
-
640
- const lrpValidator = mkLrpValidator(lrpParams);
641
- const lrpValidatorHash = validatorToScriptHash(lrpValidator);
642
- const lrpRefScriptOutRef = await runCreateScriptRefTx(
643
- lucid,
644
- lrpValidator,
645
- network,
646
- );
446
+ {
447
+ const orefs = await findAllNecessaryOrefs(
448
+ context.lucid,
449
+ sysParams,
450
+ toText(iasset),
451
+ );
647
452
 
648
- const findSingleOwnLrp = async (): Promise<UTxO> => {
649
- return matchSingle(
650
- await findLrp(
651
- lucid,
652
- network,
653
- lrpValidatorHash,
654
- ownPkh.hash,
655
- iassetTokenName,
453
+ await runAndAwaitTx(
454
+ context.lucid,
455
+ openCdp(
456
+ 100_000_000n,
457
+ 30_000_000n,
458
+ sysParams,
459
+ orefs.cdpCreatorUtxo,
460
+ orefs.iasset.utxo,
461
+ orefs.priceOracleUtxo,
462
+ orefs.interestOracleUtxo,
463
+ orefs.collectorUtxo,
464
+ context.lucid,
465
+ context.emulator.slot,
656
466
  ),
657
- (res) =>
658
- new Error('Expected a single LRP UTXO.: ' + JSON.stringify(res)),
659
467
  );
660
- };
468
+ }
661
469
 
662
470
  await runAndAwaitTx(
663
- lucid,
471
+ context.lucid,
664
472
  openLrp(
665
- iassetTokenName,
666
- 20_000_000n,
473
+ iasset,
474
+ 40_000_000n,
667
475
  { getOnChainInt: 1_000_000n },
668
- lucid,
669
- lrpValidatorHash,
670
- network,
476
+ context.lucid,
477
+ sysParams,
671
478
  ),
672
479
  );
673
480
 
674
- const lrpUtxo = await findSingleOwnLrp();
481
+ const lrpUtxo = await findSingleLrp(context, sysParams, iasset, ownPkh);
675
482
 
676
483
  const redemptionAsset: AssetClass = {
677
- currencySymbol: testCtx.iassetAc.currencySymbol,
678
- tokenName: iassetTokenName,
484
+ currencySymbol: sysParams.lrpParams.iassetPolicyId.unCurrencySymbol,
485
+ tokenName: iasset,
679
486
  };
680
487
 
681
- strictEqual(
488
+ expect(
682
489
  assetClassValueOf(lrpUtxo.assets, redemptionAsset),
683
- 0n,
684
490
  'LRP should have no iassets before redemption',
685
- );
491
+ ).toBe(0n);
686
492
 
687
- const redemptionIAssetAmt = 5_000_000n;
493
+ const redemptionIAssetAmt = 11_000_000n;
688
494
 
689
- await runAndAwaitTx(
690
- lucid,
691
- redeemLrp(
692
- [[lrpUtxo, redemptionIAssetAmt]],
693
- lrpRefScriptOutRef,
694
- await findPriceOracle(lucid, testCtx.oracleNft),
695
- (
696
- await findIAsset(
697
- lucid,
698
- testCtx.iassetValHash,
699
- testCtx.iassetNft,
700
- toText(iassetTokenName),
701
- )
702
- ).utxo,
703
- lucid,
704
- lrpParams,
705
- network,
706
- ),
707
- );
495
+ {
496
+ const orefs = await findAllNecessaryOrefs(
497
+ context.lucid,
498
+ sysParams,
499
+ toText(iasset),
500
+ );
501
+
502
+ await runAndAwaitTx(
503
+ context.lucid,
504
+ redeemLrp(
505
+ [[lrpUtxo, redemptionIAssetAmt]],
506
+ orefs.priceOracleUtxo,
507
+ orefs.iasset.utxo,
508
+ context.lucid,
509
+ sysParams,
510
+ ),
511
+ );
512
+ }
708
513
 
709
- const redeemedLrp = await findSingleOwnLrp();
514
+ const redeemedLrp = await findSingleLrp(context, sysParams, iasset, ownPkh);
710
515
 
711
- await runAndAwaitTx(
712
- lucid,
713
- redeemLrp(
714
- [[redeemedLrp, redemptionIAssetAmt]],
715
- lrpRefScriptOutRef,
716
- await findPriceOracle(lucid, testCtx.oracleNft),
717
- (
718
- await findIAsset(
719
- lucid,
720
- testCtx.iassetValHash,
721
- testCtx.iassetNft,
722
- toText(iassetTokenName),
723
- )
724
- ).utxo,
725
- lucid,
726
- lrpParams,
727
- network,
728
- ),
729
- );
516
+ {
517
+ const orefs = await findAllNecessaryOrefs(
518
+ context.lucid,
519
+ sysParams,
520
+ toText(iasset),
521
+ );
522
+
523
+ await runAndAwaitTx(
524
+ context.lucid,
525
+ redeemLrp(
526
+ [[redeemedLrp, redemptionIAssetAmt]],
527
+ orefs.priceOracleUtxo,
528
+ orefs.iasset.utxo,
529
+ context.lucid,
530
+ sysParams,
531
+ ),
532
+ );
533
+ }
534
+
535
+ const closableLrp = await findSingleLrp(context, sysParams, iasset, ownPkh);
730
536
 
731
537
  strictEqual(
732
- assetClassValueOf(redeemedLrp.assets, redemptionAsset),
733
- redemptionIAssetAmt,
734
- 'LRP has wrong number of iassets after redemption',
538
+ assetClassValueOf(closableLrp.assets, redemptionAsset),
539
+ redemptionIAssetAmt * 2n,
540
+ 'LRP has wrong number of iassets after 2 redemptions',
735
541
  );
736
542
 
737
- const closableLrp = await findSingleOwnLrp();
543
+ expect(
544
+ assetClassValueOf(redeemedLrp.assets, redemptionAsset),
545
+ 'LRP has wrong number of iassets after redemption',
546
+ ).toBe(redemptionIAssetAmt);
738
547
 
739
548
  await runAndAwaitTx(
740
- lucid,
741
- cancelLrp(closableLrp, lrpRefScriptOutRef, lucid),
549
+ context.lucid,
550
+ cancelLrp(closableLrp, sysParams, context.lucid),
742
551
  );
743
552
  });
744
553
 
745
- it('multi redemption case', async () => {
746
- const network: Network = 'Custom';
747
- const account1 = generateEmulatorAccount({
748
- lovelace: 80_000_000_000n, // 80,000 ADA
749
- });
750
- const account2 = generateEmulatorAccount({
751
- lovelace: 80_000_000_000n, // 80,000 ADA
752
- });
753
-
754
- const emulator = new Emulator([account1, account2]);
755
- const lucid = await Lucid(emulator, network);
756
-
757
- lucid.selectWallet.fromSeed(account1.seedPhrase);
758
-
759
- const iassetTokenName = fromText('TEST_IBTC');
760
- const testCtx = await initTest(
761
- lucid,
762
- network,
763
- iassetTokenName,
764
- 100_000_000n,
765
- OCD_ONE,
766
- );
554
+ test<MyContext>('multi redemption case', async (context: MyContext) => {
555
+ context.lucid.selectWallet.fromSeed(context.users.admin.seedPhrase);
767
556
 
768
- const lrpParams: LRPParams = {
769
- versionRecordToken: {
770
- currencySymbol: fromText('smth'),
771
- tokenName: fromText('version_record'),
772
- },
773
- iassetNft: testCtx.iassetNft,
774
- iassetPolicyId: testCtx.iassetAc.currencySymbol,
775
- minRedemptionLovelacesAmt: 1_000_000n,
776
- };
557
+ const [sysParams, __] = await init(context.lucid, [iusdInitialAssetCfg]);
777
558
 
778
- const lrpValidator = mkLrpValidator(lrpParams);
779
- const lrpValidatorHash = validatorToScriptHash(lrpValidator);
780
- const lrpRefScriptOutRef = await runCreateScriptRefTx(
781
- lucid,
782
- lrpValidator,
783
- network,
784
- );
559
+ const iasset = fromText(iusdInitialAssetCfg.name);
560
+
561
+ {
562
+ const orefs = await findAllNecessaryOrefs(
563
+ context.lucid,
564
+ sysParams,
565
+ toText(iasset),
566
+ );
567
+
568
+ await runAndAwaitTx(
569
+ context.lucid,
570
+ openCdp(
571
+ 100_000_000n,
572
+ 30_000_000n,
573
+ sysParams,
574
+ orefs.cdpCreatorUtxo,
575
+ orefs.iasset.utxo,
576
+ orefs.priceOracleUtxo,
577
+ orefs.interestOracleUtxo,
578
+ orefs.collectorUtxo,
579
+ context.lucid,
580
+ context.emulator.slot,
581
+ ),
582
+ );
583
+ }
785
584
 
786
585
  await runAndAwaitTx(
787
- lucid,
586
+ context.lucid,
788
587
  openLrp(
789
- iassetTokenName,
588
+ iasset,
790
589
  20_000_000n,
791
590
  { getOnChainInt: 1_000_000n },
792
- lucid,
793
- lrpValidatorHash,
794
- network,
591
+ context.lucid,
592
+ sysParams,
795
593
  ),
796
594
  );
797
595
 
798
- lucid.selectWallet.fromSeed(account2.seedPhrase);
596
+ context.lucid.selectWallet.fromSeed(context.users.user.seedPhrase);
799
597
 
800
598
  await runAndAwaitTx(
801
- lucid,
599
+ context.lucid,
802
600
  openLrp(
803
- iassetTokenName,
601
+ iasset,
804
602
  20_000_000n,
805
- { getOnChainInt: 1_100_000n },
806
- lucid,
807
- lrpValidatorHash,
808
- network,
603
+ { getOnChainInt: 1_000_000n },
604
+ context.lucid,
605
+ sysParams,
809
606
  ),
810
607
  );
811
608
 
812
- const lrpUtxo2 = matchSingle(
813
- await findLrp(
814
- lucid,
815
- network,
816
- lrpValidatorHash,
817
- await addrDetails(lucid).then((d) => d[0].hash),
818
- iassetTokenName,
819
- ),
820
- (res) => new Error('Expected a single LRP UTXO.: ' + JSON.stringify(res)),
609
+ const lrpUtxo1 = await findSingleLrp(
610
+ context,
611
+ sysParams,
612
+ iasset,
613
+ paymentCredentialOf(context.users.admin.address),
614
+ );
615
+ const lrpUtxo2 = await findSingleLrp(
616
+ context,
617
+ sysParams,
618
+ iasset,
619
+ paymentCredentialOf(context.users.user.address),
821
620
  );
822
621
 
823
- lucid.selectWallet.fromSeed(account1.seedPhrase);
622
+ context.lucid.selectWallet.fromSeed(context.users.admin.seedPhrase);
824
623
 
825
- const lrpUtxo1 = matchSingle(
826
- await findLrp(
827
- lucid,
828
- network,
829
- lrpValidatorHash,
830
- await addrDetails(lucid).then((d) => d[0].hash),
831
- iassetTokenName,
832
- ),
833
- (res) => new Error('Expected a single LRP UTXO.: ' + JSON.stringify(res)),
834
- );
624
+ {
625
+ const orefs = await findAllNecessaryOrefs(
626
+ context.lucid,
627
+ sysParams,
628
+ toText(iasset),
629
+ );
835
630
 
836
- await runAndAwaitTx(
837
- lucid,
838
- redeemLrp(
839
- [
840
- [lrpUtxo1, 5_000_000n],
841
- [lrpUtxo2, 4_000_000n],
842
- ],
843
- lrpRefScriptOutRef,
844
- await findPriceOracle(lucid, testCtx.oracleNft),
845
- (
846
- await findIAsset(
847
- lucid,
848
- testCtx.iassetValHash,
849
- testCtx.iassetNft,
850
- toText(iassetTokenName),
851
- )
852
- ).utxo,
853
- lucid,
854
- lrpParams,
855
- network,
856
- ),
857
- );
631
+ await runAndAwaitTx(
632
+ context.lucid,
633
+ redeemLrp(
634
+ [
635
+ [lrpUtxo1, 10_000_000n],
636
+ [lrpUtxo2, 11_000_000n],
637
+ ],
638
+ orefs.priceOracleUtxo,
639
+ orefs.iasset.utxo,
640
+ context.lucid,
641
+ sysParams,
642
+ ),
643
+ );
644
+ }
858
645
 
859
- const resultLrpUtxo1 = matchSingle(
860
- await findLrp(
861
- lucid,
862
- network,
863
- lrpValidatorHash,
864
- paymentCredentialOf(account1.address).hash,
865
- iassetTokenName,
866
- ),
867
- (res) => new Error('Expected a single LRP UTXO.: ' + JSON.stringify(res)),
646
+ const resultLrpUtxo1 = await findSingleLrp(
647
+ context,
648
+ sysParams,
649
+ iasset,
650
+ paymentCredentialOf(context.users.admin.address),
868
651
  );
869
- const resultLrpUtxo2 = matchSingle(
870
- await findLrp(
871
- lucid,
872
- network,
873
- lrpValidatorHash,
874
- paymentCredentialOf(account2.address).hash,
875
- iassetTokenName,
876
- ),
877
- (res) => new Error('Expected a single LRP UTXO.: ' + JSON.stringify(res)),
652
+ const resultLrpUtxo2 = await findSingleLrp(
653
+ context,
654
+ sysParams,
655
+ iasset,
656
+ paymentCredentialOf(context.users.user.address),
878
657
  );
879
658
 
880
- assert(
881
- assetClassValueOf(resultLrpUtxo1.assets, {
882
- currencySymbol: testCtx.iassetAc.currencySymbol,
883
- tokenName: iassetTokenName,
884
- }) === 5_000_000n,
659
+ const redemptionAsset: AssetClass = {
660
+ currencySymbol: sysParams.lrpParams.iassetPolicyId.unCurrencySymbol,
661
+ tokenName: iasset,
662
+ };
663
+
664
+ expect(
665
+ assetClassValueOf(resultLrpUtxo1.assets, redemptionAsset),
885
666
  'LRP1 has wrong number of iassets after redemption',
886
- );
887
- assert(
888
- assetClassValueOf(resultLrpUtxo2.assets, {
889
- currencySymbol: testCtx.iassetAc.currencySymbol,
890
- tokenName: iassetTokenName,
891
- }) === 4_000_000n,
667
+ ).toBe(10_000_000n);
668
+ expect(
669
+ assetClassValueOf(resultLrpUtxo2.assets, redemptionAsset),
892
670
  'LRP2 has wrong number of iassets after redemption',
893
- );
671
+ ).toBe(11_000_000n);
894
672
  });
895
673
  });