@argonprotocol/mainchain 1.3.18 → 1.3.20

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