@indigo-labs/indigo-sdk 0.2.41 → 0.3.0

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 (201) hide show
  1. package/.github/workflows/ci.yml +4 -2
  2. package/dist/index.d.mts +3008 -2194
  3. package/dist/index.d.ts +3008 -2194
  4. package/dist/index.js +9827 -6194
  5. package/dist/index.mjs +8591 -4809
  6. package/package.json +14 -3
  7. package/src/contracts/cdp/helpers.ts +68 -72
  8. package/src/contracts/cdp/scripts.ts +50 -13
  9. package/src/contracts/cdp/transactions.ts +831 -545
  10. package/src/contracts/cdp/types-new.ts +256 -0
  11. package/src/contracts/cdp/types.ts +26 -144
  12. package/src/contracts/cdp-creator/scripts.ts +15 -9
  13. package/src/contracts/cdp-creator/types-new.ts +50 -0
  14. package/src/contracts/cdp-creator/types.ts +5 -31
  15. package/src/contracts/collector/scripts.ts +1 -1
  16. package/src/contracts/collector/transactions.ts +23 -13
  17. package/src/contracts/collector/types-new.ts +17 -0
  18. package/src/contracts/execute/scripts.ts +19 -10
  19. package/src/contracts/execute/types-new.ts +44 -0
  20. package/src/contracts/execute/types.ts +5 -38
  21. package/src/contracts/gov/helpers.ts +187 -51
  22. package/src/contracts/gov/scripts.ts +17 -10
  23. package/src/contracts/gov/transactions.ts +599 -271
  24. package/src/contracts/gov/types-new.ts +253 -100
  25. package/src/contracts/gov/types.ts +4 -71
  26. package/src/contracts/iasset/helpers.ts +172 -0
  27. package/src/contracts/iasset/scripts.ts +38 -0
  28. package/src/contracts/iasset/types.ts +154 -0
  29. package/src/contracts/initialize/actions.ts +768 -0
  30. package/src/contracts/initialize/helpers.ts +611 -36
  31. package/src/contracts/initialize/types.ts +102 -28
  32. package/src/contracts/interest-collection/helpers.ts +19 -0
  33. package/src/contracts/interest-collection/scripts.ts +44 -0
  34. package/src/contracts/interest-collection/transactions.ts +436 -0
  35. package/src/contracts/interest-collection/types-new.ts +50 -0
  36. package/src/contracts/interest-collection/types.ts +26 -0
  37. package/src/contracts/interest-oracle/helpers.ts +2 -30
  38. package/src/contracts/interest-oracle/scripts.ts +1 -1
  39. package/src/contracts/interest-oracle/transactions.ts +21 -16
  40. package/src/contracts/interest-oracle/types-new.ts +32 -0
  41. package/src/contracts/interest-oracle/types.ts +1 -40
  42. package/src/contracts/one-shot/transactions.ts +1 -2
  43. package/src/contracts/poll/helpers.ts +5 -23
  44. package/src/contracts/poll/scripts.ts +12 -13
  45. package/src/contracts/poll/types-poll-manager.ts +1 -19
  46. package/src/contracts/poll/types-poll-new.ts +170 -0
  47. package/src/contracts/poll/types-poll-shard.ts +2 -24
  48. package/src/contracts/price-oracle/helpers.ts +1 -4
  49. package/src/contracts/price-oracle/scripts.ts +3 -8
  50. package/src/contracts/price-oracle/transactions.ts +32 -25
  51. package/src/contracts/price-oracle/types-new.ts +50 -0
  52. package/src/contracts/price-oracle/types.ts +2 -36
  53. package/src/contracts/pyth-feed/helpers.ts +58 -0
  54. package/src/contracts/pyth-feed/scripts.ts +15 -0
  55. package/src/contracts/pyth-feed/types.ts +181 -0
  56. package/src/contracts/rob/helpers.ts +405 -0
  57. package/src/contracts/rob/scripts.ts +35 -0
  58. package/src/contracts/rob/transactions.ts +410 -0
  59. package/src/contracts/rob/types-new.ts +128 -0
  60. package/src/contracts/rob/types.ts +16 -0
  61. package/src/contracts/rob-leverage/helpers.ts +424 -0
  62. package/src/contracts/{leverage → rob-leverage}/transactions.ts +68 -48
  63. package/src/contracts/stability-pool/helpers.ts +714 -230
  64. package/src/contracts/stability-pool/scripts.ts +20 -15
  65. package/src/contracts/stability-pool/transactions.ts +625 -495
  66. package/src/contracts/stability-pool/types-new.ts +237 -100
  67. package/src/contracts/stability-pool/types.ts +5 -22
  68. package/src/contracts/stableswap/helpers.ts +22 -0
  69. package/src/contracts/stableswap/scripts.ts +37 -0
  70. package/src/contracts/stableswap/transactions.ts +647 -0
  71. package/src/contracts/stableswap/types-new.ts +131 -0
  72. package/src/contracts/stableswap/types.ts +17 -0
  73. package/src/contracts/staking/helpers.ts +49 -34
  74. package/src/contracts/staking/scripts.ts +1 -1
  75. package/src/contracts/staking/transactions.ts +85 -130
  76. package/src/contracts/staking/types-new.ts +60 -28
  77. package/src/contracts/staking/types.ts +1 -28
  78. package/src/contracts/treasury/helpers.ts +21 -0
  79. package/src/contracts/treasury/scripts.ts +16 -26
  80. package/src/contracts/treasury/transactions.ts +256 -27
  81. package/src/contracts/treasury/types-new.ts +69 -0
  82. package/src/contracts/treasury/types.ts +2 -43
  83. package/src/contracts/version-registry/scripts.ts +2 -2
  84. package/src/contracts/version-registry/types-new.ts +6 -7
  85. package/src/index.ts +37 -20
  86. package/src/scripts/auth-token-policy.ts +3 -2
  87. package/src/scripts/iasset-policy.ts +3 -2
  88. package/src/types/evolution-schema-options.ts +3 -3
  89. package/src/types/generic.ts +17 -89
  90. package/src/types/multisig.ts +48 -0
  91. package/src/types/on-chain-decimal.ts +14 -7
  92. package/src/types/rational.ts +61 -0
  93. package/src/types/system-params.ts +237 -41
  94. package/src/utils/array-utils.ts +70 -1
  95. package/src/utils/bigint-utils.ts +12 -0
  96. package/src/utils/indigo-helpers.ts +8 -10
  97. package/src/utils/lucid-utils.ts +47 -40
  98. package/src/utils/oracle-helpers.ts +62 -0
  99. package/src/utils/pyth/decode.ts +223 -0
  100. package/src/utils/pyth/encode.ts +262 -0
  101. package/src/utils/pyth/index.ts +14 -0
  102. package/src/utils/pyth/types.ts +87 -0
  103. package/src/validators/always-succeed-validator.ts +6 -0
  104. package/src/validators/cdp-creator-validator.ts +2 -2
  105. package/src/validators/cdp-redeem-validator.ts +7 -0
  106. package/src/validators/cdp-validator.ts +2 -2
  107. package/src/validators/collector-validator.ts +2 -2
  108. package/src/validators/execute-validator.ts +2 -2
  109. package/src/validators/governance-validator.ts +2 -2
  110. package/src/validators/iasset-validator.ts +7 -0
  111. package/src/validators/interest-collection-validator.ts +7 -0
  112. package/src/validators/interest-oracle-validator.ts +2 -2
  113. package/src/validators/poll-manager-validator.ts +2 -2
  114. package/src/validators/poll-shard-validator.ts +2 -2
  115. package/src/validators/price-oracle-validator.ts +7 -0
  116. package/src/validators/pyth-feed-validator.ts +7 -0
  117. package/src/validators/rob-validator.ts +7 -0
  118. package/src/validators/stability-pool-validator.ts +2 -2
  119. package/src/validators/stableswap-validator.ts +7 -0
  120. package/src/validators/staking-validator.ts +2 -2
  121. package/src/validators/treasury-validator.ts +2 -2
  122. package/src/validators/version-record-policy.ts +2 -2
  123. package/src/validators/version-registry-validator.ts +2 -2
  124. package/tests/always-succeed/script.ts +7 -0
  125. package/tests/bigint-utils.test.ts +41 -0
  126. package/tests/cdp/actions.ts +611 -0
  127. package/tests/cdp/cdp-helpers.ts +55 -0
  128. package/tests/cdp/cdp-queries.ts +440 -0
  129. package/tests/cdp/cdp.test.ts +6087 -0
  130. package/tests/cdp/transactions-mutated.ts +1729 -0
  131. package/tests/data/system-params.json +177 -34
  132. package/tests/datums.test.ts +209 -210
  133. package/tests/endpoints/initialize.ts +68 -0
  134. package/tests/endpoints/interest-collector.ts +37 -0
  135. package/tests/endpoints/treasury.ts +70 -0
  136. package/tests/gov/actions.ts +406 -0
  137. package/tests/gov/gov.test.ts +4450 -0
  138. package/tests/{queries → gov}/governance-queries.ts +6 -3
  139. package/tests/hash-checks.test.ts +38 -11
  140. package/tests/indigo-test-helpers.ts +100 -0
  141. package/tests/initialize.test.ts +61 -9
  142. package/tests/interest-collection/interest-collection.test.ts +892 -0
  143. package/tests/interest-collection/interest-collector-queries.ts +49 -0
  144. package/tests/interest-collection/transactions-mutated.ts +260 -0
  145. package/tests/interest-oracle.test.ts +43 -35
  146. package/tests/mock/assets-mock.ts +234 -23
  147. package/tests/mock/protocol-params-mock.ts +21 -0
  148. package/tests/price-oracle/actions.ts +163 -0
  149. package/tests/price-oracle/price-oracle-queries.ts +12 -0
  150. package/tests/price-oracle/price-oracle.test.ts +240 -0
  151. package/tests/price-oracle/transactions-mutated.ts +62 -0
  152. package/tests/pyth/endpoints.ts +96 -0
  153. package/tests/pyth/helpers.ts +37 -0
  154. package/tests/pyth/pyth-encoding.test.ts +376 -0
  155. package/tests/pyth/pyth-indigo.test.ts +509 -0
  156. package/tests/pyth/pyth.test.ts +300 -0
  157. package/tests/queries/execute-queries.ts +6 -5
  158. package/tests/queries/iasset-queries.ts +175 -5
  159. package/tests/queries/interest-oracle-queries.ts +4 -2
  160. package/tests/queries/poll-queries.ts +8 -9
  161. package/tests/queries/stability-pool-queries.ts +95 -48
  162. package/tests/queries/staking-queries.ts +4 -2
  163. package/tests/queries/treasury-queries.ts +80 -5
  164. package/tests/rob/actions.ts +58 -0
  165. package/tests/{lrp-leverage.test.ts → rob/rob-leverage.test.ts} +393 -296
  166. package/tests/rob/rob-queries.ts +95 -0
  167. package/tests/rob/rob.test.ts +3762 -0
  168. package/tests/rob/transactions-mutated.ts +853 -0
  169. package/tests/script-size.test.ts +240 -0
  170. package/tests/setup.ts +135 -0
  171. package/tests/stability-pool/actions.ts +210 -0
  172. package/tests/stability-pool.test.ts +5469 -666
  173. package/tests/stableswap/stableswap-actions.ts +84 -0
  174. package/tests/stableswap/stableswap-queries.ts +89 -0
  175. package/tests/stableswap/stableswap.test.ts +3891 -0
  176. package/tests/stableswap/transactions-mutated.ts +348 -0
  177. package/tests/staking.test.ts +82 -99
  178. package/tests/test-helpers.ts +58 -11
  179. package/tests/treasury.test.ts +242 -0
  180. package/tests/utils/asserts.ts +74 -0
  181. package/tests/utils/benchmark-utils.ts +81 -0
  182. package/tests/utils/index.ts +122 -4
  183. package/tsconfig.json +9 -1
  184. package/vitest.config.ts +3 -1
  185. package/src/contracts/collector/types.ts +0 -16
  186. package/src/contracts/initialize/transactions.ts +0 -891
  187. package/src/contracts/leverage/helpers.ts +0 -424
  188. package/src/contracts/lrp/helpers.ts +0 -294
  189. package/src/contracts/lrp/scripts.ts +0 -27
  190. package/src/contracts/lrp/transactions.ts +0 -250
  191. package/src/contracts/lrp/types.ts +0 -131
  192. package/src/contracts/poll/types-poll.ts +0 -88
  193. package/src/contracts/vesting/helpers.ts +0 -218
  194. package/src/utils/value-helpers.ts +0 -37
  195. package/src/validators/lrp-validator.ts +0 -7
  196. package/tests/cdp.test.ts +0 -1528
  197. package/tests/gov.test.ts +0 -2011
  198. package/tests/lrp.test.ts +0 -673
  199. package/tests/queries/cdp-queries.ts +0 -220
  200. package/tests/queries/lrp-queries.ts +0 -76
  201. package/tests/queries/price-oracle-queries.ts +0 -10
@@ -1,5 +1,4 @@
1
1
  import {
2
- Constr,
3
2
  fromText,
4
3
  LucidEvolution,
5
4
  TxBuilder,
@@ -9,70 +8,83 @@ import {
9
8
  credentialToAddress,
10
9
  fromHex,
11
10
  toHex,
11
+ addAssets,
12
+ OutRef,
13
+ slotToUnixTime,
12
14
  } from '@lucid-evolution/lucid';
13
- import { ActionReturnDatum } from './types';
14
- import { fromSystemParamsAsset, SystemParams } from '../../types/system-params';
15
15
  import {
16
- addrDetails,
17
- getInlineDatumOrThrow,
18
- scriptRef,
19
- UtxoOrOutRef,
20
- } from '../../utils/lucid-utils';
16
+ fromSystemParamsAsset,
17
+ fromSystemParamsScriptRef,
18
+ SystemParams,
19
+ } from '../../types/system-params';
20
+ import { addrDetails, getInlineDatumOrThrow } from '../../utils/lucid-utils';
21
21
  import { mkStabilityPoolValidatorFromSP } from './scripts';
22
22
  import {
23
- adjustmentHelper,
24
- setSumInEpochToScaleToSum,
25
- updatePoolSnapshotWithdrawalFee,
23
+ BASE_MAX_TX_FEE,
24
+ createProcessRequestAccountRedeemer,
25
+ findRelevantE2s2sIdxs,
26
+ initSpState,
27
+ liquidationHelper,
28
+ mkStabilityPoolAddr,
29
+ partitionEpochToScaleToSums,
30
+ updateAccount,
31
+ updatePoolStateWhenWithdrawalFee,
26
32
  } 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';
33
+ import { calculateFeeFromRatio } from '../../utils/indigo-helpers';
34
34
  import {
35
35
  AccountAction,
36
36
  AccountContent,
37
- EpochToScaleToSum,
38
37
  fromSPInteger,
39
38
  mkSPInteger,
40
- parseAccountDatum,
41
- parseStabilityPoolDatum,
39
+ parseAccountDatumOrThrow,
40
+ parseStabilityPoolDatumOrThrow,
41
+ serialiseActionReturnDatum,
42
42
  serialiseStabilityPoolDatum,
43
43
  serialiseStabilityPoolRedeemer,
44
44
  spAdd,
45
- spDiv,
46
- spMul,
47
45
  spSub,
48
- StabilityPoolRedeemer,
49
- StabilityPoolSnapshot,
46
+ spZeroNegatives,
50
47
  } from './types-new';
51
- import { collectorFeeTx } from '../collector/transactions';
52
- import { mkAssetsOf } from '../../utils/value-helpers';
48
+ import {
49
+ adaAssetClass,
50
+ addressFromBech32,
51
+ addressToBech32,
52
+ AssetClass,
53
+ assetClassValueOf,
54
+ estimateUtxoMinLovelace,
55
+ lovelacesAmt,
56
+ matchSingle,
57
+ mkAssetsOf,
58
+ mkLovelacesOf,
59
+ negateAssets,
60
+ } from '@3rd-eye-labs/cardano-offchain-common';
61
+ import { parseIAssetDatumOrThrow } from '../iasset/types';
62
+ import { match, P } from 'ts-pattern';
63
+ import { bigintMax, zeroNegatives } from '../../utils/bigint-utils';
53
64
 
54
65
  export async function createSpAccount(
55
- asset: string,
66
+ assetAscii: string,
56
67
  amount: bigint,
57
- params: SystemParams,
68
+ sysParams: SystemParams,
58
69
  lucid: LucidEvolution,
59
70
  ): Promise<TxBuilder> {
60
71
  const [pkh, _skh] = await addrDetails(lucid);
61
- const minLovelaces = BigInt(
62
- params.stabilityPoolParams.accountCreateFeeLovelaces +
63
- params.stabilityPoolParams.requestCollateralLovelaces,
64
- );
72
+
73
+ const iasset = fromHex(fromText(assetAscii));
74
+ const iassetAssetClass = {
75
+ currencySymbol: fromHex(
76
+ sysParams.stabilityPoolParams.assetSymbol.unCurrencySymbol,
77
+ ),
78
+ tokenName: iasset,
79
+ };
80
+
65
81
  const datum: AccountContent = {
66
82
  owner: fromHex(pkh.hash),
67
- asset: fromHex(fromText(asset)),
68
- accountSnapshot: {
69
- productVal: { value: 0n },
70
- depositVal: { value: 0n },
71
- sumVal: { value: 0n },
72
- epoch: 0n,
73
- scale: 0n,
74
- },
83
+ iasset: iasset,
84
+ state: initSpState,
85
+ assetSums: [],
75
86
  request: 'Create',
87
+ lastRequestProcessingTime: 0n,
76
88
  };
77
89
 
78
90
  return lucid
@@ -80,7 +92,7 @@ export async function createSpAccount(
80
92
  .pay.ToContract(
81
93
  credentialToAddress(lucid.config().network!, {
82
94
  hash: validatorToScriptHash(
83
- mkStabilityPoolValidatorFromSP(params.stabilityPoolParams),
95
+ mkStabilityPoolValidatorFromSP(sysParams.stabilityPoolParams),
84
96
  ),
85
97
  type: 'Script',
86
98
  }),
@@ -88,30 +100,35 @@ export async function createSpAccount(
88
100
  kind: 'inline',
89
101
  value: serialiseStabilityPoolDatum({ Account: datum }),
90
102
  },
91
- {
92
- lovelace: minLovelaces,
93
- [params.stabilityPoolParams.assetSymbol.unCurrencySymbol +
94
- fromText(asset)]: amount,
95
- },
103
+ addAssets(
104
+ mkAssetsOf(iassetAssetClass, amount),
105
+ mkLovelacesOf(
106
+ // TODO: Calculate a more accurate amount to just cover costs.
107
+ 5_000_000n,
108
+ ),
109
+ ),
96
110
  )
97
111
  .addSignerKey(pkh.hash);
98
112
  }
99
113
 
100
114
  export async function adjustSpAccount(
101
- asset: string,
102
115
  amount: bigint,
103
116
  accountUtxo: UTxO,
104
- params: SystemParams,
117
+ sysParams: SystemParams,
105
118
  lucid: LucidEvolution,
106
119
  ): Promise<TxBuilder> {
107
120
  const myAddress = await lucid.wallet().address();
108
121
 
109
- const stabilityPoolScriptRef = await scriptRef(
110
- params.scriptReferences.stabilityPoolValidatorRef,
111
- lucid,
122
+ const stabilityPoolScriptRef = matchSingle(
123
+ await lucid.utxosByOutRef([
124
+ fromSystemParamsScriptRef(
125
+ sysParams.scriptReferences.stabilityPoolValidatorRef,
126
+ ),
127
+ ]),
128
+ (_) => new Error('Expected a single stability pool Ref Script UTXO'),
112
129
  );
113
130
 
114
- const oldAccountDatum: AccountContent = parseAccountDatum(
131
+ const oldAccountDatum: AccountContent = parseAccountDatumOrThrow(
115
132
  getInlineDatumOrThrow(accountUtxo),
116
133
  );
117
134
 
@@ -125,21 +142,6 @@ export async function adjustSpAccount(
125
142
  },
126
143
  };
127
144
 
128
- const value = {
129
- lovelace: BigInt(
130
- params.stabilityPoolParams.requestCollateralLovelaces +
131
- params.stabilityPoolParams.accountAdjustmentFeeLovelaces,
132
- ),
133
- [params.stabilityPoolParams.accountToken[0].unCurrencySymbol +
134
- fromText(params.stabilityPoolParams.accountToken[1].unTokenName)]: 1n,
135
- };
136
-
137
- if (amount > 0n) {
138
- value[
139
- params.stabilityPoolParams.assetSymbol.unCurrencySymbol + fromText(asset)
140
- ] = amount;
141
- }
142
-
143
145
  return lucid
144
146
  .newTx()
145
147
  .readFrom([stabilityPoolScriptRef])
@@ -155,41 +157,62 @@ export async function adjustSpAccount(
155
157
  }),
156
158
  )
157
159
  .pay.ToContract(
158
- credentialToAddress(lucid.config().network!, {
159
- hash: validatorToScriptHash(
160
- mkStabilityPoolValidatorFromSP(params.stabilityPoolParams),
161
- ),
162
- type: 'Script',
163
- }),
160
+ accountUtxo.address,
164
161
  {
165
162
  kind: 'inline',
166
163
  value: serialiseStabilityPoolDatum({
167
164
  Account: newAccountDatum,
168
165
  }),
169
166
  },
170
- value,
167
+ addAssets(
168
+ mkLovelacesOf(
169
+ // TODO: Calculate a more accurate amount to just cover costs.
170
+ 7_000_000n,
171
+ ),
172
+ mkAssetsOf(
173
+ fromSystemParamsAsset(sysParams.stabilityPoolParams.accountToken),
174
+ 1n,
175
+ ),
176
+ amount > 0n
177
+ ? mkAssetsOf(
178
+ {
179
+ currencySymbol: fromHex(
180
+ sysParams.stabilityPoolParams.assetSymbol.unCurrencySymbol,
181
+ ),
182
+ tokenName: oldAccountDatum.iasset,
183
+ },
184
+ amount,
185
+ )
186
+ : {},
187
+ ),
171
188
  )
172
189
  .addSignerKey(toHex(oldAccountDatum.owner));
173
190
  }
174
191
 
175
192
  export async function closeSpAccount(
176
193
  accountUtxo: UTxO,
177
- params: SystemParams,
194
+ sysParams: SystemParams,
178
195
  lucid: LucidEvolution,
196
+ maxTxFee: bigint = BASE_MAX_TX_FEE,
179
197
  ): Promise<TxBuilder> {
180
198
  const myAddress = await lucid.wallet().address();
181
199
 
182
- const stabilityPoolScriptRef = await scriptRef(
183
- params.scriptReferences.stabilityPoolValidatorRef,
184
- lucid,
200
+ const stabilityPoolScriptRef = matchSingle(
201
+ await lucid.utxosByOutRef([
202
+ fromSystemParamsScriptRef(
203
+ sysParams.scriptReferences.stabilityPoolValidatorRef,
204
+ ),
205
+ ]),
206
+ (_) => new Error('Expected a single stability pool Ref Script UTXO'),
185
207
  );
186
208
 
187
209
  const request: AccountAction = {
188
210
  Close: {
189
211
  outputAddress: addressFromBech32(myAddress),
212
+ maxTxFee: maxTxFee,
190
213
  },
191
214
  };
192
- const oldAccountDatum: AccountContent = parseAccountDatum(
215
+ const oldAccountDatum: AccountContent = parseAccountDatumOrThrow(
193
216
  getInlineDatumOrThrow(accountUtxo),
194
217
  );
195
218
  const newAccountDatum: AccountContent = {
@@ -205,462 +228,571 @@ export async function closeSpAccount(
205
228
  serialiseStabilityPoolRedeemer({ RequestAction: request }),
206
229
  )
207
230
  .pay.ToContract(
208
- credentialToAddress(lucid.config().network!, {
209
- hash: validatorToScriptHash(
210
- mkStabilityPoolValidatorFromSP(params.stabilityPoolParams),
211
- ),
212
- type: 'Script',
213
- }),
231
+ accountUtxo.address,
214
232
  {
215
233
  kind: 'inline',
216
234
  value: serialiseStabilityPoolDatum({ Account: newAccountDatum }),
217
235
  },
218
- {
219
- lovelace: BigInt(
220
- params.stabilityPoolParams.requestCollateralLovelaces +
221
- params.stabilityPoolParams.accountAdjustmentFeeLovelaces,
236
+ addAssets(
237
+ mkLovelacesOf(
238
+ // TODO: Calculate a more accurate amount to just cover costs.
239
+ 5_000_000n,
222
240
  ),
223
- [params.stabilityPoolParams.accountToken[0].unCurrencySymbol +
224
- fromText(params.stabilityPoolParams.accountToken[1].unTokenName)]: 1n,
225
- },
241
+ mkAssetsOf(
242
+ fromSystemParamsAsset(sysParams.stabilityPoolParams.accountToken),
243
+ 1n,
244
+ ),
245
+ ),
226
246
  )
227
247
  .addSignerKey(toHex(oldAccountDatum.owner));
228
248
  }
229
249
 
230
250
  export async function processSpRequest(
231
- asset: string,
232
251
  stabilityPoolUtxo: UTxO,
233
252
  accountUtxo: UTxO,
234
- govUtxo: UTxO,
235
253
  iAssetUtxo: UTxO,
236
- newSnapshotUtxo: UTxO | undefined,
237
- params: SystemParams,
254
+ /**
255
+ * For performance provide only the ones related to the pool's iAsset.
256
+ */
257
+ allE2s2sSnapshotOrefs: OutRef[],
258
+ sysParams: SystemParams,
238
259
  lucid: LucidEvolution,
239
- collector: UtxoOrOutRef,
260
+ currentSlot: number,
240
261
  ): Promise<TxBuilder> {
241
- const redeemer: StabilityPoolRedeemer = {
242
- ProcessRequest: {
243
- txHash: { hash: fromHex(accountUtxo.txHash) },
244
- outputIndex: BigInt(accountUtxo.outputIndex),
245
- },
246
- };
247
- const stabilityPoolScriptRef = await scriptRef(
248
- params.scriptReferences.stabilityPoolValidatorRef,
249
- lucid,
262
+ const network = lucid.config().network!;
263
+ const currentTime = BigInt(slotToUnixTime(network, currentSlot));
264
+
265
+ const stabilityPoolScriptRef = matchSingle(
266
+ await lucid.utxosByOutRef([
267
+ fromSystemParamsScriptRef(
268
+ sysParams.scriptReferences.stabilityPoolValidatorRef,
269
+ ),
270
+ ]),
271
+ (_) => new Error('Expected a single stability pool Ref Script UTXO'),
250
272
  );
251
273
 
252
- const accountDatum = parseAccountDatum(getInlineDatumOrThrow(accountUtxo));
274
+ const accountDatum = parseAccountDatumOrThrow(
275
+ getInlineDatumOrThrow(accountUtxo),
276
+ );
253
277
 
254
- const stabilityPoolDatum = parseStabilityPoolDatum(
278
+ const stabilityPoolDatum = parseStabilityPoolDatumOrThrow(
255
279
  getInlineDatumOrThrow(stabilityPoolUtxo),
256
280
  );
257
281
 
282
+ const baseRefInputs = [iAssetUtxo, stabilityPoolScriptRef];
283
+
284
+ const validFrom = slotToUnixTime(network, currentSlot - 1);
258
285
  const tx = lucid
259
286
  .newTx()
260
- .collectFrom([stabilityPoolUtxo], serialiseStabilityPoolRedeemer(redeemer))
261
- .collectFrom([accountUtxo], serialiseStabilityPoolRedeemer(redeemer))
262
- .readFrom([iAssetUtxo, govUtxo, stabilityPoolScriptRef]);
263
-
287
+ .validFrom(validFrom)
288
+ .validTo(validFrom + sysParams.stabilityPoolParams.accountProcessingBiasMs)
289
+ .readFrom(baseRefInputs)
290
+ .collectFrom([stabilityPoolUtxo], {
291
+ kind: 'selected',
292
+ inputs: [stabilityPoolUtxo, accountUtxo],
293
+ makeRedeemer: (indices) =>
294
+ serialiseStabilityPoolRedeemer({
295
+ ProcessRequestPool: {
296
+ poolInputIdx: indices[0],
297
+ accountInputIdx: indices[1],
298
+ },
299
+ }),
300
+ });
264
301
  if (!accountDatum.request) throw new Error('Account Request is null');
265
302
 
266
- if (accountDatum.request === 'Create') {
267
- const accountTokenScriptRef = await scriptRef(
268
- params.scriptReferences.authTokenPolicies.accountTokenRef,
269
- lucid,
270
- );
271
- tx.readFrom([accountTokenScriptRef]);
272
-
273
- const iassetUnit =
274
- params.stabilityPoolParams.assetSymbol.unCurrencySymbol + fromText(asset);
275
- const reqAmount = accountUtxo.assets[iassetUnit] ?? 0n;
276
-
277
- const newAccountSnapshot: StabilityPoolSnapshot = {
278
- ...stabilityPoolDatum.poolSnapshot,
279
- depositVal: {
280
- value: spAdd(
281
- accountDatum.accountSnapshot.depositVal,
282
- mkSPInteger(reqAmount),
283
- ).value,
284
- },
285
- };
303
+ const iassetAssetClass: AssetClass = {
304
+ currencySymbol: fromHex(
305
+ sysParams.stabilityPoolParams.assetSymbol.unCurrencySymbol,
306
+ ),
307
+ tokenName: stabilityPoolDatum.iasset,
308
+ };
286
309
 
287
- const newDeposit = spAdd(
288
- stabilityPoolDatum.poolSnapshot.depositVal,
289
- mkSPInteger(reqAmount),
290
- );
310
+ await match(accountDatum.request)
311
+ .with('Create', async (_) => {
312
+ const accountTokenScriptRef = matchSingle(
313
+ await lucid.utxosByOutRef([
314
+ fromSystemParamsScriptRef(
315
+ sysParams.scriptReferences.authTokenPolicies.accountTokenRef,
316
+ ),
317
+ ]),
318
+ (_) =>
319
+ new Error('Expected a single cdp auth token policy Ref Script UTXO'),
320
+ );
291
321
 
292
- const newSum = spAdd(
293
- stabilityPoolDatum.poolSnapshot.sumVal,
294
- spDiv(
295
- spMul(
296
- mkSPInteger(
297
- BigInt(params.stabilityPoolParams.accountCreateFeeLovelaces),
322
+ const requestDepositAmt = assetClassValueOf(
323
+ accountUtxo.assets,
324
+ iassetAssetClass,
325
+ );
326
+
327
+ const poolAddr = mkStabilityPoolAddr(lucid, sysParams);
328
+
329
+ tx.readFrom([accountTokenScriptRef])
330
+ .collectFrom([accountUtxo], {
331
+ kind: 'selected',
332
+ inputs: [stabilityPoolUtxo, accountUtxo],
333
+ makeRedeemer: (indices) =>
334
+ serialiseStabilityPoolRedeemer({
335
+ ProcessRequestAccount: {
336
+ poolInputIdx: indices[0],
337
+ accountInputIdx: indices[1],
338
+ e2s2sIdxs: [],
339
+ currentTime: currentTime,
340
+ },
341
+ }),
342
+ })
343
+ .mintAssets(
344
+ mkAssetsOf(
345
+ fromSystemParamsAsset(sysParams.stabilityPoolParams.accountToken),
346
+ 1n,
298
347
  ),
299
- stabilityPoolDatum.poolSnapshot.productVal,
348
+ Data.void(),
349
+ )
350
+ .pay.ToContract(
351
+ poolAddr,
352
+ {
353
+ kind: 'inline',
354
+ value: serialiseStabilityPoolDatum({
355
+ StabilityPool: liquidationHelper(
356
+ {
357
+ ...stabilityPoolDatum,
358
+ state: {
359
+ ...stabilityPoolDatum.state,
360
+ depositVal: spAdd(
361
+ stabilityPoolDatum.state.depositVal,
362
+ mkSPInteger(requestDepositAmt),
363
+ ),
364
+ },
365
+ },
366
+ adaAssetClass,
367
+ 0n,
368
+ BigInt(sysParams.stabilityPoolParams.accountCreateFeeLovelaces),
369
+ ),
370
+ }),
371
+ },
372
+ addAssets(
373
+ stabilityPoolUtxo.assets,
374
+ mkAssetsOf(iassetAssetClass, requestDepositAmt),
375
+ mkLovelacesOf(
376
+ BigInt(sysParams.stabilityPoolParams.accountCreateFeeLovelaces),
377
+ ),
378
+ ),
379
+ )
380
+ .pay.ToContract(
381
+ poolAddr,
382
+ {
383
+ kind: 'inline',
384
+ value: serialiseStabilityPoolDatum({
385
+ Account: {
386
+ owner: accountDatum.owner,
387
+ iasset: stabilityPoolDatum.iasset,
388
+ state: {
389
+ ...stabilityPoolDatum.state,
390
+ depositVal: mkSPInteger(requestDepositAmt),
391
+ },
392
+ assetSums: stabilityPoolDatum.assetStates.map(([key, val]) => [
393
+ key,
394
+ val.currentSumVal,
395
+ ]),
396
+ request: null,
397
+ lastRequestProcessingTime: currentTime,
398
+ },
399
+ }),
400
+ },
401
+ addAssets(
402
+ mkAssetsOf(
403
+ fromSystemParamsAsset(sysParams.stabilityPoolParams.accountToken),
404
+ 1n,
405
+ ),
406
+ mkLovelacesOf(lovelacesAmt(accountUtxo.assets)),
407
+ ),
408
+ );
409
+ })
410
+ .with({ Adjust: P.select() }, async (adjustContent) => {
411
+ const iassetDatum = parseIAssetDatumOrThrow(
412
+ getInlineDatumOrThrow(iAssetUtxo),
413
+ );
414
+
415
+ const accountDepositChange = adjustContent.amount;
416
+ const outputAddress = addressToBech32(
417
+ adjustContent.outputAddress,
418
+ lucid.config().network!,
419
+ );
420
+
421
+ const e2s2sIdxs = await findRelevantE2s2sIdxs(
422
+ lucid,
423
+ stabilityPoolDatum,
424
+ accountDatum.state,
425
+ allE2s2sSnapshotOrefs,
426
+ );
427
+
428
+ const { updatedAccountContent, reward } = updateAccount(
429
+ stabilityPoolDatum,
430
+ accountDatum,
431
+ e2s2sIdxs,
432
+ );
433
+
434
+ const isDepositOrRewardWithdrawal = accountDepositChange >= 0;
435
+
436
+ const accountBalanceChange = isDepositOrRewardWithdrawal
437
+ ? accountDepositChange
438
+ : bigintMax(
439
+ accountDepositChange,
440
+ -fromSPInteger(updatedAccountContent.state.depositVal),
441
+ );
442
+
443
+ const newPoolDepositExcludingFee = spZeroNegatives(
444
+ spAdd(
445
+ stabilityPoolDatum.state.depositVal,
446
+ mkSPInteger(accountBalanceChange),
300
447
  ),
301
- newDeposit,
302
- ),
303
- );
448
+ );
304
449
 
305
- const newStabilityPoolSnapshot: StabilityPoolSnapshot = {
306
- ...stabilityPoolDatum.poolSnapshot,
307
- depositVal: newDeposit,
308
- sumVal: newSum,
309
- };
310
-
311
- const newEpochToScaleToSum: EpochToScaleToSum = setSumInEpochToScaleToSum(
312
- stabilityPoolDatum.epochToScaleToSum,
313
- stabilityPoolDatum.poolSnapshot.epoch,
314
- stabilityPoolDatum.poolSnapshot.scale,
315
- newSum,
316
- );
450
+ const withdrawalFeeAmt =
451
+ isDepositOrRewardWithdrawal || newPoolDepositExcludingFee.value === 0n
452
+ ? 0n
453
+ : calculateFeeFromRatio(
454
+ iassetDatum.stabilityPoolWithdrawalFeeRatio,
455
+ -accountBalanceChange,
456
+ );
457
+
458
+ const newPoolState = updatePoolStateWhenWithdrawalFee(withdrawalFeeAmt, {
459
+ ...stabilityPoolDatum.state,
460
+ depositVal: newPoolDepositExcludingFee,
461
+ });
462
+
463
+ const { e2s2sRefInputs, mkProcessRequestAccountRedeemerContent } =
464
+ createProcessRequestAccountRedeemer(
465
+ e2s2sIdxs,
466
+ baseRefInputs,
467
+ currentTime,
468
+ );
469
+
470
+ if (e2s2sRefInputs.length > 0) {
471
+ tx.readFrom(e2s2sRefInputs);
472
+ }
473
+
474
+ tx.collectFrom([accountUtxo], {
475
+ kind: 'selected',
476
+ inputs: [stabilityPoolUtxo, accountUtxo],
477
+ makeRedeemer: (indices) => {
478
+ return serialiseStabilityPoolRedeemer({
479
+ ProcessRequestAccount: mkProcessRequestAccountRedeemerContent(
480
+ indices[0],
481
+ indices[1],
482
+ ),
483
+ });
484
+ },
485
+ }).pay.ToContract(
486
+ stabilityPoolUtxo.address,
487
+ {
488
+ kind: 'inline',
489
+ value: serialiseStabilityPoolDatum({
490
+ StabilityPool: {
491
+ ...stabilityPoolDatum,
492
+ state: newPoolState,
493
+ },
494
+ }),
495
+ },
496
+ addAssets(
497
+ stabilityPoolUtxo.assets,
498
+ negateAssets(reward),
499
+ mkAssetsOf(iassetAssetClass, accountBalanceChange + withdrawalFeeAmt),
500
+ ),
501
+ );
317
502
 
318
- const stabilityPoolAssetToken = stabilityPoolUtxo.assets[iassetUnit] ?? 0n;
319
- const poolOutputValue = {
320
- lovelace:
321
- stabilityPoolUtxo.assets.lovelace +
322
- BigInt(params.stabilityPoolParams.accountCreateFeeLovelaces),
323
- [params.stabilityPoolParams.stabilityPoolToken[0].unCurrencySymbol +
324
- fromText(params.stabilityPoolParams.stabilityPoolToken[1].unTokenName)]:
325
- 1n,
326
- [params.stabilityPoolParams.assetSymbol.unCurrencySymbol +
327
- fromText(asset)]: stabilityPoolAssetToken + reqAmount,
328
- };
503
+ const theoreticalOwnerOutputVal = addAssets(
504
+ reward,
505
+ isDepositOrRewardWithdrawal
506
+ ? {}
507
+ : mkAssetsOf(
508
+ iassetAssetClass,
509
+ -accountBalanceChange - withdrawalFeeAmt,
510
+ ),
511
+ );
512
+ const ownerOutputDat = serialiseActionReturnDatum({
513
+ IndigoStabilityPoolAccountAdjustment: {
514
+ txHash: fromHex(accountUtxo.txHash),
515
+ outputIndex: BigInt(accountUtxo.outputIndex),
516
+ },
517
+ });
329
518
 
330
- tx.mintAssets(
331
- {
332
- [params.stabilityPoolParams.accountToken[0].unCurrencySymbol +
333
- fromText(params.stabilityPoolParams.accountToken[1].unTokenName)]: 1n,
334
- },
335
- Data.to(new Constr(0, [])),
336
- );
519
+ const ownerOutputMinUtxoLovelace = estimateUtxoMinLovelace(
520
+ lucid.config().protocolParameters!,
521
+ outputAddress,
522
+ theoreticalOwnerOutputVal,
523
+ { InlineDatum: { datum: ownerOutputDat } },
524
+ );
337
525
 
338
- tx.pay.ToContract(
339
- stabilityPoolUtxo.address,
340
- {
341
- kind: 'inline',
342
- value: serialiseStabilityPoolDatum({
343
- StabilityPool: {
344
- ...stabilityPoolDatum,
345
- poolSnapshot: newStabilityPoolSnapshot,
346
- epochToScaleToSum: newEpochToScaleToSum,
526
+ // Add extra lovelaces only when needed to reach minUTxo lovelaces.
527
+ const extraOwnerOutputLovelacesAmt =
528
+ lovelacesAmt(theoreticalOwnerOutputVal) >= ownerOutputMinUtxoLovelace
529
+ ? 0n
530
+ : ownerOutputMinUtxoLovelace -
531
+ lovelacesAmt(theoreticalOwnerOutputVal);
532
+
533
+ const actualOwnerOutputVal = addAssets(
534
+ theoreticalOwnerOutputVal,
535
+ mkLovelacesOf(extraOwnerOutputLovelacesAmt),
536
+ );
537
+
538
+ const accountOutputDat = serialiseStabilityPoolDatum({
539
+ Account: {
540
+ ...updatedAccountContent,
541
+ state: {
542
+ ...updatedAccountContent.state,
543
+ depositVal: spAdd(
544
+ updatedAccountContent.state.depositVal,
545
+ mkSPInteger(accountBalanceChange),
546
+ ),
347
547
  },
348
- }),
349
- },
350
- poolOutputValue,
351
- );
548
+ request: null,
549
+ lastRequestProcessingTime: currentTime,
550
+ },
551
+ });
352
552
 
353
- tx.pay.ToContract(
354
- stabilityPoolUtxo.address,
355
- {
356
- kind: 'inline',
357
- value: serialiseStabilityPoolDatum({
358
- Account: {
359
- ...accountDatum,
360
- accountSnapshot: newAccountSnapshot,
361
- request: null,
553
+ const accountOutputValWithoutAda = mkAssetsOf(
554
+ fromSystemParamsAsset(sysParams.stabilityPoolParams.accountToken),
555
+ 1n,
556
+ );
557
+
558
+ const accountOutMinUtxoLovelace = estimateUtxoMinLovelace(
559
+ lucid.config().protocolParameters!,
560
+ stabilityPoolUtxo.address,
561
+ accountOutputValWithoutAda,
562
+ { InlineDatum: { datum: accountOutputDat } },
563
+ );
564
+
565
+ // TODO: include Tx fee here.
566
+ const accountOutputAdaAmt =
567
+ lovelacesAmt(accountUtxo.assets) - extraOwnerOutputLovelacesAmt;
568
+
569
+ // This is to prevent spending ADA from the wallet submitting the request processing Tx.
570
+ if (accountOutputAdaAmt < accountOutMinUtxoLovelace) {
571
+ throw new Error("Account doesn't have enough ADA to be processed.");
572
+ }
573
+
574
+ tx.pay
575
+ .ToContract(
576
+ stabilityPoolUtxo.address,
577
+ {
578
+ kind: 'inline',
579
+ value: accountOutputDat,
362
580
  },
363
- }),
364
- },
365
- {
366
- lovelace:
367
- accountUtxo.assets.lovelace -
368
- BigInt(params.stabilityPoolParams.accountCreateFeeLovelaces),
369
- [params.stabilityPoolParams.accountToken[0].unCurrencySymbol +
370
- fromText(params.stabilityPoolParams.accountToken[1].unTokenName)]: 1n,
371
- },
372
- );
373
- } else if ('Adjust' in accountDatum.request) {
374
- const amount = accountDatum.request.Adjust.amount;
375
- const outputAddress = addressToBech32(
376
- accountDatum.request.Adjust.outputAddress,
377
- lucid.config().network!,
378
- );
379
- const myAddress = await lucid.wallet().address();
380
- const [updatedAccountSnapshot, reward, refInputs] = adjustmentHelper(
381
- stabilityPoolUtxo,
382
- newSnapshotUtxo,
383
- stabilityPoolDatum.poolSnapshot,
384
- stabilityPoolDatum.epochToScaleToSum,
385
- accountDatum.accountSnapshot,
386
- );
387
- const govDatum: GovDatum = parseGovDatumOrThrow(
388
- getInlineDatumOrThrow(govUtxo),
389
- );
390
- const iassetDatum: IAssetContent = parseIAssetDatumOrThrow(
391
- getInlineDatumOrThrow(iAssetUtxo),
392
- );
393
- const rewardLovelacesFee = calculateFeeFromPercentage(
394
- govDatum.protocolParams.collateralFeePercentage,
395
- reward,
396
- );
397
- const isDepositOrRewardWithdrawal: boolean = amount > 0n;
398
- const bigIntMax = (...args: bigint[]): bigint =>
399
- args.reduce((m, e) => (e > m ? e : m));
400
-
401
- const balanceChange: bigint = isDepositOrRewardWithdrawal
402
- ? amount
403
- : bigIntMax(amount, -fromSPInteger(updatedAccountSnapshot.depositVal));
404
- const newAccountSnapshot: StabilityPoolSnapshot = {
405
- ...updatedAccountSnapshot,
406
- depositVal: spAdd(
407
- updatedAccountSnapshot.depositVal,
408
- mkSPInteger(balanceChange),
409
- ),
410
- };
411
- const _newPoolDepositExcludingFee = spAdd(
412
- stabilityPoolDatum.poolSnapshot.depositVal,
413
- mkSPInteger(balanceChange),
414
- );
415
- const newPoolDepositExcludingFee =
416
- _newPoolDepositExcludingFee.value > 0n
417
- ? _newPoolDepositExcludingFee
418
- : mkSPInteger(0n);
419
- const withdrawalFee =
420
- isDepositOrRewardWithdrawal || newPoolDepositExcludingFee.value === 0n
421
- ? 0n
422
- : calculateFeeFromPercentage(
423
- iassetDatum.stabilityPoolWithdrawalFeePercentage,
424
- -balanceChange,
425
- );
426
- const newPoolDeposit = spAdd(
427
- newPoolDepositExcludingFee,
428
- mkSPInteger(withdrawalFee),
429
- );
430
- const newPoolProduct =
431
- withdrawalFee === 0n
432
- ? stabilityPoolDatum.poolSnapshot.productVal
433
- : spMul(
434
- stabilityPoolDatum.poolSnapshot.productVal,
435
- spAdd(
436
- mkSPInteger(1n),
437
- spDiv(mkSPInteger(withdrawalFee), newPoolDepositExcludingFee),
438
- ),
439
- );
440
- const newPoolSum = spAdd(
441
- stabilityPoolDatum.poolSnapshot.sumVal,
442
- spDiv(
443
- spMul(
444
- mkSPInteger(
445
- BigInt(params.stabilityPoolParams.accountAdjustmentFeeLovelaces),
581
+ addAssets(
582
+ accountOutputValWithoutAda,
583
+ mkLovelacesOf(accountOutputAdaAmt),
446
584
  ),
447
- newPoolProduct,
585
+ )
586
+ .pay.ToAddressWithData(
587
+ outputAddress,
588
+ {
589
+ kind: 'inline',
590
+ value: ownerOutputDat,
591
+ },
592
+ actualOwnerOutputVal,
593
+ );
594
+ })
595
+ .with({ Close: P.select() }, async (closeContent) => {
596
+ const accountTokenScriptRef = matchSingle(
597
+ await lucid.utxosByOutRef([
598
+ fromSystemParamsScriptRef(
599
+ sysParams.scriptReferences.authTokenPolicies.accountTokenRef,
600
+ ),
601
+ ]),
602
+ (_) =>
603
+ new Error('Expected a single cdp auth token policy Ref Script UTXO'),
604
+ );
605
+
606
+ const iassetDatum = parseIAssetDatumOrThrow(
607
+ getInlineDatumOrThrow(iAssetUtxo),
608
+ );
609
+
610
+ const outputAddress = addressToBech32(
611
+ closeContent.outputAddress,
612
+ lucid.config().network!,
613
+ );
614
+
615
+ const e2s2sIdxs = await findRelevantE2s2sIdxs(
616
+ lucid,
617
+ stabilityPoolDatum,
618
+ accountDatum.state,
619
+ allE2s2sSnapshotOrefs,
620
+ );
621
+
622
+ const { updatedAccountContent, reward } = updateAccount(
623
+ stabilityPoolDatum,
624
+ accountDatum,
625
+ e2s2sIdxs,
626
+ );
627
+
628
+ const newPoolDepositExcludingFee = spZeroNegatives(
629
+ spSub(
630
+ stabilityPoolDatum.state.depositVal,
631
+ updatedAccountContent.state.depositVal,
448
632
  ),
449
- newPoolDeposit,
450
- ),
451
- );
452
- const newPoolSnapshot: StabilityPoolSnapshot = {
453
- ...stabilityPoolDatum.poolSnapshot,
454
- depositVal: newPoolDeposit,
455
- sumVal: newPoolSum,
456
- productVal: newPoolProduct,
457
- };
458
- const newEpochToScaleToSum: EpochToScaleToSum = setSumInEpochToScaleToSum(
459
- stabilityPoolDatum.epochToScaleToSum,
460
- stabilityPoolDatum.poolSnapshot.epoch,
461
- stabilityPoolDatum.poolSnapshot.scale,
462
- newPoolSum,
463
- );
633
+ );
464
634
 
465
- if (rewardLovelacesFee > 0n) {
466
- await collectorFeeTx(rewardLovelacesFee, lucid, params, tx, collector);
467
- }
468
- tx.readFrom([govUtxo, iAssetUtxo, ...refInputs]);
469
- tx.pay.ToContract(
470
- stabilityPoolUtxo.address,
471
- {
472
- kind: 'inline',
473
- value: serialiseStabilityPoolDatum({
474
- StabilityPool: {
475
- ...stabilityPoolDatum,
476
- poolSnapshot: newPoolSnapshot,
477
- epochToScaleToSum: newEpochToScaleToSum,
635
+ const withdrawnAmt = zeroNegatives(
636
+ fromSPInteger(updatedAccountContent.state.depositVal),
637
+ );
638
+
639
+ const withdrawalFeeAmt =
640
+ newPoolDepositExcludingFee.value === 0n
641
+ ? 0n
642
+ : calculateFeeFromRatio(
643
+ iassetDatum.stabilityPoolWithdrawalFeeRatio,
644
+ withdrawnAmt,
645
+ );
646
+
647
+ const newPoolState = updatePoolStateWhenWithdrawalFee(withdrawalFeeAmt, {
648
+ ...stabilityPoolDatum.state,
649
+ depositVal: newPoolDepositExcludingFee,
650
+ });
651
+
652
+ const { e2s2sRefInputs, mkProcessRequestAccountRedeemerContent } =
653
+ createProcessRequestAccountRedeemer(
654
+ e2s2sIdxs,
655
+ [...baseRefInputs, accountTokenScriptRef],
656
+ currentTime,
657
+ );
658
+
659
+ if (e2s2sRefInputs.length > 0) {
660
+ tx.readFrom(e2s2sRefInputs);
661
+ }
662
+
663
+ tx.readFrom([accountTokenScriptRef])
664
+ .collectFrom([accountUtxo], {
665
+ kind: 'selected',
666
+ inputs: [stabilityPoolUtxo, accountUtxo],
667
+ makeRedeemer: (indices) => {
668
+ return serialiseStabilityPoolRedeemer({
669
+ ProcessRequestAccount: mkProcessRequestAccountRedeemerContent(
670
+ indices[0],
671
+ indices[1],
672
+ ),
673
+ });
478
674
  },
479
- }),
480
- },
481
- {
482
- lovelace:
483
- stabilityPoolUtxo.assets.lovelace +
484
- BigInt(params.stabilityPoolParams.accountAdjustmentFeeLovelaces) -
485
- reward,
486
- [params.stabilityPoolParams.stabilityPoolToken[0].unCurrencySymbol +
487
- fromText(params.stabilityPoolParams.stabilityPoolToken[1].unTokenName)]:
488
- 1n,
489
- [params.stabilityPoolParams.assetSymbol.unCurrencySymbol +
490
- fromText(asset)]:
491
- stabilityPoolUtxo.assets[
492
- params.stabilityPoolParams.assetSymbol.unCurrencySymbol +
493
- fromText(asset)
494
- ] +
495
- balanceChange +
496
- withdrawalFee,
497
- },
498
- );
499
- tx.pay.ToContract(
500
- stabilityPoolUtxo.address,
501
- {
502
- kind: 'inline',
503
- value: serialiseStabilityPoolDatum({
504
- Account: {
505
- ...accountDatum,
506
- accountSnapshot: newAccountSnapshot,
507
- request: null,
675
+ })
676
+ .mintAssets(
677
+ mkAssetsOf(
678
+ fromSystemParamsAsset(sysParams.stabilityPoolParams.accountToken),
679
+ -1n,
680
+ ),
681
+ Data.void(),
682
+ )
683
+ .pay.ToContract(
684
+ stabilityPoolUtxo.address,
685
+ {
686
+ kind: 'inline',
687
+ value: serialiseStabilityPoolDatum({
688
+ StabilityPool: {
689
+ ...stabilityPoolDatum,
690
+ state: newPoolState,
691
+ },
692
+ }),
508
693
  },
509
- }),
510
- },
511
- {
512
- lovelace:
513
- accountUtxo.assets.lovelace -
514
- BigInt(params.stabilityPoolParams.accountAdjustmentFeeLovelaces) -
515
- 2_000_000n,
516
- [params.stabilityPoolParams.accountToken[0].unCurrencySymbol +
517
- fromText(params.stabilityPoolParams.accountToken[1].unTokenName)]: 1n,
518
- },
519
- );
520
- if (myAddress !== outputAddress) {
521
- tx.pay.ToAddressWithData(
522
- outputAddress,
523
- {
524
- kind: 'inline',
525
- value: Data.to(
526
- {
527
- IndigoStabilityPoolAccountAdjustment: {
528
- spent_account: {
529
- txHash: { hash: accountUtxo.txHash },
530
- outputIndex: BigInt(accountUtxo.outputIndex),
531
- },
694
+ addAssets(
695
+ stabilityPoolUtxo.assets,
696
+ negateAssets(reward),
697
+ mkAssetsOf(iassetAssetClass, -withdrawnAmt + withdrawalFeeAmt),
698
+ ),
699
+ )
700
+ .pay.ToAddressWithData(
701
+ outputAddress,
702
+ {
703
+ kind: 'inline',
704
+ value: serialiseActionReturnDatum({
705
+ IndigoStabilityPoolAccountClosure: {
706
+ txHash: fromHex(accountUtxo.txHash),
707
+ outputIndex: BigInt(accountUtxo.outputIndex),
532
708
  },
533
- },
534
- ActionReturnDatum,
709
+ }),
710
+ },
711
+ addAssets(
712
+ mkLovelacesOf(lovelacesAmt(accountUtxo.assets)),
713
+ reward,
714
+ mkAssetsOf(iassetAssetClass, withdrawnAmt - withdrawalFeeAmt),
535
715
  ),
536
- },
537
- {
538
- lovelace: reward - rewardLovelacesFee + 2_000_000n,
539
- ...(!isDepositOrRewardWithdrawal
540
- ? {
541
- [params.stabilityPoolParams.assetSymbol.unCurrencySymbol +
542
- fromText(asset)]: -balanceChange - withdrawalFee,
543
- }
544
- : {}),
545
- },
546
- );
547
- } else {
548
- // TODO: User is self-handling the process request, so we will need to handle the change datum
549
- }
550
- } else if ('Close' in accountDatum.request) {
551
- const outputAddress = addressToBech32(
552
- accountDatum.request.Close.outputAddress,
553
- lucid.config().network!,
554
- );
555
- const myAddress = await lucid.wallet().address();
556
- const [updatedAccountSnapshot, reward, refInputs] = adjustmentHelper(
557
- stabilityPoolUtxo,
558
- newSnapshotUtxo,
559
- stabilityPoolDatum.poolSnapshot,
560
- stabilityPoolDatum.epochToScaleToSum,
561
- accountDatum.accountSnapshot,
562
- );
563
- const govDatum: GovDatum = parseGovDatumOrThrow(
564
- getInlineDatumOrThrow(govUtxo),
565
- );
566
- const iassetDatum: IAssetContent = parseIAssetDatumOrThrow(
567
- getInlineDatumOrThrow(iAssetUtxo),
568
- );
569
- const rewardLovelacesFee = calculateFeeFromPercentage(
570
- govDatum.protocolParams.collateralFeePercentage,
571
- reward,
572
- );
573
- const fund = updatedAccountSnapshot.depositVal;
574
- const newPoolDepositExcludingFee = spSub(
575
- stabilityPoolDatum.poolSnapshot.depositVal,
576
- fund,
577
- );
578
- const withdrawnAmt = fund.value < 0n ? mkSPInteger(0n) : fund;
579
- const withdrawalFeeAmount =
580
- newPoolDepositExcludingFee.value === 0n
581
- ? 0n
582
- : calculateFeeFromPercentage(
583
- iassetDatum.stabilityPoolWithdrawalFeePercentage,
584
- withdrawnAmt.value,
585
- );
586
- const [newPoolDeposit, newPoolProduct] = updatePoolSnapshotWithdrawalFee(
587
- mkSPInteger(withdrawalFeeAmount),
588
- newPoolDepositExcludingFee,
589
- stabilityPoolDatum.poolSnapshot,
590
- );
591
- const newPoolSnapshot: StabilityPoolSnapshot = {
592
- ...stabilityPoolDatum.poolSnapshot,
593
- depositVal: newPoolDeposit,
594
- productVal: newPoolProduct,
595
- };
596
- const accountTokenRef = await scriptRef(
597
- params.scriptReferences.authTokenPolicies.accountTokenRef,
598
- lucid,
599
- );
600
- await collectorFeeTx(rewardLovelacesFee, lucid, params, tx, collector);
601
- tx.readFrom([govUtxo, iAssetUtxo, accountTokenRef, ...refInputs]);
602
- tx.mintAssets(
716
+ );
717
+ })
718
+ .exhaustive();
719
+
720
+ return tx;
721
+ }
722
+
723
+ export async function createE2s2sSnapshots(
724
+ stabilityPoolOref: OutRef,
725
+ sysParams: SystemParams,
726
+ lucid: LucidEvolution,
727
+ ): Promise<TxBuilder> {
728
+ const stabilityPoolRefScriptUtxo = matchSingle(
729
+ await lucid.utxosByOutRef([
730
+ fromSystemParamsScriptRef(
731
+ sysParams.scriptReferences.stabilityPoolValidatorRef,
732
+ ),
733
+ ]),
734
+ (_) => new Error('Expected a single stability pool Ref Script UTXO'),
735
+ );
736
+ const snapshotE2s2sPolicyRefScriptUtxo = matchSingle(
737
+ await lucid.utxosByOutRef([
738
+ fromSystemParamsScriptRef(
739
+ sysParams.scriptReferences.authTokenPolicies
740
+ .snapshotEpochToScaleToSumTokenRef,
741
+ ),
742
+ ]),
743
+ (_) => new Error('Expected a single snapshot e2s2s policy Ref Script UTXO'),
744
+ );
745
+
746
+ const spUtxo = matchSingle(
747
+ await lucid.utxosByOutRef([stabilityPoolOref]),
748
+ (_) => new Error('Expected a single stability pool UTXO'),
749
+ );
750
+ const spDatum = parseStabilityPoolDatumOrThrow(getInlineDatumOrThrow(spUtxo));
751
+
752
+ const [newSnapshotDatums, newAssetStates] =
753
+ partitionEpochToScaleToSums(spDatum);
754
+
755
+ if (newSnapshotDatums.length === 0) {
756
+ throw new Error('There has to be a snapshot being created.');
757
+ }
758
+
759
+ const snapshotAc = fromSystemParamsAsset(
760
+ sysParams.stabilityPoolParams.snapshotEpochToScaleToSumToken,
761
+ );
762
+
763
+ const tx = lucid
764
+ .newTx()
765
+ .readFrom([stabilityPoolRefScriptUtxo, snapshotE2s2sPolicyRefScriptUtxo])
766
+ .collectFrom(
767
+ [spUtxo],
768
+ serialiseStabilityPoolRedeemer('RecordEpochToScaleToSum'),
769
+ )
770
+ .mintAssets(
771
+ mkAssetsOf(snapshotAc, BigInt(newSnapshotDatums.length)),
772
+ Data.void(),
773
+ )
774
+ .pay.ToContract(
775
+ spUtxo.address,
603
776
  {
604
- [params.stabilityPoolParams.accountToken[0].unCurrencySymbol +
605
- fromText(params.stabilityPoolParams.accountToken[1].unTokenName)]: -1n,
777
+ kind: 'inline',
778
+ value: serialiseStabilityPoolDatum({
779
+ StabilityPool: { ...spDatum, assetStates: newAssetStates },
780
+ }),
606
781
  },
607
- Data.to(new Constr(0, [])),
782
+ spUtxo.assets,
608
783
  );
609
- const assetOutputAmountForSP =
610
- stabilityPoolUtxo.assets[
611
- params.stabilityPoolParams.assetSymbol.unCurrencySymbol +
612
- fromText(asset)
613
- ] -
614
- fromSPInteger(withdrawnAmt) -
615
- withdrawalFeeAmount;
784
+
785
+ for (const newDatum of newSnapshotDatums) {
616
786
  tx.pay.ToContract(
617
- stabilityPoolUtxo.address,
787
+ spUtxo.address,
618
788
  {
619
789
  kind: 'inline',
620
790
  value: serialiseStabilityPoolDatum({
621
- StabilityPool: {
622
- ...stabilityPoolDatum,
623
- poolSnapshot: newPoolSnapshot,
624
- },
791
+ SnapshotEpochToScaleToSum: newDatum,
625
792
  }),
626
793
  },
627
- {
628
- lovelace: stabilityPoolUtxo.assets.lovelace - reward,
629
- [params.stabilityPoolParams.stabilityPoolToken[0].unCurrencySymbol +
630
- fromText(params.stabilityPoolParams.stabilityPoolToken[1].unTokenName)]:
631
- 1n,
632
- ...(assetOutputAmountForSP > 0n
633
- ? {
634
- [params.stabilityPoolParams.assetSymbol.unCurrencySymbol +
635
- fromText(asset)]: assetOutputAmountForSP,
636
- }
637
- : {}),
638
- },
794
+ mkAssetsOf(snapshotAc, 1n),
639
795
  );
640
- if (myAddress !== outputAddress) {
641
- tx.pay.ToAddressWithData(
642
- outputAddress,
643
- {
644
- kind: 'inline',
645
- value: Data.to(
646
- {
647
- IndigoStabilityPoolAccountClosure: {
648
- closed_account: {
649
- txHash: { hash: accountUtxo.txHash },
650
- outputIndex: BigInt(accountUtxo.outputIndex),
651
- },
652
- },
653
- },
654
- ActionReturnDatum,
655
- ),
656
- },
657
- {
658
- lovelace: accountUtxo.assets.lovelace + reward - rewardLovelacesFee,
659
- [params.stabilityPoolParams.assetSymbol.unCurrencySymbol +
660
- fromText(asset)]: fromSPInteger(withdrawnAmt) - withdrawalFeeAmount,
661
- },
662
- );
663
- }
664
796
  }
665
797
 
666
798
  return tx;
@@ -671,29 +803,27 @@ export async function annulRequest(
671
803
  params: SystemParams,
672
804
  lucid: LucidEvolution,
673
805
  ): Promise<TxBuilder> {
674
- const stabilityPoolScriptRef = await scriptRef(
675
- params.scriptReferences.stabilityPoolValidatorRef,
676
- lucid,
806
+ const stabilityPoolRefScriptUtxo = matchSingle(
807
+ await lucid.utxosByOutRef([
808
+ fromSystemParamsScriptRef(
809
+ params.scriptReferences.stabilityPoolValidatorRef,
810
+ ),
811
+ ]),
812
+ (_) => new Error('Expected a single stability pool Ref Script UTXO'),
677
813
  );
678
-
679
- const oldAccountDatum: AccountContent = parseAccountDatum(
814
+ const oldAccountDatum: AccountContent = parseAccountDatumOrThrow(
680
815
  getInlineDatumOrThrow(accountUtxo),
681
816
  );
682
817
 
683
818
  const tx = lucid
684
819
  .newTx()
685
- .readFrom([stabilityPoolScriptRef])
820
+ .readFrom([stabilityPoolRefScriptUtxo])
686
821
  .collectFrom([accountUtxo], serialiseStabilityPoolRedeemer('AnnulRequest'))
687
822
  .addSignerKey(toHex(oldAccountDatum.owner));
688
823
 
689
824
  if (oldAccountDatum.request !== 'Create') {
690
825
  tx.pay.ToContract(
691
- credentialToAddress(lucid.config().network!, {
692
- hash: validatorToScriptHash(
693
- mkStabilityPoolValidatorFromSP(params.stabilityPoolParams),
694
- ),
695
- type: 'Script',
696
- }),
826
+ accountUtxo.address,
697
827
  {
698
828
  kind: 'inline',
699
829
  value: serialiseStabilityPoolDatum({