@indigo-labs/indigo-sdk 0.1.2 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. package/.github/workflows/ci.yml +62 -0
  2. package/.github/workflows/test.yml +44 -0
  3. package/.husky/pre-commit +1 -0
  4. package/.prettierrc +1 -1
  5. package/README.md +52 -7
  6. package/dist/index.d.mts +1064 -182
  7. package/dist/index.d.ts +1064 -182
  8. package/dist/index.js +2565 -561
  9. package/dist/index.mjs +2546 -593
  10. package/eslint.config.mjs +35 -0
  11. package/package.json +61 -43
  12. package/src/contracts/cdp.ts +208 -359
  13. package/src/contracts/collector.ts +13 -6
  14. package/src/contracts/gov.ts +1 -58
  15. package/src/contracts/interest-oracle.ts +139 -39
  16. package/src/contracts/lrp.ts +223 -0
  17. package/src/contracts/one-shot.ts +67 -0
  18. package/src/contracts/stability-pool.ts +684 -0
  19. package/src/contracts/staking.ts +348 -0
  20. package/src/contracts/treasury.ts +30 -13
  21. package/src/helpers/asset-helpers.ts +51 -22
  22. package/src/helpers/helper-txs.ts +30 -0
  23. package/src/helpers/helpers.ts +29 -8
  24. package/src/helpers/indigo-helpers.ts +19 -0
  25. package/src/helpers/interest-oracle.ts +57 -0
  26. package/src/helpers/lucid-utils.ts +62 -16
  27. package/src/helpers/price-oracle-helpers.ts +36 -0
  28. package/src/helpers/stability-pool-helpers.ts +207 -0
  29. package/src/helpers/staking-helpers.ts +94 -0
  30. package/src/helpers/time-helpers.ts +4 -3
  31. package/src/helpers/value-helpers.ts +16 -0
  32. package/src/index.ts +15 -4
  33. package/src/scripts/always-fail-validator.ts +7 -0
  34. package/src/scripts/auth-token-policy.ts +23 -0
  35. package/src/scripts/cdp-creator-validator.ts +46 -2
  36. package/src/scripts/collector-validator.ts +2 -2
  37. package/src/scripts/execute-validator.ts +52 -0
  38. package/src/scripts/gov-validator.ts +44 -0
  39. package/src/scripts/iasset-policy.ts +22 -0
  40. package/src/scripts/interest-oracle-validator.ts +18 -3
  41. package/src/scripts/lrp-validator.ts +23 -0
  42. package/src/scripts/one-shot-policy.ts +62 -0
  43. package/src/scripts/poll-manager-validator.ts +52 -0
  44. package/src/scripts/poll-shard-validator.ts +47 -0
  45. package/src/scripts/price-oracle-validator.ts +26 -0
  46. package/src/scripts/stability-pool-validator.ts +60 -0
  47. package/src/scripts/staking-validator.ts +8 -0
  48. package/src/scripts/version-record-policy.ts +26 -0
  49. package/src/scripts/version-registry.ts +15 -0
  50. package/src/types/generic.ts +99 -6
  51. package/src/types/indigo/cdp-creator.ts +46 -0
  52. package/src/types/indigo/cdp.ts +86 -31
  53. package/src/types/indigo/execute.ts +21 -0
  54. package/src/types/indigo/gov.ts +50 -20
  55. package/src/types/indigo/interest-oracle.ts +55 -5
  56. package/src/types/indigo/lrp.ts +54 -0
  57. package/src/types/indigo/poll-manager.ts +21 -0
  58. package/src/types/indigo/poll-shard.ts +16 -0
  59. package/src/types/indigo/price-oracle.ts +38 -4
  60. package/src/types/indigo/stability-pool.ts +233 -0
  61. package/src/types/indigo/staking.ts +99 -0
  62. package/src/types/indigo/version-record.ts +17 -0
  63. package/src/types/on-chain-decimal.ts +23 -0
  64. package/src/types/one-shot.ts +22 -0
  65. package/src/types/system-params.ts +95 -77
  66. package/tests/data/system-params.json +972 -972
  67. package/tests/datums.test.ts +279 -44
  68. package/tests/endpoints/initialize.ts +1013 -0
  69. package/tests/hash-checks.test.ts +71 -15
  70. package/tests/indigo-test-helpers.ts +115 -0
  71. package/tests/initialize.test.ts +27 -0
  72. package/tests/interest-calculations.test.ts +110 -133
  73. package/tests/interest-oracle.test.ts +90 -0
  74. package/tests/lrp.test.ts +149 -0
  75. package/tests/queries/governance-queries.ts +31 -0
  76. package/tests/queries/iasset-queries.ts +39 -0
  77. package/tests/queries/interest-oracle-queries.ts +13 -0
  78. package/tests/queries/lrp-queries.ts +39 -0
  79. package/tests/queries/price-oracle-queries.ts +27 -0
  80. package/tests/queries/stability-pool-queries.ts +75 -0
  81. package/tests/queries/staking-queries.ts +43 -0
  82. package/tests/stability-pool.test.ts +364 -0
  83. package/tests/staking.test.ts +105 -0
  84. package/tests/test-helpers.ts +38 -0
  85. package/tsconfig.build.json +4 -0
  86. package/tsconfig.json +8 -27
  87. package/vitest.config.ts +9 -0
  88. package/babel.config.cjs +0 -13
  89. package/examples/sample-cdp.ts +0 -43
  90. package/jest.config.js +0 -13
  91. package/src/contracts/cdp-creator.ts +0 -86
  92. package/src/contracts/price-oracle.ts +0 -24
  93. package/src/helpers/cdp-helpers.ts +0 -9
@@ -13,8 +13,13 @@ import {
13
13
  validatorToScriptHash,
14
14
  } from '@lucid-evolution/lucid';
15
15
  import { _collectorValidator } from '../scripts/collector-validator';
16
- import { CollectorParams, ScriptReferences, SystemParams } from '../types/system-params';
17
- import { getRandomElement, scriptRef } from '../helpers/lucid-utils';
16
+ import {
17
+ CollectorParams,
18
+ ScriptReferences,
19
+ SystemParams,
20
+ } from '../types/system-params';
21
+ import { scriptRef } from '../helpers/lucid-utils';
22
+ import { getRandomElement } from '../helpers/helpers';
18
23
 
19
24
  export class CollectorContract {
20
25
  static async feeTx(
@@ -26,9 +31,11 @@ export class CollectorContract {
26
31
  ): Promise<void> {
27
32
  const collectorUtxo: UTxO = collectorRef
28
33
  ? getRandomElement(await lucid.utxosByOutRef([collectorRef]))
29
- : getRandomElement(await lucid.utxosAt(
30
- CollectorContract.address(params.collectorParams, lucid),
31
- ));
34
+ : getRandomElement(
35
+ await lucid.utxosAt(
36
+ CollectorContract.address(params.collectorParams, lucid),
37
+ ),
38
+ );
32
39
 
33
40
  const collectorScriptRefUtxo = await CollectorContract.scriptRef(
34
41
  params.scriptReferences,
@@ -41,7 +48,7 @@ export class CollectorContract {
41
48
  { kind: 'inline', value: Data.to(new Constr(0, [])) },
42
49
  {
43
50
  ...collectorUtxo.assets,
44
- lovelace: collectorUtxo.assets['lovelace'] + fee,
51
+ lovelace: collectorUtxo.assets.lovelace + fee,
45
52
  },
46
53
  )
47
54
  .readFrom([collectorScriptRefUtxo]);
@@ -1,58 +1 @@
1
- import { Constr, Data } from '@lucid-evolution/lucid';
2
- import { GovDatum } from '../types/indigo/gov';
3
-
4
- export class GovContract {
5
- static decodeGovDatum(datum: string): GovDatum {
6
- const d = Data.from(datum) as any;
7
- if (
8
- d.index !== 0 ||
9
- d.fields.length !== 6 ||
10
- d.fields[1].fields.length !== 10
11
- )
12
- throw 'Invalid GovDatum found';
13
-
14
- return {
15
- currentProposal: d.fields[0],
16
- protocolParams: {
17
- proposalDeposit: d.fields[1].fields[0],
18
- votingPeriod: d.fields[1].fields[1],
19
- effectiveDelay: d.fields[1].fields[2],
20
- expirationPeriod: d.fields[1].fields[3],
21
- collateralFeePercentage: d.fields[1].fields[4].fields[0],
22
- proposingPeriod: d.fields[1].fields[5],
23
- totalShards: d.fields[1].fields[6],
24
- minimumQuorum: d.fields[1].fields[7],
25
- maxTreasuryLovelaceSpend: d.fields[1].fields[8],
26
- maxTreasuryIndySpend: d.fields[1].fields[9],
27
- },
28
- currentVersion: d.fields[2],
29
- iassetsCount: d.fields[3],
30
- activeProposals: d.fields[4],
31
- treasuryIndyWithdrawnAmt: d.fields[5],
32
- };
33
- }
34
-
35
- static encodeGovDatum(datum: GovDatum): string {
36
- return Data.to(
37
- new Constr(0, [
38
- datum.currentProposal,
39
- new Constr(0, [
40
- datum.protocolParams.proposalDeposit,
41
- datum.protocolParams.votingPeriod,
42
- datum.protocolParams.effectiveDelay,
43
- datum.protocolParams.expirationPeriod,
44
- new Constr(0, [datum.protocolParams.collateralFeePercentage]),
45
- datum.protocolParams.proposingPeriod,
46
- datum.protocolParams.totalShards,
47
- datum.protocolParams.minimumQuorum,
48
- datum.protocolParams.maxTreasuryLovelaceSpend,
49
- datum.protocolParams.maxTreasuryIndySpend,
50
- ]),
51
- datum.currentVersion,
52
- datum.iassetsCount,
53
- datum.activeProposals,
54
- datum.treasuryIndyWithdrawnAmt,
55
- ]),
56
- );
57
- }
58
- }
1
+ export class GovContract {}
@@ -1,49 +1,149 @@
1
- import { Constr, Data } from "@lucid-evolution/lucid";
2
- import { InterestOracleDatum } from "../types/indigo/interest-oracle";
3
- import { oneYear } from "../helpers/time-helpers";
4
-
5
- const unitaryInterestPrecision = 1_000_000_000_000_000_000n;
6
- const decimalUnit = 1_000_000n;
1
+ import {
2
+ fromText,
3
+ LucidEvolution,
4
+ OutRef,
5
+ toUnit,
6
+ TxBuilder,
7
+ UTxO,
8
+ validatorToAddress,
9
+ } from '@lucid-evolution/lucid';
10
+ import { AssetClass } from '../types/generic';
11
+ import {
12
+ InterestOracleParams,
13
+ parseInterestOracleDatum,
14
+ serialiseFeedInterestOracleRedeemer,
15
+ serialiseInterestOracleDatum,
16
+ } from '../types/indigo/interest-oracle';
17
+ import { oneShotMintTx } from './one-shot';
18
+ import { mkInterestOracleValidator } from '../scripts/interest-oracle-validator';
19
+ import { findInterestOracle } from '../../tests/queries/interest-oracle-queries';
20
+ import { ONE_SECOND } from '../helpers/time-helpers';
21
+ import { calculateUnitaryInterestSinceOracleLastUpdated } from '../helpers/interest-oracle';
7
22
 
8
23
  export class InterestOracleContract {
9
- static decodeInterestOracleDatum(datum: string): InterestOracleDatum {
10
- const oracleDatum = Data.from(datum) as any;
11
- if (oracleDatum.index != 0 || oracleDatum.fields.length !== 3 || oracleDatum.fields[1].index !== 0)
12
- throw 'Invalid Interest Oracle Datum provided.'
13
-
14
- return {
15
- unitaryInterest: oracleDatum.fields[0],
16
- interestRate: oracleDatum.fields[1].fields[0],
17
- lastUpdated: oracleDatum.fields[2],
18
- }
19
- }
20
-
21
- static encodeInterestOracleDatum(datum: InterestOracleDatum): string {
22
- return Data.to(
23
- new Constr(0, [
24
- datum.unitaryInterest,
25
- new Constr(0, [datum.interestRate]),
26
- datum.lastUpdated,
27
- ])
28
- )
24
+ static async startInterestOracle(
25
+ initialUnitaryInterest: bigint,
26
+ initialInterestRate: bigint,
27
+ initialLastInterestUpdate: bigint,
28
+ oracleParams: InterestOracleParams,
29
+ lucid: LucidEvolution,
30
+ withScriptRef: boolean = false,
31
+ refOutRef?: OutRef,
32
+ interestTokenName?: string,
33
+ ): Promise<[TxBuilder, AssetClass]> {
34
+ const tokenName = interestTokenName ?? 'INTEREST_ORACLE';
35
+ if (!refOutRef) {
36
+ refOutRef = (await lucid.wallet().getUtxos())[0];
29
37
  }
30
38
 
31
- static calculateUnitaryInterestSinceOracleLastUpdated(now: bigint, oracleDatum: InterestOracleDatum): bigint {
32
- return InterestOracleContract.calculateUnitaryInterest(now - oracleDatum.lastUpdated, oracleDatum.interestRate);
39
+ const [tx, policyId] = await oneShotMintTx(lucid, {
40
+ referenceOutRef: {
41
+ txHash: refOutRef.txHash,
42
+ outputIdx: BigInt(refOutRef.outputIndex),
43
+ },
44
+ mintAmounts: [
45
+ {
46
+ tokenName: fromText(tokenName),
47
+ amount: 1n,
48
+ },
49
+ ],
50
+ });
51
+
52
+ const validator = mkInterestOracleValidator(oracleParams);
53
+
54
+ tx.pay.ToContract(
55
+ validatorToAddress(lucid.config().network, validator),
56
+ {
57
+ kind: 'inline',
58
+ value: serialiseInterestOracleDatum({
59
+ unitaryInterest: initialUnitaryInterest,
60
+ interestRate: {
61
+ getOnChainInt: initialInterestRate,
62
+ },
63
+ lastUpdated: initialLastInterestUpdate,
64
+ }),
65
+ },
66
+ {
67
+ lovelace: 2_500_000n,
68
+ [toUnit(policyId, fromText(tokenName))]: 1n,
69
+ },
70
+ );
71
+
72
+ if (withScriptRef) {
73
+ tx.pay.ToAddressWithData(
74
+ validatorToAddress(lucid.config().network, validator),
75
+ undefined,
76
+ undefined,
77
+ validator,
78
+ );
33
79
  }
34
80
 
35
- static calculateUnitaryInterest(timePeriod: bigint, interestRate: bigint): bigint {
36
- return ((timePeriod * interestRate * unitaryInterestPrecision) / oneYear) / decimalUnit;
81
+ return [
82
+ tx,
83
+ {
84
+ currencySymbol: policyId,
85
+ tokenName: fromText(tokenName),
86
+ },
87
+ ];
88
+ }
89
+
90
+ static async feedInterestOracle(
91
+ params: InterestOracleParams,
92
+ newInterestRate: bigint,
93
+ lucid: LucidEvolution,
94
+ assetClass?: AssetClass,
95
+ utxo?: UTxO,
96
+ scriptRef?: UTxO,
97
+ ): Promise<TxBuilder> {
98
+ if (!assetClass && !utxo)
99
+ throw new Error('Either interest oracle nft or utxo must be provided');
100
+ if (assetClass && !utxo) {
101
+ const [ioUtxo, _datum] = await findInterestOracle(lucid, assetClass);
102
+ utxo = ioUtxo;
37
103
  }
38
104
 
39
- static calculateAccruedInterest(now: bigint, unitaryInterestSnapshot: bigint, mintedAmount: bigint, interestLastSettled: bigint, interestOracleDatum: InterestOracleDatum): bigint {
40
- if (interestOracleDatum.unitaryInterest >= unitaryInterestSnapshot) {
41
- const interestFromPreviousRates = ((interestOracleDatum.unitaryInterest - unitaryInterestSnapshot) * mintedAmount) / unitaryInterestPrecision;
42
- const lastRateInterest = (((now - interestOracleDatum.lastUpdated) * interestOracleDatum.interestRate * mintedAmount) / oneYear) / decimalUnit;
105
+ const now = BigInt(Date.now());
106
+ const tx = lucid.newTx();
107
+ const datum = parseInterestOracleDatum(utxo.datum);
43
108
 
44
- return interestFromPreviousRates + lastRateInterest;
45
- } else {
46
- return (((now - interestLastSettled) * interestOracleDatum.interestRate * mintedAmount) / oneYear) / decimalUnit;
47
- }
109
+ if (scriptRef) {
110
+ tx.readFrom([scriptRef]);
111
+ } else {
112
+ tx.attach.Script(mkInterestOracleValidator(params));
48
113
  }
49
- }
114
+
115
+ tx.collectFrom(
116
+ [utxo],
117
+ serialiseFeedInterestOracleRedeemer({
118
+ newInterestRate: {
119
+ getOnChainInt: newInterestRate,
120
+ },
121
+ currentTime: now,
122
+ }),
123
+ );
124
+
125
+ tx.pay.ToContract(
126
+ utxo.address,
127
+ {
128
+ kind: 'inline',
129
+ value: serialiseInterestOracleDatum({
130
+ unitaryInterest:
131
+ datum.unitaryInterest +
132
+ calculateUnitaryInterestSinceOracleLastUpdated(now, datum),
133
+ interestRate: {
134
+ getOnChainInt: newInterestRate,
135
+ },
136
+ lastUpdated: now,
137
+ }),
138
+ },
139
+ utxo.assets,
140
+ );
141
+
142
+ tx.validFrom(Number(now) - ONE_SECOND);
143
+ tx.validTo(Number(now + params.biasTime) - ONE_SECOND);
144
+
145
+ tx.addSignerKey(params.owner);
146
+
147
+ return tx;
148
+ }
149
+ }
@@ -0,0 +1,223 @@
1
+ import {
2
+ LucidEvolution,
3
+ Network,
4
+ ScriptHash,
5
+ TxBuilder,
6
+ Credential,
7
+ OutRef,
8
+ UTxO,
9
+ addAssets,
10
+ } from '@lucid-evolution/lucid';
11
+ import {
12
+ addrDetails,
13
+ createScriptAddress,
14
+ getInlineDatumOrThrow,
15
+ } from '../helpers/lucid-utils';
16
+ import { match, P } from 'ts-pattern';
17
+ import { unzip, zip } from 'fp-ts/lib/Array';
18
+ import { reduceWithIndex } from 'fp-ts/lib/Array';
19
+ import {
20
+ LRPDatum,
21
+ LRPParams,
22
+ parseLrpDatum,
23
+ serialiseLrpDatum,
24
+ serialiseLrpRedeemer,
25
+ } from '../types/indigo/lrp';
26
+ import {
27
+ parsePriceOracleDatum,
28
+ PriceOracleParams,
29
+ } from '../types/indigo/price-oracle';
30
+ import { ocdMul, OnChainDecimal } from '../types/on-chain-decimal';
31
+ import { parseIAssetDatum } from '../types/indigo/cdp';
32
+ import { mkAssetsOf, mkLovelacesOf } from '../helpers/value-helpers';
33
+ import { oracleExpirationAwareValidity } from '../helpers/price-oracle-helpers';
34
+ import { calculateFeeFromPercentage } from '../helpers/indigo-helpers';
35
+ import { matchSingle } from '../helpers/helpers';
36
+
37
+ const MIN_UTXO_COLLATERAL_AMT = 2_000_000n;
38
+
39
+ export async function openLrp(
40
+ assetTokenName: string,
41
+ lovelacesAmt: bigint,
42
+ maxPrice: OnChainDecimal,
43
+ lucid: LucidEvolution,
44
+ lrpScriptHash: ScriptHash,
45
+ network: Network,
46
+ lrpStakeCredential?: Credential,
47
+ ): Promise<TxBuilder> {
48
+ const [ownPkh, _] = await addrDetails(lucid);
49
+
50
+ const newDatum: LRPDatum = {
51
+ owner: ownPkh.hash,
52
+ iasset: assetTokenName,
53
+ maxPrice: maxPrice,
54
+ lovelacesToSpend: lovelacesAmt,
55
+ };
56
+
57
+ return lucid.newTx().pay.ToContract(
58
+ createScriptAddress(network, lrpScriptHash, lrpStakeCredential),
59
+ {
60
+ kind: 'inline',
61
+ value: serialiseLrpDatum(newDatum),
62
+ },
63
+ { lovelace: lovelacesAmt + MIN_UTXO_COLLATERAL_AMT },
64
+ );
65
+ }
66
+
67
+ export async function cancelLrp(
68
+ lrpOutRef: OutRef,
69
+ lrpRefScriptOutRef: OutRef,
70
+ lucid: LucidEvolution,
71
+ ): Promise<TxBuilder> {
72
+ const ownAddr = await lucid.wallet().address();
73
+ // TODO: use Promise.all
74
+ const lrpScriptRefUtxo = matchSingle(
75
+ await lucid.utxosByOutRef([lrpRefScriptOutRef]),
76
+ (_) => new Error('Expected a single LRP Ref Script UTXO'),
77
+ );
78
+
79
+ const lrpUtxo = matchSingle(
80
+ await lucid.utxosByOutRef([lrpOutRef]),
81
+ (_) => new Error('Expected a single LRP UTXO.'),
82
+ );
83
+
84
+ return lucid
85
+ .newTx()
86
+ .readFrom([lrpScriptRefUtxo])
87
+ .collectFrom([lrpUtxo], serialiseLrpRedeemer('Cancel'))
88
+ .addSigner(ownAddr);
89
+ }
90
+
91
+ export async function redeemLrp(
92
+ redemptionLrpsData: [OutRef, bigint][],
93
+ lrpRefScriptOutRef: OutRef,
94
+ priceOracleOutRef: OutRef,
95
+ iassetOutRef: OutRef,
96
+ lucid: LucidEvolution,
97
+ lrpParams: LRPParams,
98
+ priceOracleParams: PriceOracleParams,
99
+ network: Network,
100
+ ): Promise<TxBuilder> {
101
+ const lrpScriptRefUtxo = matchSingle(
102
+ await lucid.utxosByOutRef([lrpRefScriptOutRef]),
103
+ (_) => new Error('Expected a single LRP Ref Script UTXO'),
104
+ );
105
+
106
+ const priceOracleUtxo = matchSingle(
107
+ await lucid.utxosByOutRef([priceOracleOutRef]),
108
+ (_) => new Error('Expected a single price oracle UTXO'),
109
+ );
110
+
111
+ const iassetUtxo = matchSingle(
112
+ await lucid.utxosByOutRef([iassetOutRef]),
113
+ (_) => new Error('Expected a single IAsset UTXO'),
114
+ );
115
+
116
+ const iassetDatum = parseIAssetDatum(getInlineDatumOrThrow(iassetUtxo));
117
+
118
+ const [lrpsToRedeemOutRefs, lrpRedemptionIAssetAmt] =
119
+ unzip(redemptionLrpsData);
120
+
121
+ const priceOracleDatum = parsePriceOracleDatum(
122
+ getInlineDatumOrThrow(priceOracleUtxo),
123
+ );
124
+
125
+ const redemptionLrps = await lucid
126
+ .utxosByOutRef(lrpsToRedeemOutRefs)
127
+ .then((val) => zip(val, lrpRedemptionIAssetAmt));
128
+
129
+ const [[mainLrpUtxo, mainLrpRedemptionIAssetAmt], _] = match(redemptionLrps)
130
+ .with(
131
+ [P._, ...P.array()],
132
+ ([[firstLrp, firstLrpIAssetAmt], ...rest]): [
133
+ [UTxO, bigint],
134
+ [UTxO, bigint][],
135
+ ] => [[firstLrp, firstLrpIAssetAmt], rest],
136
+ )
137
+ .otherwise(() => {
138
+ throw new Error('Expects at least 1 UTXO to redeem.');
139
+ });
140
+
141
+ const mainLrpDatum = parseLrpDatum(getInlineDatumOrThrow(mainLrpUtxo));
142
+
143
+ const tx = reduceWithIndex<[UTxO, bigint], TxBuilder>(
144
+ lucid.newTx(),
145
+ (idx, acc, [lrpUtxo, redeemIAssetAmt]) => {
146
+ const lovelacesForRedemption = ocdMul(
147
+ {
148
+ getOnChainInt: mainLrpRedemptionIAssetAmt,
149
+ },
150
+ priceOracleDatum.price,
151
+ ).getOnChainInt;
152
+ const reimburstmentLovelaces = calculateFeeFromPercentage(
153
+ iassetDatum.redemptionReimbursementPercentage,
154
+ lovelacesForRedemption,
155
+ );
156
+
157
+ const lrpDatum = parseLrpDatum(getInlineDatumOrThrow(lrpUtxo));
158
+
159
+ return acc
160
+ .collectFrom(
161
+ [lrpUtxo],
162
+ serialiseLrpRedeemer(
163
+ idx === 0
164
+ ? { Redeem: { continuingOutputIdx: 0n } }
165
+ : {
166
+ RedeemAuxiliary: {
167
+ continuingOutputIdx: BigInt(idx),
168
+ mainRedeemOutRef: {
169
+ txHash: { hash: mainLrpUtxo.txHash },
170
+ outputIndex: BigInt(mainLrpUtxo.outputIndex),
171
+ },
172
+ asset: mainLrpDatum.iasset,
173
+ assetPrice: priceOracleDatum.price,
174
+ redemptionReimbursementPercentage:
175
+ iassetDatum.redemptionReimbursementPercentage,
176
+ },
177
+ },
178
+ ),
179
+ )
180
+ .pay.ToContract(
181
+ lrpUtxo.address,
182
+ {
183
+ kind: 'inline',
184
+ value: serialiseLrpDatum({
185
+ ...lrpDatum,
186
+ lovelacesToSpend:
187
+ lrpDatum.lovelacesToSpend - lovelacesForRedemption,
188
+ }),
189
+ },
190
+ addAssets(
191
+ lrpUtxo.assets,
192
+ mkLovelacesOf(-(lovelacesForRedemption - reimburstmentLovelaces)),
193
+ mkAssetsOf(
194
+ {
195
+ currencySymbol: lrpParams.iassetPolicyId,
196
+ tokenName: mainLrpDatum.iasset,
197
+ },
198
+ redeemIAssetAmt,
199
+ ),
200
+ ),
201
+ );
202
+ },
203
+ )(redemptionLrps);
204
+
205
+ const txValidity = oracleExpirationAwareValidity(
206
+ lucid.currentSlot(),
207
+ Number(priceOracleParams.biasTime),
208
+ Number(priceOracleDatum.expiration),
209
+ network,
210
+ );
211
+
212
+ return (
213
+ lucid
214
+ .newTx()
215
+ // .validFrom(txValidity.validFrom)
216
+ .validTo(txValidity.validTo)
217
+ // Ref script
218
+ .readFrom([lrpScriptRefUtxo])
219
+ // Ref inputs
220
+ .readFrom([iassetUtxo, priceOracleUtxo])
221
+ .compose(tx)
222
+ );
223
+ }
@@ -0,0 +1,67 @@
1
+ import {
2
+ addAssets,
3
+ Assets,
4
+ Constr,
5
+ Data,
6
+ LucidEvolution,
7
+ mintingPolicyToId,
8
+ PolicyId,
9
+ toUnit,
10
+ TxBuilder,
11
+ } from '@lucid-evolution/lucid';
12
+ import { OneShotParams } from '../types/one-shot';
13
+ import { matchSingle } from '../helpers/helpers';
14
+ import { mkOneShotPolicy } from '../scripts/one-shot-policy';
15
+ import { reduce } from 'fp-ts/lib/Array';
16
+
17
+ export async function oneShotMintTx(
18
+ lucid: LucidEvolution,
19
+ params: OneShotParams,
20
+ ): Promise<[TxBuilder, PolicyId]> {
21
+ const oneShotPolicy = mkOneShotPolicy(params);
22
+ const policyId = mintingPolicyToId(oneShotPolicy);
23
+
24
+ const refUtxo = matchSingle(
25
+ await lucid.utxosByOutRef([
26
+ {
27
+ txHash: params.referenceOutRef.txHash,
28
+ outputIndex: Number(params.referenceOutRef.outputIdx),
29
+ },
30
+ ]),
31
+ (_) => {
32
+ throw new Error('Cannot find the reference UTXO for one-shot.');
33
+ },
34
+ );
35
+
36
+ return [
37
+ lucid
38
+ .newTx()
39
+ .collectFrom([refUtxo])
40
+ .mintAssets(
41
+ reduce<{ tokenName: string; amount: bigint }, Assets>(
42
+ {},
43
+ (acc, entry) =>
44
+ addAssets(acc, {
45
+ [toUnit(policyId, entry.tokenName)]: entry.amount,
46
+ }),
47
+ )(params.mintAmounts),
48
+ Data.to(new Constr(0, [])),
49
+ )
50
+ .attach.MintingPolicy(oneShotPolicy),
51
+ policyId,
52
+ ];
53
+ }
54
+
55
+ export async function runOneShotMintTx(
56
+ lucid: LucidEvolution,
57
+ params: OneShotParams,
58
+ ): Promise<PolicyId> {
59
+ const [tx, policyId] = await oneShotMintTx(lucid, params);
60
+ const txHash = await tx
61
+ .complete()
62
+ .then((tx) => tx.sign.withWallet().complete())
63
+ .then((tx) => tx.submit());
64
+
65
+ await lucid.awaitTx(txHash);
66
+ return policyId;
67
+ }