@argonprotocol/mainchain 1.3.17 → 1.3.19

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/lib/index.cjs CHANGED
@@ -562,8 +562,7 @@ var Vault = class _Vault {
562
562
  baseFee,
563
563
  bitcoinXpub,
564
564
  tip,
565
- doNotExceedBalance,
566
- txProgressCallback
565
+ doNotExceedBalance
567
566
  } = args;
568
567
  let xpubBytes = _util.hexToU8a.call(void 0, bitcoinXpub);
569
568
  if (xpubBytes.length !== 78) {
@@ -606,7 +605,6 @@ var Vault = class _Vault {
606
605
  ...args,
607
606
  useLatestNonce: true
608
607
  });
609
- const tickDuration = await _asyncNullishCoalesce(config.tickDurationMillis, async () => ( await client.query.ticks.genesisTicker().then((x) => x.tickDurationMillis.toNumber())));
610
608
  async function getVault() {
611
609
  await result.waitForFinalizedBlock;
612
610
  let vaultId;
@@ -619,11 +617,7 @@ var Vault = class _Vault {
619
617
  if (vaultId === void 0) {
620
618
  throw new Error("Vault creation failed, no VaultCreated event found");
621
619
  }
622
- const rawVault = await client.query.vaults.vaultsById(vaultId);
623
- if (rawVault.isNone) {
624
- throw new Error("Vault creation failed, vault not found");
625
- }
626
- return new _Vault(vaultId, rawVault.unwrap(), tickDuration);
620
+ return _Vault.get(client, vaultId, config.tickDurationMillis);
627
621
  }
628
622
  return { getVault, txResult: result };
629
623
  }
@@ -645,25 +639,280 @@ function fromFixedNumber(value, decimals = FIXED_U128_DECIMALS) {
645
639
  var FIXED_U128_DECIMALS = 18;
646
640
  var PERMILL_DECIMALS = 6;
647
641
 
648
- // src/BitcoinLocks.ts
642
+ // src/BitcoinLock.ts
649
643
 
650
644
  var SATS_PER_BTC = 100000000n;
651
- var BitcoinLocks = class {
652
- constructor(client) {
653
- this.client = client;
645
+ var BitcoinLock = class _BitcoinLock {
646
+
647
+
648
+
649
+
650
+
651
+
652
+
653
+
654
+
655
+
656
+
657
+
658
+
659
+
660
+
661
+
662
+
663
+
664
+ constructor(data) {
665
+ this.utxoId = data.utxoId;
666
+ this.p2wshScriptHashHex = data.p2wshScriptHashHex;
667
+ this.vaultId = data.vaultId;
668
+ this.peggedPrice = data.peggedPrice;
669
+ this.liquidityPromised = data.liquidityPromised;
670
+ this.ownerAccount = data.ownerAccount;
671
+ this.satoshis = data.satoshis;
672
+ this.vaultPubkey = data.vaultPubkey;
673
+ this.securityFees = data.securityFees;
674
+ this.vaultClaimPubkey = data.vaultClaimPubkey;
675
+ this.ownerPubkey = data.ownerPubkey;
676
+ this.vaultXpubSources = data.vaultXpubSources;
677
+ this.vaultClaimHeight = data.vaultClaimHeight;
678
+ this.openClaimHeight = data.openClaimHeight;
679
+ this.createdAtHeight = data.createdAtHeight;
680
+ this.isVerified = data.isVerified;
681
+ this.isRejectedNeedsRelease = data.isRejectedNeedsRelease;
682
+ this.fundHoldExtensionsByBitcoinExpirationHeight = data.fundHoldExtensionsByBitcoinExpirationHeight;
683
+ }
684
+ /**
685
+ * Gets the UTXO reference by ID.
686
+ * @param client - client at the block height to query the UTXO reference at a specific point in time.
687
+ * @return An object containing the transaction ID and output index, or undefined if not found.
688
+ * @return.txid - The Bitcoin transaction ID of the UTXO.
689
+ * @return.vout - The output index of the UTXO in the transaction.
690
+ * @return.bitcoinTxid - The Bitcoin transaction ID of the UTXO formatted in little endian
691
+ */
692
+ async getUtxoRef(client) {
693
+ const refRaw = await client.query.bitcoinUtxos.utxoIdToRef(this.utxoId);
694
+ if (!refRaw) {
695
+ return;
696
+ }
697
+ const ref = refRaw.unwrap();
698
+ const txid = _util.u8aToHex.call(void 0, ref.txid);
699
+ const bitcoinTxid = _util.u8aToHex.call(void 0, ref.txid.reverse());
700
+ const vout = ref.outputIndex.toNumber();
701
+ return { txid, vout, bitcoinTxid };
702
+ }
703
+ async findPendingMints(client) {
704
+ const pendingMint = await client.query.mint.pendingMintUtxos();
705
+ const mintsPending = [];
706
+ for (const [utxoIdRaw, _accountId, mintAmountRaw] of pendingMint) {
707
+ if (utxoIdRaw.toNumber() === this.utxoId) {
708
+ mintsPending.push(mintAmountRaw.toBigInt());
709
+ }
710
+ }
711
+ return mintsPending;
654
712
  }
655
- async getUtxoIdFromEvents(events) {
713
+ async getRatchetPrice(client, priceIndex, vault) {
714
+ const { createdAtHeight, vaultClaimHeight, peggedPrice, satoshis } = this;
715
+ const marketRate = await _BitcoinLock.getMarketRate(priceIndex, BigInt(satoshis));
716
+ let ratchetingFee = vault.terms.bitcoinBaseFee;
717
+ let burnAmount = 0n;
718
+ if (marketRate > peggedPrice) {
719
+ const lockFee = vault.calculateBitcoinFee(marketRate);
720
+ const currentBitcoinHeight = await client.query.bitcoinUtxos.confirmedBitcoinBlockTip().then((x) => x.unwrap().blockHeight.toNumber());
721
+ const blockLength = vaultClaimHeight - createdAtHeight;
722
+ const elapsed = (currentBitcoinHeight - createdAtHeight) / blockLength;
723
+ const remainingDuration = 1 - elapsed;
724
+ ratchetingFee = BigInt(remainingDuration * Number(lockFee));
725
+ } else {
726
+ burnAmount = await this.releasePrice(priceIndex);
727
+ }
728
+ return {
729
+ ratchetingFee,
730
+ burnAmount,
731
+ marketRate
732
+ };
733
+ }
734
+ async ratchet(args) {
735
+ const { priceIndex, argonKeyring, tip = 0n, vault, client } = args;
736
+ const ratchetPrice = await this.getRatchetPrice(client, priceIndex, vault);
737
+ const txSubmitter = new TxSubmitter(
738
+ client,
739
+ client.tx.bitcoinLocks.ratchet(this.utxoId),
740
+ argonKeyring
741
+ );
742
+ const canAfford = await txSubmitter.canAfford({
743
+ tip,
744
+ unavailableBalance: BigInt(ratchetPrice.burnAmount + ratchetPrice.ratchetingFee)
745
+ });
746
+ if (!canAfford.canAfford) {
747
+ throw new Error(
748
+ `Insufficient funds to ratchet lock. Available: ${formatArgons(canAfford.availableBalance)}, Required: ${formatArgons(
749
+ ratchetPrice.burnAmount + ratchetPrice.ratchetingFee
750
+ )}`
751
+ );
752
+ }
753
+ const txResult = await txSubmitter.submit(args);
754
+ const getRatchetResult = async () => {
755
+ const blockHash = await txResult.waitForFinalizedBlock;
756
+ const ratchetEvent = txResult.events.find(
757
+ (x) => client.events.bitcoinLocks.BitcoinLockRatcheted.is(x)
758
+ );
759
+ if (!ratchetEvent) {
760
+ throw new Error(`Ratchet event not found in transaction events`);
761
+ }
762
+ const api = await client.at(blockHash);
763
+ const bitcoinBlockHeight = await api.query.bitcoinUtxos.confirmedBitcoinBlockTip().then((x) => x.unwrap().blockHeight.toNumber());
764
+ const {
765
+ amountBurned,
766
+ liquidityPromised: liquidityPromisedRaw,
767
+ newPeggedPrice,
768
+ originalPeggedPrice,
769
+ securityFee
770
+ } = ratchetEvent.data;
771
+ const liquidityPromised = liquidityPromisedRaw.toBigInt();
772
+ let mintAmount = liquidityPromised;
773
+ if (liquidityPromised > originalPeggedPrice.toBigInt()) {
774
+ mintAmount -= originalPeggedPrice.toBigInt();
775
+ }
776
+ return {
777
+ txFee: _nullishCoalesce(txResult.finalFee, () => ( 0n)),
778
+ blockHeight: txResult.blockNumber,
779
+ bitcoinBlockHeight,
780
+ pendingMint: mintAmount,
781
+ liquidityPromised,
782
+ newPeggedPrice: newPeggedPrice.toBigInt(),
783
+ burned: amountBurned.toBigInt(),
784
+ securityFee: securityFee.toBigInt()
785
+ };
786
+ };
787
+ return {
788
+ txResult,
789
+ getRatchetResult
790
+ };
791
+ }
792
+ async releasePrice(priceIndex) {
793
+ return await _BitcoinLock.getRedemptionRate(priceIndex, this);
794
+ }
795
+ async requestRelease(args) {
796
+ const {
797
+ priceIndex,
798
+ releaseRequest: { bitcoinNetworkFee, toScriptPubkey },
799
+ argonKeyring,
800
+ tip = 0n,
801
+ client
802
+ } = args;
803
+ if (!toScriptPubkey.startsWith("0x")) {
804
+ throw new Error("toScriptPubkey must be a hex string starting with 0x");
805
+ }
806
+ const submitter = new TxSubmitter(
807
+ client,
808
+ client.tx.bitcoinLocks.requestRelease(this.utxoId, toScriptPubkey, bitcoinNetworkFee),
809
+ argonKeyring
810
+ );
811
+ const redemptionPrice = await _BitcoinLock.getRedemptionRate(priceIndex, this);
812
+ const canAfford = await submitter.canAfford({
813
+ tip,
814
+ unavailableBalance: BigInt(redemptionPrice)
815
+ });
816
+ if (!canAfford.canAfford) {
817
+ throw new Error(
818
+ `Insufficient funds to release lock. Available: ${formatArgons(canAfford.availableBalance)}, Required: ${formatArgons(redemptionPrice + canAfford.txFee + tip)}`
819
+ );
820
+ }
821
+ return submitter.submit({
822
+ logResults: true,
823
+ ...args
824
+ });
825
+ }
826
+ async getReleaseRequest(client) {
827
+ const requestMaybe = await client.query.bitcoinLocks.lockReleaseRequestsByUtxoId(this.utxoId);
828
+ if (!requestMaybe.isSome) {
829
+ return void 0;
830
+ }
831
+ const request = requestMaybe.unwrap();
832
+ return {
833
+ toScriptPubkey: request.toScriptPubkey.toHex(),
834
+ bitcoinNetworkFee: request.bitcoinNetworkFee.toBigInt(),
835
+ dueFrame: request.cosignDueFrame.toNumber(),
836
+ vaultId: request.vaultId.toNumber(),
837
+ redemptionPrice: request.redemptionPrice.toBigInt()
838
+ };
839
+ }
840
+ /**
841
+ * Finds the cosign signature for a vault lock by UTXO ID. Optionally waits for the signature
842
+ * @param client - The Argon client with rpc access
843
+ * @param finalizedStateOnly - If true, only checks finalized state
844
+ * @param waitForSignatureMillis - Optional timeout in milliseconds to wait for the signature. If -1, waits indefinitely.
845
+ */
846
+ async findVaultCosignSignature(client, finalizedStateOnly = false, waitForSignatureMillis) {
847
+ let queryClient = client;
848
+ if (finalizedStateOnly) {
849
+ const finalizedHead = await client.rpc.chain.getFinalizedHead();
850
+ queryClient = await client.at(finalizedHead);
851
+ }
852
+ const releaseHeight = await queryClient.query.bitcoinLocks.lockReleaseCosignHeightById(
853
+ this.utxoId
854
+ );
855
+ if (releaseHeight.isSome) {
856
+ const releaseHeightValue = releaseHeight.unwrap().toNumber();
857
+ const signature = await this.getVaultCosignSignature(client, releaseHeightValue);
858
+ if (signature) {
859
+ return { blockHeight: releaseHeightValue, signature };
860
+ }
861
+ }
862
+ if (!waitForSignatureMillis) {
863
+ return void 0;
864
+ }
865
+ return await new Promise(async (resolve, reject) => {
866
+ let timeout;
867
+ const unsub = await client.rpc.chain.subscribeNewHeads((header) => {
868
+ const atHeight = header.number.toNumber();
869
+ this.getVaultCosignSignature(client, atHeight).then((signature) => {
870
+ if (signature) {
871
+ _optionalChain([unsub, 'optionalCall', _3 => _3()]);
872
+ clearTimeout(timeout);
873
+ resolve({ signature, blockHeight: atHeight });
874
+ }
875
+ }).catch((err) => {
876
+ console.error(`Error checking for cosign signature at height ${atHeight}:`, err);
877
+ });
878
+ });
879
+ if (waitForSignatureMillis !== -1) {
880
+ timeout = setTimeout(() => {
881
+ _optionalChain([unsub, 'optionalCall', _4 => _4()]);
882
+ reject(new Error(`Timeout waiting for cosign signature for UTXO ID ${this.utxoId}`));
883
+ }, waitForSignatureMillis);
884
+ }
885
+ });
886
+ }
887
+ async getVaultCosignSignature(client, atHeight) {
888
+ const blockHash = await _BitcoinLock.blockHashAtHeight(client, atHeight);
889
+ if (!blockHash) {
890
+ console.warn(`Block hash not found for height ${atHeight}`);
891
+ return void 0;
892
+ }
893
+ const blockEvents = await client.at(blockHash).then((api) => api.query.system.events());
894
+ for (const event of blockEvents) {
895
+ if (client.events.bitcoinLocks.BitcoinUtxoCosigned.is(event.event)) {
896
+ const { utxoId: id, signature } = event.event.data;
897
+ if (id.toNumber() === this.utxoId) {
898
+ return new Uint8Array(signature);
899
+ }
900
+ }
901
+ }
902
+ return void 0;
903
+ }
904
+ static async getUtxoIdFromEvents(client, events) {
656
905
  for (const event of events) {
657
- if (this.client.events.bitcoinLocks.BitcoinLockCreated.is(event)) {
906
+ if (client.events.bitcoinLocks.BitcoinLockCreated.is(event)) {
658
907
  return event.data.utxoId.toNumber();
659
908
  }
660
909
  }
661
910
  return void 0;
662
911
  }
663
- async getMarketRate(priceIndex, satoshis) {
912
+ static async getMarketRate(priceIndex, satoshis) {
664
913
  return priceIndex.getBtcMicrogonPrice(satoshis);
665
914
  }
666
- async getRedemptionRate(priceIndex, details) {
915
+ static async getRedemptionRate(priceIndex, details) {
667
916
  const { satoshis, peggedPrice } = details;
668
917
  const satsPerArgon = Number(SATS_PER_BTC) / MICROGONS_PER_ARGON;
669
918
  let price = Number(priceIndex.btcUsdPrice);
@@ -684,28 +933,7 @@ var BitcoinLocks = class {
684
933
  }
685
934
  return BigInt(Math.floor(price * multiplier));
686
935
  }
687
- async getMarketRateApi(satoshis) {
688
- const client = this.client;
689
- const sats = client.createType("U64", satoshis.toString());
690
- const marketRate = await client.rpc.state.call("BitcoinApis_market_rate", sats.toHex(true));
691
- const rate = client.createType("Option<U128>", marketRate);
692
- if (!rate.isSome) {
693
- throw new Error("Market rate not available");
694
- }
695
- return rate.value.toBigInt();
696
- }
697
- async getRedemptionRateApi(satoshis) {
698
- const client = this.client;
699
- const sats = client.createType("U64", satoshis.toString());
700
- const marketRate = await client.rpc.state.call("BitcoinApis_redemption_rate", sats.toHex(true));
701
- const rate = client.createType("Option<U128>", marketRate);
702
- if (!rate.isSome) {
703
- throw new Error("Redemption rate not available");
704
- }
705
- return rate.value.toBigInt();
706
- }
707
- async getConfig() {
708
- const client = this.client;
936
+ static async getConfig(client) {
709
937
  const bitcoinNetwork = await client.query.bitcoinUtxos.bitcoinNetwork();
710
938
  return {
711
939
  lockReleaseCosignDeadlineFrames: client.consts.bitcoinLocks.lockReleaseCosignDeadlineFrames.toNumber(),
@@ -714,48 +942,11 @@ var BitcoinLocks = class {
714
942
  bitcoinNetwork
715
943
  };
716
944
  }
717
- async getBitcoinConfirmedBlockHeight() {
718
- return await this.client.query.bitcoinUtxos.confirmedBitcoinBlockTip().then((x) => _nullishCoalesce(_optionalChain([x, 'access', _3 => _3.value, 'optionalAccess', _4 => _4.blockHeight, 'access', _5 => _5.toNumber, 'call', _6 => _6()]), () => ( 0)));
945
+ static async getBitcoinConfirmedBlockHeight(client) {
946
+ return await client.query.bitcoinUtxos.confirmedBitcoinBlockTip().then((x) => _nullishCoalesce(_optionalChain([x, 'access', _5 => _5.value, 'optionalAccess', _6 => _6.blockHeight, 'access', _7 => _7.toNumber, 'call', _8 => _8()]), () => ( 0)));
719
947
  }
720
- /**
721
- * Gets the UTXO reference by ID.
722
- * @param utxoId - The UTXO ID to look up.
723
- * @param clientAtHeight - Optional client at the block height to query the UTXO reference at a specific point in time.
724
- * @return An object containing the transaction ID and output index, or undefined if not found.
725
- * @return.txid - The Bitcoin transaction ID of the UTXO.
726
- * @return.vout - The output index of the UTXO in the transaction.
727
- * @return.bitcoinTxid - The Bitcoin transaction ID of the UTXO formatted in little endian
728
- */
729
- async getUtxoRef(utxoId, clientAtHeight) {
730
- const client = _nullishCoalesce(clientAtHeight, () => ( this.client));
731
- const refRaw = await client.query.bitcoinUtxos.utxoIdToRef(utxoId);
732
- if (!refRaw) {
733
- return;
734
- }
735
- const ref = refRaw.unwrap();
736
- const txid = _util.u8aToHex.call(void 0, ref.txid);
737
- const bitcoinTxid = _util.u8aToHex.call(void 0, ref.txid.reverse());
738
- const vout = ref.outputIndex.toNumber();
739
- return { txid, vout, bitcoinTxid };
740
- }
741
- async getReleaseRequest(utxoId, clientAtHeight) {
742
- const client = _nullishCoalesce(clientAtHeight, () => ( this.client));
743
- const requestMaybe = await client.query.bitcoinLocks.lockReleaseRequestsByUtxoId(utxoId);
744
- if (!requestMaybe.isSome) {
745
- return void 0;
746
- }
747
- const request = requestMaybe.unwrap();
748
- return {
749
- toScriptPubkey: request.toScriptPubkey.toHex(),
750
- bitcoinNetworkFee: request.bitcoinNetworkFee.toBigInt(),
751
- dueFrame: request.cosignDueFrame.toNumber(),
752
- vaultId: request.vaultId.toNumber(),
753
- redemptionPrice: request.redemptionPrice.toBigInt()
754
- };
755
- }
756
- async submitVaultSignature(args) {
757
- const { utxoId, vaultSignature, argonKeyring, txProgressCallback } = args;
758
- const client = this.client;
948
+ static async submitVaultSignature(args) {
949
+ const { utxoId, vaultSignature, argonKeyring, client } = args;
759
950
  if (!vaultSignature || vaultSignature.byteLength < 70 || vaultSignature.byteLength > 73) {
760
951
  throw new Error(
761
952
  `Invalid vault signature length: ${vaultSignature.byteLength}. Must be 70-73 bytes.`
@@ -766,8 +957,8 @@ var BitcoinLocks = class {
766
957
  const submitter = new TxSubmitter(client, tx, argonKeyring);
767
958
  return await submitter.submit(args);
768
959
  }
769
- async getBitcoinLock(utxoId) {
770
- const utxoRaw = await this.client.query.bitcoinLocks.locksByUtxoId(utxoId);
960
+ static async get(client, utxoId) {
961
+ const utxoRaw = await client.query.bitcoinLocks.locksByUtxoId(utxoId);
771
962
  if (!utxoRaw.isSome) {
772
963
  return;
773
964
  }
@@ -798,7 +989,7 @@ var BitcoinLocks = class {
798
989
  const fundHoldExtensionsByBitcoinExpirationHeight = Object.fromEntries(
799
990
  [...utxo.fundHoldExtensions.entries()].map(([x, y]) => [x.toNumber(), y.toBigInt()])
800
991
  );
801
- return {
992
+ return new _BitcoinLock({
802
993
  utxoId,
803
994
  p2wshScriptHashHex,
804
995
  vaultId,
@@ -817,50 +1008,9 @@ var BitcoinLocks = class {
817
1008
  isVerified,
818
1009
  isRejectedNeedsRelease,
819
1010
  fundHoldExtensionsByBitcoinExpirationHeight
820
- };
821
- }
822
- /**
823
- * Finds the cosign signature for a vault lock by UTXO ID. Optionally waits for the signature
824
- * @param utxoId - The UTXO ID of the bitcoin lock
825
- * @param waitForSignatureMillis - Optional timeout in milliseconds to wait for the signature. If -1, waits indefinitely.
826
- */
827
- async findVaultCosignSignature(utxoId, waitForSignatureMillis) {
828
- const client = this.client;
829
- const releaseHeight = await client.query.bitcoinLocks.lockReleaseCosignHeightById(utxoId);
830
- if (releaseHeight.isSome) {
831
- const releaseHeightValue = releaseHeight.unwrap().toNumber();
832
- const signature = await this.getVaultCosignSignature(utxoId, releaseHeightValue);
833
- if (signature) {
834
- return { blockHeight: releaseHeightValue, signature };
835
- }
836
- }
837
- if (!waitForSignatureMillis) {
838
- return void 0;
839
- }
840
- return await new Promise(async (resolve, reject) => {
841
- let timeout;
842
- const unsub = await client.rpc.chain.subscribeNewHeads((header) => {
843
- const atHeight = header.number.toNumber();
844
- this.getVaultCosignSignature(utxoId, atHeight).then((signature) => {
845
- if (signature) {
846
- _optionalChain([unsub, 'optionalCall', _7 => _7()]);
847
- clearTimeout(timeout);
848
- resolve({ signature, blockHeight: atHeight });
849
- }
850
- }).catch((err) => {
851
- console.error(`Error checking for cosign signature at height ${atHeight}:`, err);
852
- });
853
- });
854
- if (waitForSignatureMillis !== -1) {
855
- timeout = setTimeout(() => {
856
- _optionalChain([unsub, 'optionalCall', _8 => _8()]);
857
- reject(new Error(`Timeout waiting for cosign signature for UTXO ID ${utxoId}`));
858
- }, waitForSignatureMillis);
859
- }
860
1011
  });
861
1012
  }
862
- async blockHashAtHeight(atHeight) {
863
- const client = this.client;
1013
+ static async blockHashAtHeight(client, atHeight) {
864
1014
  for (let i = 0; i < 10; i++) {
865
1015
  const currentHeight = await client.query.system.number().then((x) => x.toNumber());
866
1016
  if (atHeight > currentHeight) {
@@ -880,37 +1030,16 @@ var BitcoinLocks = class {
880
1030
  }
881
1031
  return void 0;
882
1032
  }
883
- async getVaultCosignSignature(utxoId, atHeight) {
884
- const client = this.client;
885
- const blockHash = await this.blockHashAtHeight(atHeight);
886
- if (!blockHash) {
887
- console.warn(`Block hash not found for height ${atHeight}`);
888
- return void 0;
889
- }
890
- const blockEvents = await client.at(blockHash).then((api) => api.query.system.events());
891
- for (const event of blockEvents) {
892
- if (client.events.bitcoinLocks.BitcoinUtxoCosigned.is(event.event)) {
893
- const { utxoId: id, signature } = event.event.data;
894
- if (id.toNumber() === utxoId) {
895
- return new Uint8Array(signature);
896
- }
897
- }
898
- }
899
- return void 0;
900
- }
901
- async findPendingMints(utxoId) {
902
- const pendingMint = await this.client.query.mint.pendingMintUtxos();
903
- const mintsPending = [];
904
- for (const [utxoIdRaw, _accountId, mintAmountRaw] of pendingMint) {
905
- if (utxoIdRaw.toNumber() === utxoId) {
906
- mintsPending.push(mintAmountRaw.toBigInt());
907
- }
908
- }
909
- return mintsPending;
910
- }
911
- async createInitializeLockTx(args) {
912
- const { vault, priceIndex, argonKeyring, satoshis, tip = 0n, ownerBitcoinPubkey } = args;
913
- const client = this.client;
1033
+ static async createInitializeTx(args) {
1034
+ const {
1035
+ vault,
1036
+ priceIndex,
1037
+ argonKeyring,
1038
+ satoshis,
1039
+ tip = 0n,
1040
+ ownerBitcoinPubkey,
1041
+ client
1042
+ } = args;
914
1043
  if (ownerBitcoinPubkey.length !== 33) {
915
1044
  throw new Error(
916
1045
  `Invalid Bitcoin key length: ${ownerBitcoinPubkey.length}. Must be a compressed pukey (33 bytes).`
@@ -932,23 +1061,9 @@ var BitcoinLocks = class {
932
1061
  });
933
1062
  return { tx, securityFee, txFee, canAfford, availableBalance, txFeePlusTip: txFee + tip };
934
1063
  }
935
- async getBitcoinLockFromTxResult(txResult) {
936
- await txResult.waitForFinalizedBlock;
937
- const blockHeight = txResult.blockNumber;
938
- const utxoId = await _asyncNullishCoalesce(await this.getUtxoIdFromEvents(txResult.events), async () => ( 0));
939
- if (utxoId === 0) {
940
- throw new Error("Bitcoin lock creation failed, no UTXO ID found in transaction events");
941
- }
942
- const lock = await this.getBitcoinLock(utxoId);
943
- if (!lock) {
944
- throw new Error(`Lock with ID ${utxoId} not found after initialization`);
945
- }
946
- return { lock, createdAtHeight: blockHeight, txResult };
947
- }
948
- async initializeLock(args) {
949
- const { argonKeyring } = args;
950
- const client = this.client;
951
- const { tx, securityFee, canAfford, txFeePlusTip } = await this.createInitializeLockTx(args);
1064
+ static async initialize(args) {
1065
+ const { argonKeyring, client } = args;
1066
+ const { tx, securityFee, canAfford, txFeePlusTip } = await this.createInitializeTx(args);
952
1067
  if (!canAfford) {
953
1068
  throw new Error(
954
1069
  `Insufficient funds to initialize bitcoin lock. Required security fee: ${formatArgons(securityFee)}, Tx fee plus tip: ${formatArgons(txFeePlusTip)}`
@@ -957,130 +1072,27 @@ var BitcoinLocks = class {
957
1072
  const submitter = new TxSubmitter(client, tx, argonKeyring);
958
1073
  const txResult = await submitter.submit({ logResults: true, ...args });
959
1074
  return {
960
- getLock: () => this.getBitcoinLockFromTxResult(txResult),
1075
+ getLock: () => this.getBitcoinLockFromTxResult(client, txResult),
961
1076
  txResult,
962
1077
  securityFee
963
1078
  };
964
1079
  }
965
- async requiredSatoshisForArgonLiquidity(priceIndex, argonAmount) {
966
- const marketRatePerBitcoin = priceIndex.getBtcMicrogonPrice(SATS_PER_BTC);
967
- return argonAmount * SATS_PER_BTC / marketRatePerBitcoin;
968
- }
969
- async requestRelease(args) {
970
- const client = this.client;
971
- const {
972
- lock,
973
- priceIndex,
974
- releaseRequest: { bitcoinNetworkFee, toScriptPubkey },
975
- argonKeyring,
976
- tip = 0n
977
- } = args;
978
- if (!toScriptPubkey.startsWith("0x")) {
979
- throw new Error("toScriptPubkey must be a hex string starting with 0x");
980
- }
981
- const submitter = new TxSubmitter(
982
- client,
983
- client.tx.bitcoinLocks.requestRelease(lock.utxoId, toScriptPubkey, bitcoinNetworkFee),
984
- argonKeyring
985
- );
986
- const redemptionPrice = await this.getRedemptionRate(priceIndex, lock);
987
- const canAfford = await submitter.canAfford({
988
- tip,
989
- unavailableBalance: BigInt(redemptionPrice)
990
- });
991
- if (!canAfford.canAfford) {
992
- throw new Error(
993
- `Insufficient funds to release lock. Available: ${formatArgons(canAfford.availableBalance)}, Required: ${formatArgons(redemptionPrice + canAfford.txFee + tip)}`
994
- );
1080
+ static async getBitcoinLockFromTxResult(client, txResult) {
1081
+ await txResult.waitForFinalizedBlock;
1082
+ const blockHeight = txResult.blockNumber;
1083
+ const utxoId = await _asyncNullishCoalesce(await this.getUtxoIdFromEvents(client, txResult.events), async () => ( 0));
1084
+ if (utxoId === 0) {
1085
+ throw new Error("Bitcoin lock creation failed, no UTXO ID found in transaction events");
995
1086
  }
996
- return submitter.submit({
997
- logResults: true,
998
- ...args
999
- });
1000
- }
1001
- async releasePrice(priceIndex, lock) {
1002
- return await this.getRedemptionRate(priceIndex, lock);
1003
- }
1004
- async getRatchetPrice(lock, priceIndex, vault) {
1005
- const { createdAtHeight, vaultClaimHeight, peggedPrice, satoshis } = lock;
1006
- const client = this.client;
1007
- const marketRate = await this.getMarketRate(priceIndex, BigInt(satoshis));
1008
- let ratchetingFee = vault.terms.bitcoinBaseFee;
1009
- let burnAmount = 0n;
1010
- if (marketRate > peggedPrice) {
1011
- const lockFee = vault.calculateBitcoinFee(marketRate);
1012
- const currentBitcoinHeight = await client.query.bitcoinUtxos.confirmedBitcoinBlockTip().then((x) => x.unwrap().blockHeight.toNumber());
1013
- const blockLength = vaultClaimHeight - createdAtHeight;
1014
- const elapsed = (currentBitcoinHeight - createdAtHeight) / blockLength;
1015
- const remainingDuration = 1 - elapsed;
1016
- ratchetingFee = BigInt(remainingDuration * Number(lockFee));
1017
- } else {
1018
- burnAmount = await this.releasePrice(priceIndex, lock);
1087
+ const lock = await this.get(client, utxoId);
1088
+ if (!lock) {
1089
+ throw new Error(`Lock with ID ${utxoId} not found after initialization`);
1019
1090
  }
1020
- return {
1021
- ratchetingFee,
1022
- burnAmount,
1023
- marketRate
1024
- };
1091
+ return { lock, createdAtHeight: blockHeight, txResult };
1025
1092
  }
1026
- async ratchet(args) {
1027
- const { lock, priceIndex, argonKeyring, tip = 0n, vault, txProgressCallback } = args;
1028
- const client = this.client;
1029
- const ratchetPrice = await this.getRatchetPrice(lock, priceIndex, vault);
1030
- const txSubmitter = new TxSubmitter(
1031
- client,
1032
- client.tx.bitcoinLocks.ratchet(lock.utxoId),
1033
- argonKeyring
1034
- );
1035
- const canAfford = await txSubmitter.canAfford({
1036
- tip,
1037
- unavailableBalance: BigInt(ratchetPrice.burnAmount + ratchetPrice.ratchetingFee)
1038
- });
1039
- if (!canAfford.canAfford) {
1040
- throw new Error(
1041
- `Insufficient funds to ratchet lock. Available: ${formatArgons(canAfford.availableBalance)}, Required: ${formatArgons(
1042
- ratchetPrice.burnAmount + ratchetPrice.ratchetingFee
1043
- )}`
1044
- );
1045
- }
1046
- const txResult = await txSubmitter.submit(args);
1047
- const getRatchetResult = async () => {
1048
- const blockHash = await txResult.waitForFinalizedBlock;
1049
- const ratchetEvent = txResult.events.find(
1050
- (x) => client.events.bitcoinLocks.BitcoinLockRatcheted.is(x)
1051
- );
1052
- if (!ratchetEvent) {
1053
- throw new Error(`Ratchet event not found in transaction events`);
1054
- }
1055
- const api = await client.at(blockHash);
1056
- const bitcoinBlockHeight = await api.query.bitcoinUtxos.confirmedBitcoinBlockTip().then((x) => x.unwrap().blockHeight.toNumber());
1057
- const {
1058
- amountBurned,
1059
- liquidityPromised: liquidityPromisedRaw,
1060
- newPeggedPrice,
1061
- originalPeggedPrice,
1062
- securityFee
1063
- } = ratchetEvent.data;
1064
- const liquidityPromised = liquidityPromisedRaw.toBigInt();
1065
- let mintAmount = liquidityPromised;
1066
- if (liquidityPromised > originalPeggedPrice.toBigInt()) {
1067
- mintAmount -= originalPeggedPrice.toBigInt();
1068
- }
1069
- return {
1070
- txFee: _nullishCoalesce(txResult.finalFee, () => ( 0n)),
1071
- blockHeight: txResult.blockNumber,
1072
- bitcoinBlockHeight,
1073
- pendingMint: mintAmount,
1074
- liquidityPromised,
1075
- newPeggedPrice: newPeggedPrice.toBigInt(),
1076
- burned: amountBurned.toBigInt(),
1077
- securityFee: securityFee.toBigInt()
1078
- };
1079
- };
1080
- return {
1081
- txResult,
1082
- getRatchetResult
1083
- };
1093
+ static async requiredSatoshisForArgonLiquidity(priceIndex, argonAmount) {
1094
+ const marketRatePerBitcoin = priceIndex.getBtcMicrogonPrice(SATS_PER_BTC);
1095
+ return argonAmount * SATS_PER_BTC / marketRatePerBitcoin;
1084
1096
  }
1085
1097
  };
1086
1098
 
@@ -1237,5 +1249,5 @@ async function getClient(host, options) {
1237
1249
 
1238
1250
 
1239
1251
 
1240
- exports.BTreeMap = _typescodec.BTreeMap; exports.BitcoinLocks = BitcoinLocks; exports.Bool = _typescodec.Bool; exports.Bytes = _typescodec.Bytes; exports.Compact = _typescodec.Compact; exports.Enum = _typescodec.Enum; exports.ExtrinsicError = ExtrinsicError; exports.FIXED_U128_DECIMALS = FIXED_U128_DECIMALS; exports.GenericAddress = _generic.GenericAddress; exports.GenericBlock = _generic.GenericBlock; exports.GenericEvent = _generic.GenericEvent; exports.Keyring = _api.Keyring; exports.MICROGONS_PER_ARGON = MICROGONS_PER_ARGON; exports.Null = _typescodec.Null; exports.Option = _typescodec.Option; exports.PERMILL_DECIMALS = PERMILL_DECIMALS; exports.PriceIndex = PriceIndex; exports.Range = _typescodec.Range; exports.Result = _typescodec.Result; exports.SATS_PER_BTC = SATS_PER_BTC; exports.Struct = _typescodec.Struct; exports.Text = _typescodec.Text; exports.Tuple = _typescodec.Tuple; exports.TxResult = TxResult; exports.TxSubmitter = TxSubmitter; exports.U256 = _typescodec.U256; exports.U8aFixed = _typescodec.U8aFixed; exports.Vault = Vault; exports.Vec = _typescodec.Vec; exports.WageProtector = WageProtector; exports.bool = _typescodec.bool; exports.checkForExtrinsicSuccess = checkForExtrinsicSuccess; exports.createKeyringPair = createKeyringPair; exports.decodeAddress = _utilcrypto.decodeAddress; exports.dispatchErrorToExtrinsicError = dispatchErrorToExtrinsicError; exports.dispatchErrorToString = dispatchErrorToString; exports.formatArgons = formatArgons; exports.fromFixedNumber = fromFixedNumber; exports.getAuthorFromHeader = getAuthorFromHeader; exports.getClient = getClient; exports.getTickFromHeader = getTickFromHeader; exports.gettersToObject = gettersToObject; exports.hexToU8a = _util.hexToU8a; exports.i128 = _typescodec.i128; exports.keyringFromSuri = keyringFromSuri; exports.mnemonicGenerate = _utilcrypto.mnemonicGenerate; exports.toFixedNumber = toFixedNumber; exports.u128 = _typescodec.u128; exports.u16 = _typescodec.u16; exports.u32 = _typescodec.u32; exports.u64 = _typescodec.u64; exports.u8 = _typescodec.u8; exports.u8aEq = _util.u8aEq; exports.u8aToHex = _util.u8aToHex; exports.waitForLoad = waitForLoad;
1252
+ exports.BTreeMap = _typescodec.BTreeMap; exports.BitcoinLock = BitcoinLock; exports.Bool = _typescodec.Bool; exports.Bytes = _typescodec.Bytes; exports.Compact = _typescodec.Compact; exports.Enum = _typescodec.Enum; exports.ExtrinsicError = ExtrinsicError; exports.FIXED_U128_DECIMALS = FIXED_U128_DECIMALS; exports.GenericAddress = _generic.GenericAddress; exports.GenericBlock = _generic.GenericBlock; exports.GenericEvent = _generic.GenericEvent; exports.Keyring = _api.Keyring; exports.MICROGONS_PER_ARGON = MICROGONS_PER_ARGON; exports.Null = _typescodec.Null; exports.Option = _typescodec.Option; exports.PERMILL_DECIMALS = PERMILL_DECIMALS; exports.PriceIndex = PriceIndex; exports.Range = _typescodec.Range; exports.Result = _typescodec.Result; exports.SATS_PER_BTC = SATS_PER_BTC; exports.Struct = _typescodec.Struct; exports.Text = _typescodec.Text; exports.Tuple = _typescodec.Tuple; exports.TxResult = TxResult; exports.TxSubmitter = TxSubmitter; exports.U256 = _typescodec.U256; exports.U8aFixed = _typescodec.U8aFixed; exports.Vault = Vault; exports.Vec = _typescodec.Vec; exports.WageProtector = WageProtector; exports.bool = _typescodec.bool; exports.checkForExtrinsicSuccess = checkForExtrinsicSuccess; exports.createKeyringPair = createKeyringPair; exports.decodeAddress = _utilcrypto.decodeAddress; exports.dispatchErrorToExtrinsicError = dispatchErrorToExtrinsicError; exports.dispatchErrorToString = dispatchErrorToString; exports.formatArgons = formatArgons; exports.fromFixedNumber = fromFixedNumber; exports.getAuthorFromHeader = getAuthorFromHeader; exports.getClient = getClient; exports.getTickFromHeader = getTickFromHeader; exports.gettersToObject = gettersToObject; exports.hexToU8a = _util.hexToU8a; exports.i128 = _typescodec.i128; exports.keyringFromSuri = keyringFromSuri; exports.mnemonicGenerate = _utilcrypto.mnemonicGenerate; exports.toFixedNumber = toFixedNumber; exports.u128 = _typescodec.u128; exports.u16 = _typescodec.u16; exports.u32 = _typescodec.u32; exports.u64 = _typescodec.u64; exports.u8 = _typescodec.u8; exports.u8aEq = _util.u8aEq; exports.u8aToHex = _util.u8aToHex; exports.waitForLoad = waitForLoad;
1241
1253
  //# sourceMappingURL=index.cjs.map