@indigo-labs/indigo-sdk 0.2.1 → 0.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -8,7 +8,7 @@ export type InitialAsset = {
8
8
  expirationTime: bigint;
9
9
  };
10
10
  };
11
- initerestOracle: {
11
+ interestOracle: {
12
12
  tokenName: string;
13
13
  initialInterestRate: bigint;
14
14
  params: {
@@ -38,7 +38,7 @@ export const iusdInitialAssetCfg: InitialAsset = {
38
38
  expirationTime: 1_800_000n,
39
39
  },
40
40
  },
41
- initerestOracle: {
41
+ interestOracle: {
42
42
  tokenName: 'iUSD_ORACLE',
43
43
  initialInterestRate: 1_000_000n,
44
44
  params: {
@@ -11,12 +11,21 @@ import {
11
11
  createScriptAddress,
12
12
  fromSystemParamsAsset,
13
13
  getRandomElement,
14
+ IAssetOutput,
14
15
  matchSingle,
15
16
  parseCdpDatum,
16
17
  SystemParams,
17
18
  } from '../../src';
18
19
  import { assetClassToUnit } from '../../src/utils/value-helpers';
19
20
  import { option as O, array as A, function as F } from 'fp-ts';
21
+ import { findRandomCollector } from './collector-queries';
22
+ import { findGov } from './governance-queries';
23
+ import { findIAsset } from './iasset-queries';
24
+ import { findInterestOracle } from './interest-oracle-queries';
25
+ import { findPriceOracle } from './price-oracle-queries';
26
+ import { findStabilityPool } from './stability-pool-queries';
27
+ import { findRandomTreasuryUtxo } from './treasury-queries';
28
+ import { match, P } from 'ts-pattern';
20
29
 
21
30
  export async function findAllActiveCdps(
22
31
  lucid: LucidEvolution,
@@ -142,3 +151,70 @@ export async function findRandomCdpCreator(
142
151
  }, F.identity),
143
152
  );
144
153
  }
154
+
155
+ export async function findAllNecessaryOrefs(
156
+ lucid: LucidEvolution,
157
+ sysParams: SystemParams,
158
+ // ASCII encoded
159
+ asset: string,
160
+ ): Promise<{
161
+ stabilityPoolUtxo: UTxO;
162
+ iasset: IAssetOutput;
163
+ cdpCreatorUtxo: UTxO;
164
+ priceOracleUtxo: UTxO;
165
+ interestOracleUtxo: UTxO;
166
+ collectorUtxo: UTxO;
167
+ govUtxo: UTxO;
168
+ treasuryUtxo: UTxO;
169
+ }> {
170
+ const iasset = await findIAsset(
171
+ lucid,
172
+ sysParams.validatorHashes.cdpHash,
173
+ fromSystemParamsAsset(sysParams.cdpParams.iAssetAuthToken),
174
+ asset,
175
+ );
176
+
177
+ const stabilityPool = await findStabilityPool(
178
+ lucid,
179
+ sysParams.validatorHashes.stabilityPoolHash,
180
+ fromSystemParamsAsset(sysParams.stabilityPoolParams.stabilityPoolToken),
181
+ asset,
182
+ );
183
+
184
+ return {
185
+ stabilityPoolUtxo: stabilityPool,
186
+ iasset,
187
+ cdpCreatorUtxo: await findRandomCdpCreator(
188
+ lucid,
189
+ sysParams.validatorHashes.cdpCreatorHash,
190
+ fromSystemParamsAsset(sysParams.cdpCreatorParams.cdpCreatorNft),
191
+ ),
192
+ priceOracleUtxo: await findPriceOracle(
193
+ lucid,
194
+ match(iasset.datum.price)
195
+ .with({ Oracle: { content: P.select() } }, (oracleNft) => oracleNft)
196
+ .otherwise(() => {
197
+ throw new Error('Expected active oracle');
198
+ }),
199
+ ),
200
+ interestOracleUtxo: await findInterestOracle(
201
+ lucid,
202
+ iasset.datum.interestOracleNft,
203
+ ),
204
+ collectorUtxo: await findRandomCollector(
205
+ lucid,
206
+ sysParams.validatorHashes.collectorHash,
207
+ ),
208
+ govUtxo: (
209
+ await findGov(
210
+ lucid,
211
+ sysParams.validatorHashes.govHash,
212
+ fromSystemParamsAsset(sysParams.govParams.govNFT),
213
+ )
214
+ ).utxo,
215
+ treasuryUtxo: await findRandomTreasuryUtxo(
216
+ lucid,
217
+ sysParams.validatorHashes.treasuryHash,
218
+ ),
219
+ };
220
+ }
@@ -1,12 +1,17 @@
1
1
  import {
2
2
  Credential,
3
3
  LucidEvolution,
4
- Network,
5
4
  ScriptHash,
6
5
  UTxO,
7
6
  } from '@lucid-evolution/lucid';
8
7
  import { createScriptAddress } from '../../src/utils/lucid-utils';
9
- import { parseLrpDatum } from '../../src/contracts/lrp/types';
8
+ import {
9
+ LRPDatum,
10
+ parseLrpDatum,
11
+ parseLrpDatumOrThrow,
12
+ } from '../../src/contracts/lrp/types';
13
+ import { SystemParams } from '../../src';
14
+ import { option as O, array as A, function as F } from 'fp-ts';
10
15
 
11
16
  /**
12
17
  * Beware, this shouldn't be used in production since it queries all the UTXOs
@@ -14,12 +19,13 @@ import { parseLrpDatum } from '../../src/contracts/lrp/types';
14
19
  */
15
20
  export async function findLrp(
16
21
  lucid: LucidEvolution,
17
- network: Network,
18
22
  lrpScriptHash: ScriptHash,
19
23
  owner: string,
20
24
  assetTokenName: string,
21
25
  stakeCredential?: Credential,
22
26
  ): Promise<UTxO[]> {
27
+ const network = lucid.config().network!;
28
+
23
29
  const lrpUtxos = await lucid.utxosAt(
24
30
  createScriptAddress(network, lrpScriptHash, stakeCredential),
25
31
  );
@@ -27,7 +33,7 @@ export async function findLrp(
27
33
  return lrpUtxos.filter((utxo) => {
28
34
  if (utxo.datum != null) {
29
35
  try {
30
- const lrpDatum = parseLrpDatum(utxo.datum);
36
+ const lrpDatum = parseLrpDatumOrThrow(utxo.datum);
31
37
 
32
38
  return lrpDatum.owner == owner && lrpDatum.iasset == assetTokenName;
33
39
  } catch (_) {
@@ -37,3 +43,34 @@ export async function findLrp(
37
43
  }
38
44
  });
39
45
  }
46
+
47
+ export async function findAllLrps(
48
+ lucid: LucidEvolution,
49
+ sysParams: SystemParams,
50
+ // hex encoded
51
+ iasset: string,
52
+ ): Promise<{ utxo: UTxO; datum: LRPDatum }[]> {
53
+ const lrpUtxos = await lucid.utxosAt(
54
+ createScriptAddress(
55
+ lucid.config().network!,
56
+ sysParams.validatorHashes.lrpHash,
57
+ ),
58
+ );
59
+
60
+ return F.pipe(
61
+ lrpUtxos.map((utxo) =>
62
+ F.pipe(
63
+ O.fromNullable(utxo.datum),
64
+ O.flatMap(parseLrpDatum),
65
+ O.flatMap((datum) => {
66
+ if (datum.iasset === iasset) {
67
+ return O.some({ utxo, datum: datum });
68
+ } else {
69
+ return O.none;
70
+ }
71
+ }),
72
+ ),
73
+ ),
74
+ A.compact,
75
+ );
76
+ }
@@ -1,6 +1,6 @@
1
- import { beforeEach, test } from 'vitest';
1
+ import { beforeEach, expect, test } from 'vitest';
2
2
  import { LucidContext, runAndAwaitTx } from './test-helpers';
3
- import { EmulatorAccount, fromText, Lucid } from '@lucid-evolution/lucid';
3
+ import { EmulatorAccount, Lucid } from '@lucid-evolution/lucid';
4
4
  import { Emulator } from '@lucid-evolution/lucid';
5
5
  import { generateEmulatorAccount } from '@lucid-evolution/lucid';
6
6
  import { init } from './endpoints/initialize';
@@ -10,8 +10,17 @@ import { iusdInitialAssetCfg } from './mock/assets-mock';
10
10
  import {
11
11
  adjustStakingPosition,
12
12
  closeStakingPosition,
13
+ distributeAda,
13
14
  openStakingPosition,
14
15
  } from '../src/contracts/staking/transactions';
16
+ import { collectorFeeTx, fromSystemParamsAsset } from '../src';
17
+ import {
18
+ findAllCollectors,
19
+ findRandomCollector,
20
+ } from './queries/collector-queries';
21
+ import { findStakingManager } from '../src/contracts/staking/helpers';
22
+ import { getValueChangeAtAddressAfterAction } from './utils';
23
+ import { lovelacesAmt } from '@3rd-eye-labs/cardano-offchain-common';
15
24
 
16
25
  type MyContext = LucidContext<{
17
26
  admin: EmulatorAccount;
@@ -58,13 +67,7 @@ test<MyContext>('Staking - Adjust Position', async ({
58
67
  const myStakingPosition = await findStakingPosition(
59
68
  lucid,
60
69
  systemParams.validatorHashes.stakingHash,
61
- {
62
- currencySymbol:
63
- systemParams.stakingParams.stakingToken[0].unCurrencySymbol,
64
- tokenName: fromText(
65
- systemParams.stakingParams.stakingToken[1].unTokenName,
66
- ),
67
- },
70
+ fromSystemParamsAsset(systemParams.stakingParams.stakingToken),
68
71
  pkh.hash,
69
72
  );
70
73
 
@@ -95,13 +98,7 @@ test<MyContext>('Staking - Close Position', async ({
95
98
  const myStakingPosition = await findStakingPosition(
96
99
  lucid,
97
100
  systemParams.validatorHashes.stakingHash,
98
- {
99
- currencySymbol:
100
- systemParams.stakingParams.stakingToken[0].unCurrencySymbol,
101
- tokenName: fromText(
102
- systemParams.stakingParams.stakingToken[1].unTokenName,
103
- ),
104
- },
101
+ fromSystemParamsAsset(systemParams.stakingParams.stakingToken),
105
102
  pkh.hash,
106
103
  );
107
104
 
@@ -110,3 +107,61 @@ test<MyContext>('Staking - Close Position', async ({
110
107
  closeStakingPosition(myStakingPosition.utxo, systemParams, lucid),
111
108
  );
112
109
  });
110
+
111
+ test<MyContext>('Staking - Distribute ADA to Stakers', async ({
112
+ lucid,
113
+ users,
114
+ }: MyContext) => {
115
+ lucid.selectWallet.fromSeed(users.admin.seedPhrase);
116
+ const [systemParams, _] = await init(lucid, [iusdInitialAssetCfg]);
117
+
118
+ await runAndAwaitTx(
119
+ lucid,
120
+ openStakingPosition(1_000_000n, systemParams, lucid),
121
+ );
122
+
123
+ const collectorOref = await findRandomCollector(
124
+ lucid,
125
+ systemParams.validatorHashes.collectorHash,
126
+ );
127
+ const tx = lucid.newTx();
128
+ await collectorFeeTx(100_000_000n, lucid, systemParams, tx, collectorOref);
129
+ await runAndAwaitTx(lucid, Promise.resolve(tx));
130
+
131
+ const collectorUtxo = (
132
+ await findAllCollectors(lucid, systemParams.validatorHashes.collectorHash)
133
+ ).find((utxo) => utxo.assets.lovelace > 100_000_000n);
134
+ if (!collectorUtxo) {
135
+ throw new Error('Expected a collector UTXO');
136
+ }
137
+
138
+ await runAndAwaitTx(
139
+ lucid,
140
+ distributeAda(
141
+ (await findStakingManager(systemParams, lucid)).utxo,
142
+ [collectorUtxo],
143
+ systemParams,
144
+ lucid,
145
+ ),
146
+ );
147
+
148
+ const [pkh, __] = await addrDetails(lucid);
149
+ const myStakingPosition = await findStakingPosition(
150
+ lucid,
151
+ systemParams.validatorHashes.stakingHash,
152
+ fromSystemParamsAsset(systemParams.stakingParams.stakingToken),
153
+ pkh.hash,
154
+ );
155
+
156
+ const [____, userValChange] = await getValueChangeAtAddressAfterAction(
157
+ lucid,
158
+ users.admin.address,
159
+ () =>
160
+ runAndAwaitTx(
161
+ lucid,
162
+ closeStakingPosition(myStakingPosition.utxo, systemParams, lucid),
163
+ ),
164
+ );
165
+
166
+ expect(lovelacesAmt(userValChange)).toBeGreaterThan(95_000_000n); // There is some loss due to tx fees.
167
+ });
@@ -1,61 +0,0 @@
1
- import {
2
- Assets,
3
- fromText,
4
- LucidEvolution,
5
- Network,
6
- ScriptHash,
7
- toUnit,
8
- } from '@lucid-evolution/lucid';
9
- import { createScriptAddress } from '../src/utils/lucid-utils';
10
- import {
11
- AssetClass,
12
- IAssetContent,
13
- runOneShotMintTx,
14
- serialiseIAssetDatum,
15
- } from '../src';
16
-
17
- /**
18
- * TODO: the NFT has to be minted using the auth policy based on execute NFT.
19
- * This is just a mocked setup for test purposes.
20
- *
21
- * @returns NFT of the iAsset.
22
- */
23
- export async function runCreateIAsset(
24
- lucid: LucidEvolution,
25
- network: Network,
26
- cdpScriptHash: ScriptHash,
27
- iasset: IAssetContent,
28
- ): Promise<AssetClass> {
29
- const nftTokenName = fromText('IASSET_NFT');
30
- const utxos = await lucid.wallet().getUtxos();
31
- const nftPolicyId = await runOneShotMintTx(lucid, {
32
- referenceOutRef: {
33
- txHash: utxos[0].txHash,
34
- outputIdx: BigInt(utxos[0].outputIndex),
35
- },
36
- mintAmounts: [{ tokenName: nftTokenName, amount: 1n }],
37
- });
38
-
39
- const nftValue: Assets = { [toUnit(nftPolicyId, nftTokenName)]: 1n };
40
-
41
- const txHash = await lucid
42
- .newTx()
43
- .pay.ToContract(
44
- createScriptAddress(network, cdpScriptHash),
45
- {
46
- kind: 'inline',
47
- value: serialiseIAssetDatum(iasset),
48
- },
49
- nftValue,
50
- )
51
- .complete()
52
- .then((tx) => tx.sign.withWallet().complete())
53
- .then((tx) => tx.submit());
54
-
55
- await lucid.awaitTx(txHash);
56
-
57
- return {
58
- currencySymbol: nftPolicyId,
59
- tokenName: nftTokenName,
60
- };
61
- }