@indigo-labs/indigo-sdk 0.1.8 → 0.1.9

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.
package/dist/index.mjs CHANGED
@@ -5,6 +5,7 @@ import {
5
5
  credentialToAddress as credentialToAddress3,
6
6
  Data as Data10,
7
7
  fromText as fromText4,
8
+ slotToUnixTime as slotToUnixTime2,
8
9
  validatorToAddress as validatorToAddress3,
9
10
  validatorToScriptHash as validatorToScriptHash3
10
11
  } from "@lucid-evolution/lucid";
@@ -602,9 +603,30 @@ function calculateAccruedInterest(now, unitaryInterestSnapshot, mintedAmount, in
602
603
  }
603
604
  }
604
605
 
606
+ // src/helpers/price-oracle-helpers.ts
607
+ import {
608
+ slotToUnixTime,
609
+ unixTimeToSlot
610
+ } from "@lucid-evolution/lucid";
611
+ function oracleExpirationAwareValidity(currentSlot, biasTime, oracleExpiration, network) {
612
+ const validateFrom = slotToUnixTime(network, currentSlot - 1);
613
+ const defaultValidateTo = validateFrom + biasTime;
614
+ const cappedValidateTo = slotToUnixTime(
615
+ network,
616
+ unixTimeToSlot(network, oracleExpiration) - 1
617
+ );
618
+ const isOracleActuallyExpired = cappedValidateTo <= validateFrom;
619
+ return {
620
+ validFrom: validateFrom,
621
+ validTo: isOracleActuallyExpired ? defaultValidateTo : Math.min(defaultValidateTo, cappedValidateTo)
622
+ };
623
+ }
624
+
605
625
  // src/contracts/cdp.ts
606
626
  var CDPContract = class _CDPContract {
607
- static async openPosition(asset, collateralAmount, mintedAmount, params, lucid, assetRef, priceOracleRef, interestOracleRef, cdpCreatorRef, collectorRef, now = Date.now()) {
627
+ static async openPosition(asset, collateralAmount, mintedAmount, params, lucid, currentSlot, assetRef, priceOracleRef, interestOracleRef, cdpCreatorRef, collectorRef) {
628
+ const network = lucid.config().network;
629
+ const currentTime = BigInt(slotToUnixTime2(network, currentSlot));
608
630
  const [pkh, skh] = await addrDetails(lucid);
609
631
  const assetOut = await (assetRef ? IAssetHelpers.findIAssetByRef(assetRef, lucid) : IAssetHelpers.findIAssetByName(asset, params, lucid));
610
632
  if (!assetOut || !assetOut.datum) throw new Error("Unable to find IAsset");
@@ -630,7 +652,7 @@ var CDPContract = class _CDPContract {
630
652
  );
631
653
  const cdpCreatorOut = getRandomElement(
632
654
  cdpCreatorRef ? await lucid.utxosByOutRef([cdpCreatorRef]) : await lucid.utxosAtWithUnit(
633
- credentialToAddress3(lucid.config().network, {
655
+ credentialToAddress3(network, {
634
656
  type: "Script",
635
657
  hash: params.validatorHashes.cdpCreatorHash
636
658
  }),
@@ -642,7 +664,7 @@ var CDPContract = class _CDPContract {
642
664
  cdpOwner: pkh.hash,
643
665
  minted: mintedAmount,
644
666
  collateral: collateralAmount,
645
- currentTime: BigInt(now)
667
+ currentTime
646
668
  }
647
669
  });
648
670
  const cdpCreatorScriptRefUtxo = await scriptRef(
@@ -656,7 +678,7 @@ var CDPContract = class _CDPContract {
656
678
  };
657
679
  cdpValue[cdpToken] = 1n;
658
680
  const newSnapshot = calculateUnitaryInterestSinceOracleLastUpdated(
659
- BigInt(now),
681
+ currentTime,
660
682
  interestOracleDatum
661
683
  ) + interestOracleDatum.unitaryInterest;
662
684
  const cdpDatum = {
@@ -665,7 +687,7 @@ var CDPContract = class _CDPContract {
665
687
  mintedAmt: mintedAmount,
666
688
  cdpFees: {
667
689
  ActiveCDPInterestTracking: {
668
- lastSettled: BigInt(now),
690
+ lastSettled: currentTime,
669
691
  unitaryInterestSnapshot: newSnapshot
670
692
  }
671
693
  }
@@ -687,10 +709,12 @@ var CDPContract = class _CDPContract {
687
709
  BigInt(assetOut.datum.debtMintingFeePercentage.getOnChainInt),
688
710
  mintedAmount * oracleDatum.price.getOnChainInt / 1000000n
689
711
  );
690
- const cappedValidateTo = oracleDatum.expiration - 20001n;
691
- const timeValidFrom = now - 1e3;
692
- const timeValidTo_ = now + Number(params.cdpCreatorParams.biasTime) - 1e3;
693
- const timeValidTo = cappedValidateTo <= timeValidFrom ? timeValidTo_ : Math.min(timeValidTo_, Number(cappedValidateTo));
712
+ const txValidity = oracleExpirationAwareValidity(
713
+ currentSlot,
714
+ Number(params.cdpCreatorParams.biasTime),
715
+ Number(oracleDatum.expiration),
716
+ network
717
+ );
694
718
  const tx = lucid.newTx().collectFrom([cdpCreatorOut], Data10.to(cdpCreatorRedeemer)).readFrom([cdpCreatorScriptRefUtxo]).pay.ToContract(
695
719
  cdpAddress,
696
720
  { kind: "inline", value: serialiseCDPDatum(cdpDatum) },
@@ -699,7 +723,7 @@ var CDPContract = class _CDPContract {
699
723
  cdpCreatorOut.address,
700
724
  { kind: "inline", value: cdpCreatorOut.datum },
701
725
  cdpCreatorOut.assets
702
- ).readFrom([oracleOut, interestOracleOut, assetOut.utxo]).mintAssets(cdpTokenMintValue, Data10.to(new Constr3(0, []))).readFrom([cdpAuthTokenScriptRefUtxo]).mintAssets(iassetTokenMintValue, Data10.to(new Constr3(0, []))).readFrom([iAssetTokenScriptRefUtxo]).addSignerKey(pkh.hash).validFrom(Number(now - 100)).validTo(Number(timeValidTo));
726
+ ).readFrom([oracleOut, interestOracleOut, assetOut.utxo]).mintAssets(cdpTokenMintValue, Data10.to(new Constr3(0, []))).readFrom([cdpAuthTokenScriptRefUtxo]).mintAssets(iassetTokenMintValue, Data10.to(new Constr3(0, []))).readFrom([iAssetTokenScriptRefUtxo]).addSignerKey(pkh.hash).validFrom(txValidity.validFrom).validTo(txValidity.validTo);
703
727
  if (debtMintingFee > 0) {
704
728
  await CollectorContract.feeTx(
705
729
  debtMintingFee,
@@ -711,13 +735,14 @@ var CDPContract = class _CDPContract {
711
735
  }
712
736
  return tx;
713
737
  }
714
- static async deposit(cdpRef, amount, params, lucid, assetRef, priceOracleRef, interestOracleRef, collectorRef, govRef, treasuryRef) {
738
+ static async deposit(cdpRef, amount, params, lucid, currentSlot, assetRef, priceOracleRef, interestOracleRef, collectorRef, govRef, treasuryRef) {
715
739
  return _CDPContract.adjust(
716
740
  cdpRef,
717
741
  amount,
718
742
  0n,
719
743
  params,
720
744
  lucid,
745
+ currentSlot,
721
746
  assetRef,
722
747
  priceOracleRef,
723
748
  interestOracleRef,
@@ -726,13 +751,14 @@ var CDPContract = class _CDPContract {
726
751
  treasuryRef
727
752
  );
728
753
  }
729
- static async withdraw(cdpRef, amount, params, lucid, assetRef, priceOracleRef, interestOracleRef, collectorRef, govRef, treasuryRef) {
754
+ static async withdraw(cdpRef, amount, params, lucid, currentSlot, assetRef, priceOracleRef, interestOracleRef, collectorRef, govRef, treasuryRef) {
730
755
  return _CDPContract.adjust(
731
756
  cdpRef,
732
757
  -amount,
733
758
  0n,
734
759
  params,
735
760
  lucid,
761
+ currentSlot,
736
762
  assetRef,
737
763
  priceOracleRef,
738
764
  interestOracleRef,
@@ -741,13 +767,14 @@ var CDPContract = class _CDPContract {
741
767
  treasuryRef
742
768
  );
743
769
  }
744
- static async mint(cdpRef, amount, params, lucid, assetRef, priceOracleRef, interestOracleRef, collectorRef, govRef, treasuryRef) {
770
+ static async mint(cdpRef, amount, params, lucid, currentSlot, assetRef, priceOracleRef, interestOracleRef, collectorRef, govRef, treasuryRef) {
745
771
  return _CDPContract.adjust(
746
772
  cdpRef,
747
773
  0n,
748
774
  amount,
749
775
  params,
750
776
  lucid,
777
+ currentSlot,
751
778
  assetRef,
752
779
  priceOracleRef,
753
780
  interestOracleRef,
@@ -756,13 +783,14 @@ var CDPContract = class _CDPContract {
756
783
  treasuryRef
757
784
  );
758
785
  }
759
- static async burn(cdpRef, amount, params, lucid, assetRef, priceOracleRef, interestOracleRef, collectorRef, govRef, treasuryRef) {
786
+ static async burn(cdpRef, amount, params, lucid, currentSlot, assetRef, priceOracleRef, interestOracleRef, collectorRef, govRef, treasuryRef) {
760
787
  return _CDPContract.adjust(
761
788
  cdpRef,
762
789
  0n,
763
790
  -amount,
764
791
  params,
765
792
  lucid,
793
+ currentSlot,
766
794
  assetRef,
767
795
  priceOracleRef,
768
796
  interestOracleRef,
@@ -771,9 +799,10 @@ var CDPContract = class _CDPContract {
771
799
  treasuryRef
772
800
  );
773
801
  }
774
- static async adjust(cdpRef, collateralAmount, mintAmount, params, lucid, assetRef, priceOracleRef, interestOracleRef, collectorRef, govRef, treasuryRef) {
802
+ static async adjust(cdpRef, collateralAmount, mintAmount, params, lucid, currentSlot, assetRef, priceOracleRef, interestOracleRef, collectorRef, govRef, treasuryRef) {
803
+ const network = lucid.config().network;
775
804
  const [pkh, _] = await addrDetails(lucid);
776
- const now = Date.now();
805
+ const currentTime = BigInt(slotToUnixTime2(network, currentSlot));
777
806
  const cdp = (await lucid.utxosByOutRef([cdpRef]))[0];
778
807
  if (!cdp.datum) throw new Error("Unable to find CDP Datum");
779
808
  const cdpDatum = parseCDPDatum(cdp.datum);
@@ -800,14 +829,14 @@ var CDPContract = class _CDPContract {
800
829
  );
801
830
  const tx = lucid.newTx().collectFrom(
802
831
  [cdp],
803
- Data10.to(new Constr3(0, [BigInt(now), mintAmount, collateralAmount]))
832
+ Data10.to(new Constr3(0, [currentTime, mintAmount, collateralAmount]))
804
833
  ).readFrom([iAsset.utxo, gov, cdpScriptRefUtxo]).addSignerKey(pkh.hash);
805
834
  if (!cdp.datum) throw new Error("Unable to find CDP Datum");
806
835
  const cdpD = parseCDPDatum(cdp.datum);
807
836
  if (!("ActiveCDPInterestTracking" in cdpD.cdpFees))
808
837
  throw new Error("Invalid CDP Fees");
809
838
  const newSnapshot = calculateUnitaryInterestSinceOracleLastUpdated(
810
- BigInt(now),
839
+ currentTime,
811
840
  interestOracleDatum
812
841
  ) + interestOracleDatum.unitaryInterest;
813
842
  const cdpD_ = {
@@ -815,7 +844,7 @@ var CDPContract = class _CDPContract {
815
844
  mintedAmt: cdpD.mintedAmt + mintAmount,
816
845
  cdpFees: {
817
846
  ActiveCDPInterestTracking: {
818
- lastSettled: BigInt(now),
847
+ lastSettled: currentTime,
819
848
  unitaryInterestSnapshot: newSnapshot
820
849
  }
821
850
  }
@@ -837,11 +866,13 @@ var CDPContract = class _CDPContract {
837
866
  return Promise.reject(new Error("Invalid oracle input"));
838
867
  const od = parsePriceOracleDatum(oracleRefInput.datum);
839
868
  if (!od) return Promise.reject(new Error("Invalid oracle input"));
840
- const cappedValidateTo = od.expiration - 20001n;
841
- const timeValidFrom = now - 1e3;
842
- const timeValidTo_ = now + Number(params.cdpCreatorParams.biasTime) - 1e3;
843
- const timeValidTo = cappedValidateTo <= timeValidFrom ? timeValidTo_ : Math.min(timeValidTo_, Number(cappedValidateTo));
844
- tx.readFrom([oracleRefInput]).validFrom(Number(timeValidFrom)).validTo(Number(timeValidTo));
869
+ const txValidity = oracleExpirationAwareValidity(
870
+ currentSlot,
871
+ Number(params.cdpCreatorParams.biasTime),
872
+ Number(od.expiration),
873
+ network
874
+ );
875
+ tx.readFrom([oracleRefInput]).validFrom(txValidity.validFrom).validTo(txValidity.validTo);
845
876
  let fee = 0n;
846
877
  if (collateralAmount < 0) {
847
878
  fee += calculateFeeFromPercentage(
@@ -856,7 +887,7 @@ var CDPContract = class _CDPContract {
856
887
  );
857
888
  }
858
889
  const interestPaymentAsset = calculateAccruedInterest(
859
- BigInt(now),
890
+ currentTime,
860
891
  cdpD.cdpFees.ActiveCDPInterestTracking.unitaryInterestSnapshot,
861
892
  cdpD.mintedAmt,
862
893
  cdpD.cdpFees.ActiveCDPInterestTracking.lastSettled,
@@ -897,9 +928,10 @@ var CDPContract = class _CDPContract {
897
928
  }
898
929
  return tx;
899
930
  }
900
- static async close(cdpRef, params, lucid, assetRef, priceOracleRef, interestOracleRef, collectorRef, govRef, treasuryRef) {
931
+ static async close(cdpRef, params, lucid, currentSlot, assetRef, priceOracleRef, interestOracleRef, collectorRef, govRef, treasuryRef) {
932
+ const network = lucid.config().network;
901
933
  const [pkh, _] = await addrDetails(lucid);
902
- const now = Date.now();
934
+ const currentTime = BigInt(slotToUnixTime2(network, currentSlot));
903
935
  const cdp = (await lucid.utxosByOutRef([cdpRef]))[0];
904
936
  if (!cdp.datum) throw new Error("Unable to find CDP Datum");
905
937
  const cdpDatum = parseCDPDatum(cdp.datum);
@@ -921,7 +953,7 @@ var CDPContract = class _CDPContract {
921
953
  const interestOracleDatum = parseInterestOracleDatum(
922
954
  interestOracleOut.datum
923
955
  );
924
- const tx = lucid.newTx().collectFrom([cdp], Data10.to(new Constr3(1, [BigInt(now)]))).readFrom([iAsset.utxo, gov, cdpScriptRefUtxo]).addSignerKey(pkh.hash);
956
+ const tx = lucid.newTx().collectFrom([cdp], Data10.to(new Constr3(1, [currentTime]))).readFrom([iAsset.utxo, gov, cdpScriptRefUtxo]).addSignerKey(pkh.hash);
925
957
  if (!cdp.datum) throw new Error("Unable to find CDP Datum");
926
958
  const cdpD = parseCDPDatum(cdp.datum);
927
959
  if (!("ActiveCDPInterestTracking" in cdpD.cdpFees))
@@ -935,14 +967,16 @@ var CDPContract = class _CDPContract {
935
967
  if (!oracleRefInput.datum)
936
968
  return Promise.reject(new Error("Invalid oracle input"));
937
969
  const od = parsePriceOracleDatum(oracleRefInput.datum);
938
- const cappedValidateTo = od.expiration - 20001n;
939
- const timeValidFrom = now - 1e3;
940
- const timeValidTo_ = now + Number(params.cdpCreatorParams.biasTime) - 1e3;
941
- const timeValidTo = cappedValidateTo <= timeValidFrom ? timeValidTo_ : Math.min(timeValidTo_, Number(cappedValidateTo));
942
- tx.readFrom([oracleRefInput]).validFrom(Number(timeValidFrom)).validTo(Number(timeValidTo));
970
+ const txValidity = oracleExpirationAwareValidity(
971
+ currentSlot,
972
+ Number(params.cdpCreatorParams.biasTime),
973
+ Number(od.expiration),
974
+ network
975
+ );
976
+ tx.readFrom([oracleRefInput]).validFrom(txValidity.validFrom).validTo(txValidity.validTo);
943
977
  let fee = 0n;
944
978
  const interestPaymentAsset = calculateAccruedInterest(
945
- BigInt(now),
979
+ currentTime,
946
980
  cdpD.cdpFees.ActiveCDPInterestTracking.unitaryInterestSnapshot,
947
981
  cdpD.mintedAmt,
948
982
  cdpD.cdpFees.ActiveCDPInterestTracking.lastSettled,
@@ -2692,32 +2726,13 @@ function castLrpParams(params) {
2692
2726
 
2693
2727
  // src/contracts/lrp.ts
2694
2728
  import {
2695
- addAssets as addAssets3
2729
+ addAssets as addAssets3,
2730
+ unixTimeToSlot as unixTimeToSlot2,
2731
+ slotToUnixTime as slotToUnixTime3
2696
2732
  } from "@lucid-evolution/lucid";
2697
2733
  import { match as match5, P as P5 } from "ts-pattern";
2698
2734
  import { unzip, zip } from "fp-ts/lib/Array";
2699
2735
  import { reduceWithIndex } from "fp-ts/lib/Array";
2700
-
2701
- // src/helpers/price-oracle-helpers.ts
2702
- import {
2703
- slotToUnixTime,
2704
- unixTimeToSlot
2705
- } from "@lucid-evolution/lucid";
2706
- function oracleExpirationAwareValidity(currentSlot, biasTime, oracleExpiration, network) {
2707
- const validateFrom = slotToUnixTime(network, currentSlot - 1);
2708
- const defaultValidateTo = validateFrom + biasTime;
2709
- const cappedValidateTo = slotToUnixTime(
2710
- network,
2711
- unixTimeToSlot(network, oracleExpiration) - 1
2712
- );
2713
- const isOracleActuallyExpired = cappedValidateTo <= validateFrom;
2714
- return {
2715
- validFrom: validateFrom,
2716
- validTo: isOracleActuallyExpired ? defaultValidateTo : Math.min(defaultValidateTo, cappedValidateTo)
2717
- };
2718
- }
2719
-
2720
- // src/contracts/lrp.ts
2721
2736
  var MIN_UTXO_COLLATERAL_AMT = 2000000n;
2722
2737
  async function openLrp(assetTokenName, lovelacesAmt, maxPrice, lucid, lrpScriptHash, network, lrpStakeCredential) {
2723
2738
  const [ownPkh, _] = await addrDetails(lucid);
@@ -2748,7 +2763,7 @@ async function cancelLrp(lrpOutRef, lrpRefScriptOutRef, lucid) {
2748
2763
  );
2749
2764
  return lucid.newTx().readFrom([lrpScriptRefUtxo]).collectFrom([lrpUtxo], serialiseLrpRedeemer("Cancel")).addSigner(ownAddr);
2750
2765
  }
2751
- async function redeemLrp(redemptionLrpsData, lrpRefScriptOutRef, priceOracleOutRef, iassetOutRef, lucid, lrpParams, priceOracleParams, network, currentSlot) {
2766
+ async function redeemLrp(redemptionLrpsData, lrpRefScriptOutRef, priceOracleOutRef, iassetOutRef, lucid, lrpParams, network) {
2752
2767
  const lrpScriptRefUtxo = matchSingle(
2753
2768
  await lucid.utxosByOutRef([lrpRefScriptOutRef]),
2754
2769
  (_2) => new Error("Expected a single LRP Ref Script UTXO")
@@ -2830,13 +2845,12 @@ async function redeemLrp(redemptionLrpsData, lrpRefScriptOutRef, priceOracleOutR
2830
2845
  );
2831
2846
  }
2832
2847
  )(redemptionLrps);
2833
- const txValidity = oracleExpirationAwareValidity(
2834
- currentSlot,
2835
- Number(priceOracleParams.biasTime),
2836
- Number(priceOracleDatum.expiration),
2837
- network
2838
- );
2839
- return lucid.newTx().validFrom(txValidity.validFrom).validTo(txValidity.validTo).readFrom([lrpScriptRefUtxo]).readFrom([iassetUtxo, priceOracleUtxo]).compose(tx);
2848
+ return lucid.newTx().validTo(
2849
+ slotToUnixTime3(
2850
+ network,
2851
+ unixTimeToSlot2(network, Number(priceOracleDatum.expiration)) - 1
2852
+ )
2853
+ ).readFrom([lrpScriptRefUtxo]).readFrom([iassetUtxo, priceOracleUtxo]).compose(tx);
2840
2854
  }
2841
2855
  async function adjustLrp(lucid, lrpOutRef, lovelacesAdjustAmt, lrpRefScriptOutRef, lrpParams) {
2842
2856
  const ownAddr = await lucid.wallet().address();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@indigo-labs/indigo-sdk",
3
- "version": "0.1.8",
3
+ "version": "0.1.9",
4
4
  "description": "Indigo SDK for interacting with Indigo endpoints via lucid-evolution",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -13,7 +13,6 @@
13
13
  "format": "npx prettier --write src/ tests/",
14
14
  "format:check": "npx prettier --check src/ tests/",
15
15
  "test": "vitest run",
16
- "prepare": "husky",
17
16
  "lint-staged": "lint-staged"
18
17
  },
19
18
  "lint-staged": {
@@ -8,6 +8,7 @@ import {
8
8
  fromText,
9
9
  LucidEvolution,
10
10
  OutRef,
11
+ slotToUnixTime,
11
12
  SpendingValidator,
12
13
  TxBuilder,
13
14
  UTxO,
@@ -41,6 +42,7 @@ import {
41
42
  calculateAccruedInterest,
42
43
  calculateUnitaryInterestSinceOracleLastUpdated,
43
44
  } from '../helpers/interest-oracle';
45
+ import { oracleExpirationAwareValidity } from '../helpers/price-oracle-helpers';
44
46
 
45
47
  export class CDPContract {
46
48
  static async openPosition(
@@ -49,13 +51,16 @@ export class CDPContract {
49
51
  mintedAmount: bigint,
50
52
  params: SystemParams,
51
53
  lucid: LucidEvolution,
54
+ currentSlot: number,
52
55
  assetRef?: OutRef,
53
56
  priceOracleRef?: OutRef,
54
57
  interestOracleRef?: OutRef,
55
58
  cdpCreatorRef?: OutRef,
56
59
  collectorRef?: OutRef,
57
- now: number = Date.now(),
58
60
  ): Promise<TxBuilder> {
61
+ const network = lucid.config().network;
62
+ const currentTime = BigInt(slotToUnixTime(network, currentSlot));
63
+
59
64
  const [pkh, skh] = await addrDetails(lucid);
60
65
  const assetOut: IAssetOutput = await (assetRef
61
66
  ? IAssetHelpers.findIAssetByRef(assetRef, lucid)
@@ -93,7 +98,7 @@ export class CDPContract {
93
98
  cdpCreatorRef
94
99
  ? await lucid.utxosByOutRef([cdpCreatorRef])
95
100
  : await lucid.utxosAtWithUnit(
96
- credentialToAddress(lucid.config().network, {
101
+ credentialToAddress(network, {
97
102
  type: 'Script',
98
103
  hash: params.validatorHashes.cdpCreatorHash,
99
104
  }),
@@ -107,7 +112,7 @@ export class CDPContract {
107
112
  cdpOwner: pkh.hash,
108
113
  minted: mintedAmount,
109
114
  collateral: collateralAmount,
110
- currentTime: BigInt(now),
115
+ currentTime: currentTime,
111
116
  },
112
117
  });
113
118
 
@@ -127,7 +132,7 @@ export class CDPContract {
127
132
  cdpValue[cdpToken] = 1n;
128
133
  const newSnapshot =
129
134
  calculateUnitaryInterestSinceOracleLastUpdated(
130
- BigInt(now),
135
+ currentTime,
131
136
  interestOracleDatum,
132
137
  ) + interestOracleDatum.unitaryInterest;
133
138
  const cdpDatum: CDPContent = {
@@ -136,7 +141,7 @@ export class CDPContract {
136
141
  mintedAmt: mintedAmount,
137
142
  cdpFees: {
138
143
  ActiveCDPInterestTracking: {
139
- lastSettled: BigInt(now),
144
+ lastSettled: currentTime,
140
145
  unitaryInterestSnapshot: newSnapshot,
141
146
  },
142
147
  },
@@ -163,14 +168,12 @@ export class CDPContract {
163
168
  (mintedAmount * oracleDatum.price.getOnChainInt) / 1_000_000n,
164
169
  );
165
170
 
166
- // Oracle timestamp - 20s (length of a slot)
167
- const cappedValidateTo = oracleDatum.expiration - 20_001n;
168
- const timeValidFrom = now - 1_000;
169
- const timeValidTo_ = now + Number(params.cdpCreatorParams.biasTime) - 1_000;
170
- const timeValidTo =
171
- cappedValidateTo <= timeValidFrom
172
- ? timeValidTo_
173
- : Math.min(timeValidTo_, Number(cappedValidateTo));
171
+ const txValidity = oracleExpirationAwareValidity(
172
+ currentSlot,
173
+ Number(params.cdpCreatorParams.biasTime),
174
+ Number(oracleDatum.expiration),
175
+ network,
176
+ );
174
177
 
175
178
  const tx = lucid
176
179
  .newTx()
@@ -192,8 +195,8 @@ export class CDPContract {
192
195
  .mintAssets(iassetTokenMintValue, Data.to(new Constr(0, [])))
193
196
  .readFrom([iAssetTokenScriptRefUtxo])
194
197
  .addSignerKey(pkh.hash)
195
- .validFrom(Number(now - 100))
196
- .validTo(Number(timeValidTo));
198
+ .validFrom(txValidity.validFrom)
199
+ .validTo(txValidity.validTo);
197
200
 
198
201
  if (debtMintingFee > 0) {
199
202
  await CollectorContract.feeTx(
@@ -212,6 +215,7 @@ export class CDPContract {
212
215
  amount: bigint,
213
216
  params: SystemParams,
214
217
  lucid: LucidEvolution,
218
+ currentSlot: number,
215
219
  assetRef?: OutRef,
216
220
  priceOracleRef?: OutRef,
217
221
  interestOracleRef?: OutRef,
@@ -225,6 +229,7 @@ export class CDPContract {
225
229
  0n,
226
230
  params,
227
231
  lucid,
232
+ currentSlot,
228
233
  assetRef,
229
234
  priceOracleRef,
230
235
  interestOracleRef,
@@ -239,6 +244,7 @@ export class CDPContract {
239
244
  amount: bigint,
240
245
  params: SystemParams,
241
246
  lucid: LucidEvolution,
247
+ currentSlot: number,
242
248
  assetRef?: OutRef,
243
249
  priceOracleRef?: OutRef,
244
250
  interestOracleRef?: OutRef,
@@ -252,6 +258,7 @@ export class CDPContract {
252
258
  0n,
253
259
  params,
254
260
  lucid,
261
+ currentSlot,
255
262
  assetRef,
256
263
  priceOracleRef,
257
264
  interestOracleRef,
@@ -266,6 +273,7 @@ export class CDPContract {
266
273
  amount: bigint,
267
274
  params: SystemParams,
268
275
  lucid: LucidEvolution,
276
+ currentSlot: number,
269
277
  assetRef?: OutRef,
270
278
  priceOracleRef?: OutRef,
271
279
  interestOracleRef?: OutRef,
@@ -279,6 +287,7 @@ export class CDPContract {
279
287
  amount,
280
288
  params,
281
289
  lucid,
290
+ currentSlot,
282
291
  assetRef,
283
292
  priceOracleRef,
284
293
  interestOracleRef,
@@ -293,6 +302,7 @@ export class CDPContract {
293
302
  amount: bigint,
294
303
  params: SystemParams,
295
304
  lucid: LucidEvolution,
305
+ currentSlot: number,
296
306
  assetRef?: OutRef,
297
307
  priceOracleRef?: OutRef,
298
308
  interestOracleRef?: OutRef,
@@ -306,6 +316,7 @@ export class CDPContract {
306
316
  -amount,
307
317
  params,
308
318
  lucid,
319
+ currentSlot,
309
320
  assetRef,
310
321
  priceOracleRef,
311
322
  interestOracleRef,
@@ -321,6 +332,7 @@ export class CDPContract {
321
332
  mintAmount: bigint,
322
333
  params: SystemParams,
323
334
  lucid: LucidEvolution,
335
+ currentSlot: number,
324
336
  assetRef?: OutRef,
325
337
  priceOracleRef?: OutRef,
326
338
  interestOracleRef?: OutRef,
@@ -328,9 +340,10 @@ export class CDPContract {
328
340
  govRef?: OutRef,
329
341
  treasuryRef?: OutRef,
330
342
  ): Promise<TxBuilder> {
343
+ const network = lucid.config().network;
331
344
  // Find Pkh, Skh
332
345
  const [pkh, _] = await addrDetails(lucid);
333
- const now = Date.now();
346
+ const currentTime = BigInt(slotToUnixTime(network, currentSlot));
334
347
 
335
348
  // Find Outputs: iAsset Output, CDP Output, Gov Output
336
349
  const cdp = (await lucid.utxosByOutRef([cdpRef]))[0];
@@ -372,7 +385,7 @@ export class CDPContract {
372
385
  .newTx()
373
386
  .collectFrom(
374
387
  [cdp],
375
- Data.to(new Constr(0, [BigInt(now), mintAmount, collateralAmount])),
388
+ Data.to(new Constr(0, [currentTime, mintAmount, collateralAmount])),
376
389
  )
377
390
  .readFrom([iAsset.utxo, gov, cdpScriptRefUtxo])
378
391
  .addSignerKey(pkh.hash);
@@ -384,7 +397,7 @@ export class CDPContract {
384
397
 
385
398
  const newSnapshot =
386
399
  calculateUnitaryInterestSinceOracleLastUpdated(
387
- BigInt(now),
400
+ currentTime,
388
401
  interestOracleDatum,
389
402
  ) + interestOracleDatum.unitaryInterest;
390
403
 
@@ -393,7 +406,7 @@ export class CDPContract {
393
406
  mintedAmt: cdpD.mintedAmt + mintAmount,
394
407
  cdpFees: {
395
408
  ActiveCDPInterestTracking: {
396
- lastSettled: BigInt(now),
409
+ lastSettled: currentTime,
397
410
  unitaryInterestSnapshot: newSnapshot,
398
411
  },
399
412
  },
@@ -424,19 +437,15 @@ export class CDPContract {
424
437
  const od = parsePriceOracleDatum(oracleRefInput.datum);
425
438
  if (!od) return Promise.reject(new Error('Invalid oracle input'));
426
439
 
427
- // TODO: Sanity check: oacle expiration
428
- // Oracle timestamp - 20s (length of a slot)
429
- // Oracle timestamp - 20s (length of a slot)
430
- const cappedValidateTo = od.expiration - 20_001n;
431
- const timeValidFrom = now - 1_000;
432
- const timeValidTo_ = now + Number(params.cdpCreatorParams.biasTime) - 1_000;
433
- const timeValidTo =
434
- cappedValidateTo <= timeValidFrom
435
- ? timeValidTo_
436
- : Math.min(timeValidTo_, Number(cappedValidateTo));
440
+ const txValidity = oracleExpirationAwareValidity(
441
+ currentSlot,
442
+ Number(params.cdpCreatorParams.biasTime),
443
+ Number(od.expiration),
444
+ network,
445
+ );
437
446
  tx.readFrom([oracleRefInput])
438
- .validFrom(Number(timeValidFrom))
439
- .validTo(Number(timeValidTo));
447
+ .validFrom(txValidity.validFrom)
448
+ .validTo(txValidity.validTo);
440
449
 
441
450
  let fee = 0n;
442
451
  if (collateralAmount < 0) {
@@ -456,7 +465,7 @@ export class CDPContract {
456
465
  // Interest payment
457
466
 
458
467
  const interestPaymentAsset = calculateAccruedInterest(
459
- BigInt(now),
468
+ currentTime,
460
469
  cdpD.cdpFees.ActiveCDPInterestTracking.unitaryInterestSnapshot,
461
470
  cdpD.mintedAmt,
462
471
  cdpD.cdpFees.ActiveCDPInterestTracking.lastSettled,
@@ -510,6 +519,7 @@ export class CDPContract {
510
519
  cdpRef: OutRef,
511
520
  params: SystemParams,
512
521
  lucid: LucidEvolution,
522
+ currentSlot: number,
513
523
  assetRef?: OutRef,
514
524
  priceOracleRef?: OutRef,
515
525
  interestOracleRef?: OutRef,
@@ -517,9 +527,10 @@ export class CDPContract {
517
527
  govRef?: OutRef,
518
528
  treasuryRef?: OutRef,
519
529
  ): Promise<TxBuilder> {
530
+ const network = lucid.config().network;
520
531
  // Find Pkh, Skh
521
532
  const [pkh, _] = await addrDetails(lucid);
522
- const now = Date.now();
533
+ const currentTime = BigInt(slotToUnixTime(network, currentSlot));
523
534
 
524
535
  // Find Outputs: iAsset Output, CDP Output, Gov Output
525
536
  const cdp = (await lucid.utxosByOutRef([cdpRef]))[0];
@@ -557,7 +568,7 @@ export class CDPContract {
557
568
 
558
569
  const tx = lucid
559
570
  .newTx()
560
- .collectFrom([cdp], Data.to(new Constr(1, [BigInt(now)])))
571
+ .collectFrom([cdp], Data.to(new Constr(1, [currentTime])))
561
572
  .readFrom([iAsset.utxo, gov, cdpScriptRefUtxo])
562
573
  .addSignerKey(pkh.hash);
563
574
  if (!cdp.datum) throw new Error('Unable to find CDP Datum');
@@ -580,25 +591,21 @@ export class CDPContract {
580
591
  return Promise.reject(new Error('Invalid oracle input'));
581
592
  const od = parsePriceOracleDatum(oracleRefInput.datum);
582
593
 
583
- // TODO: Sanity check: oacle expiration
584
- // Oracle timestamp - 20s (length of a slot)
585
- // Oracle timestamp - 20s (length of a slot)
586
- const cappedValidateTo = od.expiration - 20_001n;
587
- const timeValidFrom = now - 1_000;
588
- const timeValidTo_ = now + Number(params.cdpCreatorParams.biasTime) - 1_000;
589
- const timeValidTo =
590
- cappedValidateTo <= timeValidFrom
591
- ? timeValidTo_
592
- : Math.min(timeValidTo_, Number(cappedValidateTo));
594
+ const txValidity = oracleExpirationAwareValidity(
595
+ currentSlot,
596
+ Number(params.cdpCreatorParams.biasTime),
597
+ Number(od.expiration),
598
+ network,
599
+ );
593
600
  tx.readFrom([oracleRefInput])
594
- .validFrom(Number(timeValidFrom))
595
- .validTo(Number(timeValidTo));
601
+ .validFrom(txValidity.validFrom)
602
+ .validTo(txValidity.validTo);
596
603
 
597
604
  let fee = 0n;
598
605
 
599
606
  // Interest payment
600
607
  const interestPaymentAsset = calculateAccruedInterest(
601
- BigInt(now),
608
+ currentTime,
602
609
  cdpD.cdpFees.ActiveCDPInterestTracking.unitaryInterestSnapshot,
603
610
  cdpD.mintedAmt,
604
611
  cdpD.cdpFees.ActiveCDPInterestTracking.lastSettled,