@indigo-labs/indigo-sdk 0.1.2 → 0.1.3

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 (93) hide show
  1. package/.github/workflows/ci.yml +62 -0
  2. package/.github/workflows/test.yml +44 -0
  3. package/.husky/pre-commit +1 -0
  4. package/.prettierrc +1 -1
  5. package/README.md +52 -7
  6. package/dist/index.d.mts +1064 -182
  7. package/dist/index.d.ts +1064 -182
  8. package/dist/index.js +2565 -561
  9. package/dist/index.mjs +2546 -593
  10. package/eslint.config.mjs +35 -0
  11. package/package.json +61 -43
  12. package/src/contracts/cdp.ts +208 -359
  13. package/src/contracts/collector.ts +13 -6
  14. package/src/contracts/gov.ts +1 -58
  15. package/src/contracts/interest-oracle.ts +139 -39
  16. package/src/contracts/lrp.ts +223 -0
  17. package/src/contracts/one-shot.ts +67 -0
  18. package/src/contracts/stability-pool.ts +684 -0
  19. package/src/contracts/staking.ts +348 -0
  20. package/src/contracts/treasury.ts +30 -13
  21. package/src/helpers/asset-helpers.ts +51 -22
  22. package/src/helpers/helper-txs.ts +30 -0
  23. package/src/helpers/helpers.ts +29 -8
  24. package/src/helpers/indigo-helpers.ts +19 -0
  25. package/src/helpers/interest-oracle.ts +57 -0
  26. package/src/helpers/lucid-utils.ts +62 -16
  27. package/src/helpers/price-oracle-helpers.ts +36 -0
  28. package/src/helpers/stability-pool-helpers.ts +207 -0
  29. package/src/helpers/staking-helpers.ts +94 -0
  30. package/src/helpers/time-helpers.ts +4 -3
  31. package/src/helpers/value-helpers.ts +16 -0
  32. package/src/index.ts +15 -4
  33. package/src/scripts/always-fail-validator.ts +7 -0
  34. package/src/scripts/auth-token-policy.ts +23 -0
  35. package/src/scripts/cdp-creator-validator.ts +46 -2
  36. package/src/scripts/collector-validator.ts +2 -2
  37. package/src/scripts/execute-validator.ts +52 -0
  38. package/src/scripts/gov-validator.ts +44 -0
  39. package/src/scripts/iasset-policy.ts +22 -0
  40. package/src/scripts/interest-oracle-validator.ts +18 -3
  41. package/src/scripts/lrp-validator.ts +23 -0
  42. package/src/scripts/one-shot-policy.ts +62 -0
  43. package/src/scripts/poll-manager-validator.ts +52 -0
  44. package/src/scripts/poll-shard-validator.ts +47 -0
  45. package/src/scripts/price-oracle-validator.ts +26 -0
  46. package/src/scripts/stability-pool-validator.ts +60 -0
  47. package/src/scripts/staking-validator.ts +8 -0
  48. package/src/scripts/version-record-policy.ts +26 -0
  49. package/src/scripts/version-registry.ts +15 -0
  50. package/src/types/generic.ts +99 -6
  51. package/src/types/indigo/cdp-creator.ts +46 -0
  52. package/src/types/indigo/cdp.ts +86 -31
  53. package/src/types/indigo/execute.ts +21 -0
  54. package/src/types/indigo/gov.ts +50 -20
  55. package/src/types/indigo/interest-oracle.ts +55 -5
  56. package/src/types/indigo/lrp.ts +54 -0
  57. package/src/types/indigo/poll-manager.ts +21 -0
  58. package/src/types/indigo/poll-shard.ts +16 -0
  59. package/src/types/indigo/price-oracle.ts +38 -4
  60. package/src/types/indigo/stability-pool.ts +233 -0
  61. package/src/types/indigo/staking.ts +99 -0
  62. package/src/types/indigo/version-record.ts +17 -0
  63. package/src/types/on-chain-decimal.ts +23 -0
  64. package/src/types/one-shot.ts +22 -0
  65. package/src/types/system-params.ts +95 -77
  66. package/tests/data/system-params.json +972 -972
  67. package/tests/datums.test.ts +279 -44
  68. package/tests/endpoints/initialize.ts +1013 -0
  69. package/tests/hash-checks.test.ts +71 -15
  70. package/tests/indigo-test-helpers.ts +115 -0
  71. package/tests/initialize.test.ts +27 -0
  72. package/tests/interest-calculations.test.ts +110 -133
  73. package/tests/interest-oracle.test.ts +90 -0
  74. package/tests/lrp.test.ts +149 -0
  75. package/tests/queries/governance-queries.ts +31 -0
  76. package/tests/queries/iasset-queries.ts +39 -0
  77. package/tests/queries/interest-oracle-queries.ts +13 -0
  78. package/tests/queries/lrp-queries.ts +39 -0
  79. package/tests/queries/price-oracle-queries.ts +27 -0
  80. package/tests/queries/stability-pool-queries.ts +75 -0
  81. package/tests/queries/staking-queries.ts +43 -0
  82. package/tests/stability-pool.test.ts +364 -0
  83. package/tests/staking.test.ts +105 -0
  84. package/tests/test-helpers.ts +38 -0
  85. package/tsconfig.build.json +4 -0
  86. package/tsconfig.json +8 -27
  87. package/vitest.config.ts +9 -0
  88. package/babel.config.cjs +0 -13
  89. package/examples/sample-cdp.ts +0 -43
  90. package/jest.config.js +0 -13
  91. package/src/contracts/cdp-creator.ts +0 -86
  92. package/src/contracts/price-oracle.ts +0 -24
  93. package/src/helpers/cdp-helpers.ts +0 -9
@@ -0,0 +1,684 @@
1
+ import {
2
+ Constr,
3
+ fromText,
4
+ LucidEvolution,
5
+ TxBuilder,
6
+ validatorToScriptHash,
7
+ Data,
8
+ UTxO,
9
+ credentialToAddress,
10
+ } from '@lucid-evolution/lucid';
11
+ import {
12
+ EpochToScaleToSum,
13
+ mkSPInteger,
14
+ parseAccountDatum,
15
+ parseStabilityPoolDatum,
16
+ serialiseStabilityPoolDatum,
17
+ serialiseStabilityPoolRedeemer,
18
+ spDiv,
19
+ spMul,
20
+ StabilityPoolDatum,
21
+ StabilityPoolRedeemer,
22
+ StabilityPoolSnapshot,
23
+ AccountAction,
24
+ AccountContent,
25
+ spAdd,
26
+ fromSPInteger,
27
+ ActionReturnDatum,
28
+ spSub,
29
+ } from '../types/indigo/stability-pool';
30
+ import { SystemParams } from '../types/system-params';
31
+ import { addrDetails, scriptRef } from '../helpers/lucid-utils';
32
+ import { mkStabilityPoolValidatorFromSP } from '../scripts/stability-pool-validator';
33
+ import {
34
+ adjustmentHelper,
35
+ setSumInEpochToScaleToSum,
36
+ updatePoolSnapshotWithdrawalFee,
37
+ } from '../helpers/stability-pool-helpers';
38
+ import { calculateFeeFromPercentage } from '../helpers/indigo-helpers';
39
+ import { GovDatum, parseGovDatum } from '../types/indigo/gov';
40
+ import { IAssetContent, parseIAssetDatum } from '../types/indigo/cdp';
41
+ import { CollectorContract } from './collector';
42
+ import { addressFromBech32, addressToBech32 } from '../types/generic';
43
+
44
+ export class StabilityPoolContract {
45
+ static async createAccount(
46
+ asset: string,
47
+ amount: bigint,
48
+ params: SystemParams,
49
+ lucid: LucidEvolution,
50
+ ): Promise<TxBuilder> {
51
+ const [pkh, _skh] = await addrDetails(lucid);
52
+ const minLovelaces = BigInt(
53
+ params.stabilityPoolParams.accountCreateFeeLovelaces +
54
+ params.stabilityPoolParams.requestCollateralLovelaces,
55
+ );
56
+ const datum: StabilityPoolDatum = {
57
+ Account: {
58
+ content: {
59
+ owner: pkh.hash,
60
+ asset: fromText(asset),
61
+ snapshot: {
62
+ productVal: { value: 0n },
63
+ depositVal: { value: 0n },
64
+ sumVal: { value: 0n },
65
+ epoch: 0n,
66
+ scale: 0n,
67
+ },
68
+ request: 'Create',
69
+ },
70
+ },
71
+ };
72
+
73
+ return lucid
74
+ .newTx()
75
+ .pay.ToContract(
76
+ credentialToAddress(lucid.config().network, {
77
+ hash: validatorToScriptHash(
78
+ mkStabilityPoolValidatorFromSP(params.stabilityPoolParams),
79
+ ),
80
+ type: 'Script',
81
+ }),
82
+ { kind: 'inline', value: serialiseStabilityPoolDatum(datum) },
83
+ {
84
+ lovelace: minLovelaces,
85
+ [params.stabilityPoolParams.assetSymbol.unCurrencySymbol +
86
+ fromText(asset)]: amount,
87
+ },
88
+ )
89
+ .addSignerKey(pkh.hash);
90
+ }
91
+
92
+ static async adjustAccount(
93
+ asset: string,
94
+ amount: bigint,
95
+ accountUtxo: UTxO,
96
+ params: SystemParams,
97
+ lucid: LucidEvolution,
98
+ ): Promise<TxBuilder> {
99
+ const [pkh, _] = await addrDetails(lucid);
100
+ const myAddress = await lucid.wallet().address();
101
+
102
+ const stabilityPoolScriptRef = await scriptRef(
103
+ params.scriptReferences.stabilityPoolValidatorRef,
104
+ lucid,
105
+ );
106
+
107
+ const request: AccountAction = {
108
+ Adjust: {
109
+ amount: amount,
110
+ outputAddress: addressFromBech32(myAddress),
111
+ },
112
+ };
113
+ const oldAccountDatum: AccountContent = parseAccountDatum(
114
+ accountUtxo.datum,
115
+ );
116
+ const newAccountDatum: AccountContent = {
117
+ ...oldAccountDatum,
118
+ request,
119
+ };
120
+
121
+ const redeemer: StabilityPoolRedeemer = {
122
+ RequestAction: {
123
+ action: request,
124
+ },
125
+ };
126
+
127
+ return lucid
128
+ .newTx()
129
+ .readFrom([stabilityPoolScriptRef])
130
+ .collectFrom([accountUtxo], serialiseStabilityPoolRedeemer(redeemer))
131
+ .pay.ToContract(
132
+ credentialToAddress(lucid.config().network, {
133
+ hash: validatorToScriptHash(
134
+ mkStabilityPoolValidatorFromSP(params.stabilityPoolParams),
135
+ ),
136
+ type: 'Script',
137
+ }),
138
+ {
139
+ kind: 'inline',
140
+ value: serialiseStabilityPoolDatum({
141
+ Account: {
142
+ content: newAccountDatum,
143
+ },
144
+ }),
145
+ },
146
+ {
147
+ lovelace: BigInt(
148
+ params.stabilityPoolParams.requestCollateralLovelaces +
149
+ params.stabilityPoolParams.accountAdjustmentFeeLovelaces,
150
+ ),
151
+ [params.stabilityPoolParams.accountToken[0].unCurrencySymbol +
152
+ fromText(params.stabilityPoolParams.accountToken[1].unTokenName)]: 1n,
153
+ [params.stabilityPoolParams.assetSymbol.unCurrencySymbol +
154
+ fromText(asset)]: amount,
155
+ },
156
+ )
157
+ .addSignerKey(pkh.hash);
158
+ }
159
+
160
+ static async closeAccount(
161
+ accountUtxo: UTxO,
162
+ params: SystemParams,
163
+ lucid: LucidEvolution,
164
+ ): Promise<TxBuilder> {
165
+ const [pkh, _] = await addrDetails(lucid);
166
+ const myAddress = await lucid.wallet().address();
167
+
168
+ const stabilityPoolScriptRef = await scriptRef(
169
+ params.scriptReferences.stabilityPoolValidatorRef,
170
+ lucid,
171
+ );
172
+
173
+ const request: AccountAction = {
174
+ Close: {
175
+ outputAddress: addressFromBech32(myAddress),
176
+ },
177
+ };
178
+ const oldAccountDatum: AccountContent = parseAccountDatum(
179
+ accountUtxo.datum,
180
+ );
181
+ const newAccountDatum: AccountContent = {
182
+ ...oldAccountDatum,
183
+ request,
184
+ };
185
+
186
+ const redeemer: StabilityPoolRedeemer = {
187
+ RequestAction: {
188
+ action: request,
189
+ },
190
+ };
191
+
192
+ return lucid
193
+ .newTx()
194
+ .readFrom([stabilityPoolScriptRef])
195
+ .collectFrom([accountUtxo], serialiseStabilityPoolRedeemer(redeemer))
196
+ .pay.ToContract(
197
+ credentialToAddress(lucid.config().network, {
198
+ hash: validatorToScriptHash(
199
+ mkStabilityPoolValidatorFromSP(params.stabilityPoolParams),
200
+ ),
201
+ type: 'Script',
202
+ }),
203
+ {
204
+ kind: 'inline',
205
+ value: serialiseStabilityPoolDatum({
206
+ Account: {
207
+ content: newAccountDatum,
208
+ },
209
+ }),
210
+ },
211
+ {
212
+ lovelace: BigInt(
213
+ params.stabilityPoolParams.requestCollateralLovelaces +
214
+ params.stabilityPoolParams.accountAdjustmentFeeLovelaces,
215
+ ),
216
+ [params.stabilityPoolParams.accountToken[0].unCurrencySymbol +
217
+ fromText(params.stabilityPoolParams.accountToken[1].unTokenName)]: 1n,
218
+ },
219
+ )
220
+ .addSignerKey(pkh.hash);
221
+ }
222
+
223
+ static async processRequest(
224
+ asset: string,
225
+ stabilityPoolUtxo: UTxO,
226
+ accountUtxo: UTxO,
227
+ govUtxo: UTxO,
228
+ iAssetUtxo: UTxO,
229
+ newSnapshotUtxo: UTxO | undefined,
230
+ params: SystemParams,
231
+ lucid: LucidEvolution,
232
+ ): Promise<TxBuilder> {
233
+ const redeemer: StabilityPoolRedeemer = {
234
+ ProcessRequest: {
235
+ requestRef: {
236
+ txHash: { hash: accountUtxo.txHash },
237
+ outputIndex: BigInt(accountUtxo.outputIndex),
238
+ },
239
+ },
240
+ };
241
+ const stabilityPoolScriptRef = await scriptRef(
242
+ params.scriptReferences.stabilityPoolValidatorRef,
243
+ lucid,
244
+ );
245
+
246
+ const accountDatum = parseAccountDatum(accountUtxo.datum);
247
+ const stabilityPoolDatum = parseStabilityPoolDatum(stabilityPoolUtxo.datum);
248
+
249
+ const tx = lucid
250
+ .newTx()
251
+ .collectFrom(
252
+ [stabilityPoolUtxo],
253
+ serialiseStabilityPoolRedeemer(redeemer),
254
+ )
255
+ .collectFrom([accountUtxo], serialiseStabilityPoolRedeemer(redeemer))
256
+ .readFrom([iAssetUtxo, govUtxo, stabilityPoolScriptRef]);
257
+
258
+ if (!accountDatum.request) throw new Error('Account Request is null');
259
+ if (accountDatum.request === 'Create') {
260
+ const accountTokenScriptRef = await scriptRef(
261
+ params.scriptReferences.authTokenPolicies.accountTokenRef,
262
+ lucid,
263
+ );
264
+ tx.readFrom([accountTokenScriptRef]);
265
+
266
+ const iassetUnit =
267
+ params.stabilityPoolParams.assetSymbol.unCurrencySymbol +
268
+ fromText(asset);
269
+ const reqAmount = accountUtxo.assets[iassetUnit] ?? 0n;
270
+
271
+ const newAccountSnapshot: StabilityPoolSnapshot = {
272
+ ...stabilityPoolDatum.snapshot,
273
+ depositVal: {
274
+ value: spAdd(accountDatum.snapshot.depositVal, mkSPInteger(reqAmount))
275
+ .value,
276
+ },
277
+ };
278
+
279
+ const newDeposit = spAdd(
280
+ stabilityPoolDatum.snapshot.depositVal,
281
+ mkSPInteger(reqAmount),
282
+ );
283
+ const newSum = spAdd(
284
+ stabilityPoolDatum.snapshot.sumVal,
285
+ spDiv(
286
+ spMul(
287
+ mkSPInteger(
288
+ BigInt(params.stabilityPoolParams.accountCreateFeeLovelaces),
289
+ ),
290
+ stabilityPoolDatum.snapshot.productVal,
291
+ ),
292
+ newDeposit,
293
+ ),
294
+ );
295
+ const newStabilityPoolSnapshot: StabilityPoolSnapshot = {
296
+ ...stabilityPoolDatum.snapshot,
297
+ depositVal: newDeposit,
298
+ sumVal: newSum,
299
+ };
300
+
301
+ const newEpochToScaleToSum: EpochToScaleToSum = new Map(
302
+ stabilityPoolDatum.epochToScaleToSum,
303
+ );
304
+ newEpochToScaleToSum.set(
305
+ {
306
+ epoch: stabilityPoolDatum.snapshot.epoch,
307
+ scale: stabilityPoolDatum.snapshot.scale,
308
+ },
309
+ newSum,
310
+ );
311
+
312
+ const stabilityPoolAssetToken =
313
+ stabilityPoolUtxo.assets[iassetUnit] ?? 0n;
314
+ const poolOutputValue = {
315
+ lovelace:
316
+ stabilityPoolUtxo.assets.lovelace +
317
+ BigInt(params.stabilityPoolParams.accountCreateFeeLovelaces),
318
+ [params.stabilityPoolParams.stabilityPoolToken[0].unCurrencySymbol +
319
+ fromText(params.stabilityPoolParams.stabilityPoolToken[1].unTokenName)]:
320
+ 1n,
321
+ [params.stabilityPoolParams.assetSymbol.unCurrencySymbol +
322
+ fromText(asset)]: stabilityPoolAssetToken + reqAmount,
323
+ };
324
+
325
+ tx.mintAssets(
326
+ {
327
+ [params.stabilityPoolParams.accountToken[0].unCurrencySymbol +
328
+ fromText(params.stabilityPoolParams.accountToken[1].unTokenName)]: 1n,
329
+ },
330
+ Data.to(new Constr(0, [])),
331
+ );
332
+
333
+ tx.pay.ToContract(
334
+ stabilityPoolUtxo.address,
335
+ {
336
+ kind: 'inline',
337
+ value: serialiseStabilityPoolDatum({
338
+ StabilityPool: {
339
+ content: {
340
+ ...stabilityPoolDatum,
341
+ snapshot: newStabilityPoolSnapshot,
342
+ epochToScaleToSum: newEpochToScaleToSum,
343
+ },
344
+ },
345
+ }),
346
+ },
347
+ poolOutputValue,
348
+ );
349
+
350
+ tx.pay.ToContract(
351
+ stabilityPoolUtxo.address,
352
+ {
353
+ kind: 'inline',
354
+ value: serialiseStabilityPoolDatum({
355
+ Account: {
356
+ content: {
357
+ ...accountDatum,
358
+ snapshot: newAccountSnapshot,
359
+ request: null,
360
+ },
361
+ },
362
+ }),
363
+ },
364
+ {
365
+ lovelace:
366
+ accountUtxo.assets.lovelace -
367
+ BigInt(params.stabilityPoolParams.accountCreateFeeLovelaces),
368
+ [params.stabilityPoolParams.accountToken[0].unCurrencySymbol +
369
+ fromText(params.stabilityPoolParams.accountToken[1].unTokenName)]: 1n,
370
+ },
371
+ );
372
+ } else if ('Adjust' in accountDatum.request) {
373
+ const amount = accountDatum.request.Adjust.amount;
374
+ const outputAddress = addressToBech32(
375
+ lucid,
376
+ accountDatum.request.Adjust.outputAddress,
377
+ );
378
+ const myAddress = await lucid.wallet().address();
379
+
380
+ const [updatedAccountSnapshot, reward, refInputs] = adjustmentHelper(
381
+ stabilityPoolUtxo,
382
+ newSnapshotUtxo,
383
+ stabilityPoolDatum.snapshot,
384
+ stabilityPoolDatum.epochToScaleToSum,
385
+ accountDatum.snapshot,
386
+ );
387
+
388
+ const govDatum: GovDatum = parseGovDatum(govUtxo.datum);
389
+ const iassetDatum: IAssetContent = parseIAssetDatum(iAssetUtxo.datum);
390
+ const rewardLovelacesFee = calculateFeeFromPercentage(
391
+ govDatum.protocolParams.collateralFeePercentage,
392
+ reward,
393
+ );
394
+ const isDepositOrRewardWithdrawal: boolean = amount > 0n;
395
+ const bigIntMax = (...args: bigint[]): bigint =>
396
+ args.reduce((m, e) => (e > m ? e : m));
397
+ const balanceChange: bigint = isDepositOrRewardWithdrawal
398
+ ? amount
399
+ : bigIntMax(amount, fromSPInteger(accountDatum.snapshot.depositVal));
400
+ const newAccountSnapshot: StabilityPoolSnapshot = {
401
+ ...updatedAccountSnapshot,
402
+ depositVal: spAdd(
403
+ updatedAccountSnapshot.depositVal,
404
+ mkSPInteger(balanceChange),
405
+ ),
406
+ };
407
+
408
+ const _newPoolDepositExcludingFee = spAdd(
409
+ stabilityPoolDatum.snapshot.depositVal,
410
+ mkSPInteger(balanceChange),
411
+ );
412
+ const newPoolDepositExcludingFee =
413
+ _newPoolDepositExcludingFee.value > 0n
414
+ ? _newPoolDepositExcludingFee
415
+ : mkSPInteger(0n);
416
+
417
+ const withdrawalFee =
418
+ isDepositOrRewardWithdrawal || newPoolDepositExcludingFee.value === 0n
419
+ ? 0n
420
+ : calculateFeeFromPercentage(
421
+ iassetDatum.stabilityPoolWithdrawalFeePercentage,
422
+ -balanceChange,
423
+ );
424
+ const newPoolDeposit = spAdd(
425
+ newPoolDepositExcludingFee,
426
+ mkSPInteger(withdrawalFee),
427
+ );
428
+ const newPoolProduct =
429
+ withdrawalFee === 0n
430
+ ? stabilityPoolDatum.snapshot.productVal
431
+ : spMul(
432
+ stabilityPoolDatum.snapshot.productVal,
433
+ spAdd(
434
+ mkSPInteger(1n),
435
+ spDiv(mkSPInteger(withdrawalFee), newPoolDepositExcludingFee),
436
+ ),
437
+ );
438
+ const newPoolSum = spAdd(
439
+ stabilityPoolDatum.snapshot.sumVal,
440
+ spDiv(
441
+ spMul(
442
+ mkSPInteger(
443
+ BigInt(params.stabilityPoolParams.accountAdjustmentFeeLovelaces),
444
+ ),
445
+ newPoolProduct,
446
+ ),
447
+ newPoolDeposit,
448
+ ),
449
+ );
450
+ const newPoolSnapshot: StabilityPoolSnapshot = {
451
+ ...stabilityPoolDatum.snapshot,
452
+ depositVal: newPoolDeposit,
453
+ sumVal: newPoolSum,
454
+ productVal: newPoolProduct,
455
+ };
456
+ const newEpochToScaleToSum: EpochToScaleToSum = setSumInEpochToScaleToSum(
457
+ stabilityPoolDatum.epochToScaleToSum,
458
+ stabilityPoolDatum.snapshot.epoch,
459
+ stabilityPoolDatum.snapshot.scale,
460
+ newPoolSum,
461
+ );
462
+
463
+ await CollectorContract.feeTx(rewardLovelacesFee, lucid, params, tx);
464
+
465
+ tx.readFrom([govUtxo, iAssetUtxo, ...refInputs]);
466
+
467
+ tx.pay.ToContract(
468
+ stabilityPoolUtxo.address,
469
+ {
470
+ kind: 'inline',
471
+ value: serialiseStabilityPoolDatum({
472
+ StabilityPool: {
473
+ content: {
474
+ ...stabilityPoolDatum,
475
+ snapshot: newPoolSnapshot,
476
+ epochToScaleToSum: newEpochToScaleToSum,
477
+ },
478
+ },
479
+ }),
480
+ },
481
+ {
482
+ lovelace:
483
+ stabilityPoolUtxo.assets.lovelace +
484
+ BigInt(params.stabilityPoolParams.accountAdjustmentFeeLovelaces) -
485
+ reward,
486
+ [params.stabilityPoolParams.stabilityPoolToken[0].unCurrencySymbol +
487
+ fromText(
488
+ params.stabilityPoolParams.stabilityPoolToken[1].unTokenName,
489
+ )]: 1n,
490
+ [params.stabilityPoolParams.assetSymbol.unCurrencySymbol +
491
+ fromText(asset)]:
492
+ stabilityPoolUtxo.assets[
493
+ params.stabilityPoolParams.assetSymbol.unCurrencySymbol +
494
+ fromText(asset)
495
+ ] +
496
+ balanceChange +
497
+ withdrawalFee,
498
+ },
499
+ );
500
+
501
+ tx.pay.ToContract(
502
+ stabilityPoolUtxo.address,
503
+ {
504
+ kind: 'inline',
505
+ value: serialiseStabilityPoolDatum({
506
+ Account: {
507
+ content: {
508
+ ...accountDatum,
509
+ snapshot: newAccountSnapshot,
510
+ request: null,
511
+ },
512
+ },
513
+ }),
514
+ },
515
+ {
516
+ lovelace:
517
+ accountUtxo.assets.lovelace -
518
+ BigInt(params.stabilityPoolParams.accountAdjustmentFeeLovelaces) -
519
+ 2_000_000n,
520
+ [params.stabilityPoolParams.accountToken[0].unCurrencySymbol +
521
+ fromText(params.stabilityPoolParams.accountToken[1].unTokenName)]: 1n,
522
+ },
523
+ );
524
+
525
+ if (myAddress !== outputAddress) {
526
+ tx.pay.ToAddressWithData(
527
+ outputAddress,
528
+ {
529
+ kind: 'inline',
530
+ value: Data.to(
531
+ {
532
+ IndigoStabilityPoolAccountAdjustment: {
533
+ spent_account: {
534
+ txHash: { hash: accountUtxo.txHash },
535
+ outputIndex: BigInt(accountUtxo.outputIndex),
536
+ },
537
+ },
538
+ },
539
+ ActionReturnDatum,
540
+ ),
541
+ },
542
+ {
543
+ lovelace: reward - rewardLovelacesFee + 2_000_000n,
544
+ ...(amount < 0n
545
+ ? {
546
+ [params.stabilityPoolParams.assetSymbol.unCurrencySymbol +
547
+ fromText(asset)]: -(amount - withdrawalFee),
548
+ }
549
+ : {}),
550
+ },
551
+ );
552
+ } else {
553
+ // TODO: User is self-handling the process request, so we will need to handle the change datum
554
+ }
555
+ } else if ('Close' in accountDatum.request) {
556
+ const outputAddress = addressToBech32(
557
+ lucid,
558
+ accountDatum.request.Close.outputAddress,
559
+ );
560
+ const myAddress = await lucid.wallet().address();
561
+
562
+ const [updatedAccountSnapshot, reward, refInputs] = adjustmentHelper(
563
+ stabilityPoolUtxo,
564
+ newSnapshotUtxo,
565
+ stabilityPoolDatum.snapshot,
566
+ stabilityPoolDatum.epochToScaleToSum,
567
+ accountDatum.snapshot,
568
+ );
569
+
570
+ const govDatum: GovDatum = parseGovDatum(govUtxo.datum);
571
+ const iassetDatum: IAssetContent = parseIAssetDatum(iAssetUtxo.datum);
572
+ const rewardLovelacesFee = calculateFeeFromPercentage(
573
+ govDatum.protocolParams.collateralFeePercentage,
574
+ reward,
575
+ );
576
+
577
+ const fund = updatedAccountSnapshot.depositVal;
578
+ const newPoolDepositExcludingFee = spSub(
579
+ stabilityPoolDatum.snapshot.depositVal,
580
+ fund,
581
+ );
582
+ const withdrawnAmt = fund.value < 0n ? mkSPInteger(0n) : fund;
583
+ const withdrawalFeeAmount =
584
+ newPoolDepositExcludingFee.value === 0n
585
+ ? 0n
586
+ : calculateFeeFromPercentage(
587
+ iassetDatum.stabilityPoolWithdrawalFeePercentage,
588
+ withdrawnAmt.value,
589
+ );
590
+
591
+ const [newPoolDeposit, newPoolProduct] = updatePoolSnapshotWithdrawalFee(
592
+ mkSPInteger(withdrawalFeeAmount),
593
+ newPoolDepositExcludingFee,
594
+ stabilityPoolDatum.snapshot,
595
+ );
596
+ const newPoolSnapshot: StabilityPoolSnapshot = {
597
+ ...stabilityPoolDatum.snapshot,
598
+ depositVal: newPoolDeposit,
599
+ productVal: newPoolProduct,
600
+ };
601
+
602
+ const accountTokenRef = await scriptRef(
603
+ params.scriptReferences.authTokenPolicies.accountTokenRef,
604
+ lucid,
605
+ );
606
+
607
+ await CollectorContract.feeTx(rewardLovelacesFee, lucid, params, tx);
608
+
609
+ tx.readFrom([govUtxo, iAssetUtxo, accountTokenRef, ...refInputs]);
610
+
611
+ tx.mintAssets(
612
+ {
613
+ [params.stabilityPoolParams.accountToken[0].unCurrencySymbol +
614
+ fromText(params.stabilityPoolParams.accountToken[1].unTokenName)]:
615
+ -1n,
616
+ },
617
+ Data.to(new Constr(0, [])),
618
+ );
619
+
620
+ const assetOutputAmountForSP =
621
+ stabilityPoolUtxo.assets[
622
+ params.stabilityPoolParams.assetSymbol.unCurrencySymbol +
623
+ fromText(asset)
624
+ ] -
625
+ fromSPInteger(withdrawnAmt) -
626
+ withdrawalFeeAmount;
627
+
628
+ tx.pay.ToContract(
629
+ stabilityPoolUtxo.address,
630
+ {
631
+ kind: 'inline',
632
+ value: serialiseStabilityPoolDatum({
633
+ StabilityPool: {
634
+ content: {
635
+ ...stabilityPoolDatum,
636
+ snapshot: newPoolSnapshot,
637
+ },
638
+ },
639
+ }),
640
+ },
641
+ {
642
+ lovelace: stabilityPoolUtxo.assets.lovelace - reward,
643
+ [params.stabilityPoolParams.stabilityPoolToken[0].unCurrencySymbol +
644
+ fromText(
645
+ params.stabilityPoolParams.stabilityPoolToken[1].unTokenName,
646
+ )]: 1n,
647
+ ...(assetOutputAmountForSP > 0n
648
+ ? {
649
+ [params.stabilityPoolParams.assetSymbol.unCurrencySymbol +
650
+ fromText(asset)]: assetOutputAmountForSP,
651
+ }
652
+ : {}),
653
+ },
654
+ );
655
+
656
+ if (myAddress !== outputAddress) {
657
+ tx.pay.ToAddressWithData(
658
+ outputAddress,
659
+ {
660
+ kind: 'inline',
661
+ value: Data.to(
662
+ {
663
+ IndigoStabilityPoolAccountClosure: {
664
+ closed_account: {
665
+ txHash: { hash: accountUtxo.txHash },
666
+ outputIndex: BigInt(accountUtxo.outputIndex),
667
+ },
668
+ },
669
+ },
670
+ ActionReturnDatum,
671
+ ),
672
+ },
673
+ {
674
+ lovelace: accountUtxo.assets.lovelace + reward - rewardLovelacesFee,
675
+ [params.stabilityPoolParams.assetSymbol.unCurrencySymbol +
676
+ fromText(asset)]: fromSPInteger(withdrawnAmt) - withdrawalFeeAmount,
677
+ },
678
+ );
679
+ }
680
+ }
681
+
682
+ return tx;
683
+ }
684
+ }