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