@indigo-labs/indigo-sdk 0.1.19 → 0.1.21

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