btc-wallet 0.5.22-beta → 0.5.23-beta

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.
@@ -1,7 +1,7 @@
1
1
  import type { ENV } from '../config';
2
- import { calculateGasLimit } from '../utils/satoshi';
2
+ import { calculateWithdraw, calculateGasLimit } from '../utils/satoshi';
3
3
  import type { FinalExecutionOutcome, Transaction } from '@near-wallet-selector/core';
4
- export { calculateGasLimit };
4
+ export { calculateGasLimit, calculateWithdraw };
5
5
  type CheckGasTokenDebtReturnType<T extends boolean> = T extends true ? void : {
6
6
  receiver_id: string;
7
7
  amount: string;
@@ -9,7 +9,9 @@ type CheckGasTokenDebtReturnType<T extends boolean> = T extends true ? void : {
9
9
  } | undefined;
10
10
  export declare function checkGasTokenDebt<T extends boolean>(csna: string, env: ENV, autoDeposit?: T): Promise<CheckGasTokenDebtReturnType<T>>;
11
11
  export declare function getBtcGasPrice(): Promise<number>;
12
- export declare function getBtcBalance(): Promise<{
12
+ export declare function getBtcUtxos(account: string): Promise<any>;
13
+ export declare function calculateGasFee(account: string, amount: number, feeRate?: number): Promise<any>;
14
+ export declare function getBtcBalance(account?: string): Promise<{
13
15
  rawBalance: number;
14
16
  balance: number;
15
17
  availableBalance: number;
@@ -20,6 +22,7 @@ export declare function estimateDepositAmount(amount: string, option?: {
20
22
  env?: ENV;
21
23
  }): Promise<string>;
22
24
  export declare function getDepositAmount(amount: string, option?: {
25
+ csna?: string;
23
26
  env?: ENV;
24
27
  /** default is true, if true, new account minimum deposit amount 1000sat, otherwise 0 */
25
28
  newAccountMinDepositAmount?: boolean;
@@ -54,6 +57,8 @@ export declare function checkSatoshiWhitelist(btcAccountId: string, env?: ENV):
54
57
  interface WithdrawParams {
55
58
  amount: string | number;
56
59
  feeRate?: number;
60
+ csna?: string;
61
+ btcAddress?: string;
57
62
  env?: ENV;
58
63
  }
59
- export declare function getWithdrawTransaction({ amount, feeRate, env, }: WithdrawParams): Promise<Transaction>;
64
+ export declare function getWithdrawTransaction({ amount, feeRate, csna, btcAddress, env, }: WithdrawParams): Promise<Transaction>;
package/dist/index.js CHANGED
@@ -104,13 +104,16 @@ __export(src_exports, {
104
104
  WizzConnector: () => WizzConnector,
105
105
  XverseConnector: () => XverseConnector,
106
106
  btcRpcUrls: () => btcRpcUrls,
107
+ calculateGasFee: () => calculateGasFee,
107
108
  calculateGasLimit: () => calculateGasLimit,
109
+ calculateWithdraw: () => calculateWithdraw,
108
110
  checkGasTokenDebt: () => checkGasTokenDebt,
109
111
  checkSatoshiWhitelist: () => checkSatoshiWhitelist,
110
112
  estimateDepositAmount: () => estimateDepositAmount,
111
113
  executeBTCDepositAndAction: () => executeBTCDepositAndAction,
112
114
  getBtcBalance: () => getBtcBalance,
113
115
  getBtcGasPrice: () => getBtcGasPrice,
116
+ getBtcUtxos: () => getBtcUtxos,
114
117
  getCsnaAccountId: () => getCsnaAccountId,
115
118
  getDepositAmount: () => getDepositAmount,
116
119
  getVersion: () => getVersion,
@@ -3415,6 +3418,8 @@ function convertTransactionToTxHex(_0) {
3415
3418
  env,
3416
3419
  index = 0
3417
3420
  }) {
3421
+ if (!publicKey)
3422
+ return { txHex: "", txBytes: new Uint8Array(), hash: "" };
3418
3423
  const publicKeyFormat = import_key_pair.PublicKey.from(publicKey);
3419
3424
  const currentConfig = getWalletConfig(env);
3420
3425
  const provider = getNearProvider({ network: currentConfig.network });
@@ -3634,7 +3639,8 @@ function getPredictedGasAmount(_0) {
3634
3639
  env
3635
3640
  }) {
3636
3641
  const currentConfig = getWalletConfig(env);
3637
- const predictedGas = yield nearCallFunction(
3642
+ const isValidTransactions = transactions2.every((tx) => tx.length > 0);
3643
+ const predictedGas = isValidTransactions ? yield nearCallFunction(
3638
3644
  accountContractId,
3639
3645
  "predict_txs_gas_token_amount",
3640
3646
  {
@@ -3642,7 +3648,7 @@ function getPredictedGasAmount(_0) {
3642
3648
  near_transactions: transactions2
3643
3649
  },
3644
3650
  { network: currentConfig.network }
3645
- );
3651
+ ) : "0";
3646
3652
  const predictedGasAmount = new import_big.default(predictedGas).mul(1.2).toFixed(0);
3647
3653
  const miniGasAmount = 200 * transactions2.length;
3648
3654
  const gasAmount = Math.max(Number(predictedGasAmount), miniGasAmount);
@@ -3658,9 +3664,9 @@ function calculateWithdraw(_0) {
3658
3664
  btcAddress,
3659
3665
  env
3660
3666
  }) {
3661
- console.log("calculateWithdraw feeRate:", feeRate);
3662
3667
  try {
3663
3668
  const config = getWalletConfig(env);
3669
+ const _feeRate = feeRate || (yield getBtcGasPrice());
3664
3670
  const gasLimit = yield calculateGasLimit({
3665
3671
  csna,
3666
3672
  transactions: [
@@ -3725,7 +3731,7 @@ function calculateWithdraw(_0) {
3725
3731
  const { inputs, outputs, fee } = (0, import_coinselect.default)(
3726
3732
  utxos,
3727
3733
  [{ address: btcAddress, value: userSatoshis }],
3728
- Math.ceil(feeRate || 0)
3734
+ Math.ceil(_feeRate)
3729
3735
  );
3730
3736
  const newInputs = inputs;
3731
3737
  let newOutputs = outputs;
@@ -3839,6 +3845,7 @@ function calculateWithdraw(_0) {
3839
3845
 
3840
3846
  // src/core/btcUtils.ts
3841
3847
  var import_bitcoinjs_lib = __toESM(require("bitcoinjs-lib"), 1);
3848
+ var import_coinselect2 = __toESM(require("coinselect"), 1);
3842
3849
  var ecc = __toESM(require("@bitcoinerlab/secp256k1"), 1);
3843
3850
  import_bitcoinjs_lib.default.initEccLib(ecc);
3844
3851
  var NEAR_STORAGE_DEPOSIT_AMOUNT = "1250000000000000000000";
@@ -3853,9 +3860,13 @@ function getBtcProvider() {
3853
3860
  }
3854
3861
  function getNetwork() {
3855
3862
  return __async(this, null, function* () {
3856
- const network = yield getBtcProvider().getNetwork();
3857
- console.log("btc network:", network);
3858
- return network === "livenet" ? "mainnet" : "testnet";
3863
+ try {
3864
+ const network = yield getBtcProvider().getNetwork();
3865
+ console.log("btc network:", network);
3866
+ return network === "livenet" ? "mainnet" : "testnet";
3867
+ } catch (error) {
3868
+ return "mainnet";
3869
+ }
3859
3870
  });
3860
3871
  }
3861
3872
  function getBtcRpcUrl() {
@@ -3918,25 +3929,37 @@ function getBtcGasPrice() {
3918
3929
  }
3919
3930
  });
3920
3931
  }
3921
- function getBtcBalance() {
3932
+ function getBtcUtxos(account) {
3922
3933
  return __async(this, null, function* () {
3923
- const { account } = yield retryOperation(getBtcProvider, (res) => !!res.account);
3924
- if (!account) {
3925
- console.error("BTC Account is not available.");
3926
- return { rawBalance: 0, balance: 0, availableBalance: 0 };
3927
- }
3928
3934
  const btcRpcUrl = yield getBtcRpcUrl();
3929
3935
  const utxos = yield fetch(`${btcRpcUrl}/address/${account}/utxo`).then((res) => res.json());
3936
+ return utxos;
3937
+ });
3938
+ }
3939
+ function calculateGasFee(account, amount, feeRate) {
3940
+ return __async(this, null, function* () {
3941
+ const _feeRate = feeRate || (yield getBtcGasPrice());
3942
+ const utxos = yield getBtcUtxos(account);
3943
+ const { fee } = (0, import_coinselect2.default)(utxos, [{ address: account, value: amount }], Math.ceil(_feeRate));
3944
+ console.log("calculateGasFee fee:", fee);
3945
+ return fee;
3946
+ });
3947
+ }
3948
+ function getBtcBalance(account) {
3949
+ return __async(this, null, function* () {
3950
+ if (!account) {
3951
+ const res = yield retryOperation(getBtcProvider, (res2) => !!res2.account);
3952
+ if (!res.account) {
3953
+ console.error("BTC Account is not available.");
3954
+ return { rawBalance: 0, balance: 0, availableBalance: 0 };
3955
+ }
3956
+ account = res.account;
3957
+ }
3958
+ const utxos = yield getBtcUtxos(account);
3930
3959
  const btcDecimals = 8;
3931
3960
  const rawBalance = (utxos == null ? void 0 : utxos.reduce((acc, cur) => acc + cur.value, 0)) || 0;
3932
3961
  const balance = rawBalance / __pow(10, btcDecimals);
3933
- const feeRate = yield getBtcGasPrice();
3934
- const inputSize = ((utxos == null ? void 0 : utxos.length) || 0) * 69;
3935
- const outputSize = 33 * 2;
3936
- const overheadSize = 11;
3937
- const estimatedTxSize = inputSize + outputSize + overheadSize;
3938
- const estimatedFee = Math.ceil(estimatedTxSize * feeRate);
3939
- console.log("estimatedFee:", estimatedFee);
3962
+ const estimatedFee = yield calculateGasFee(account, rawBalance);
3940
3963
  const availableRawBalance = (rawBalance - estimatedFee).toFixed(0);
3941
3964
  const availableBalance = new import_big2.default(availableRawBalance).div(__pow(10, btcDecimals)).round(btcDecimals, import_big2.default.roundDown).toNumber();
3942
3965
  return {
@@ -3963,7 +3986,7 @@ function getDepositAmount(amount, option) {
3963
3986
  var _a;
3964
3987
  const env = (option == null ? void 0 : option.env) || "mainnet";
3965
3988
  const _newAccountMinDepositAmount = (_a = option == null ? void 0 : option.newAccountMinDepositAmount) != null ? _a : true;
3966
- const csna = yield getCsnaAccountId(env);
3989
+ const csna = (option == null ? void 0 : option.csna) || (yield getCsnaAccountId(env));
3967
3990
  const accountInfo = yield getAccountInfo({ csna, env });
3968
3991
  const debtAction = yield checkGasTokenDebt(csna, env, false);
3969
3992
  const repayAmount = (debtAction == null ? void 0 : debtAction.amount) || 0;
@@ -4160,18 +4183,18 @@ function getWithdrawTransaction(_0) {
4160
4183
  return __async(this, arguments, function* ({
4161
4184
  amount,
4162
4185
  feeRate,
4186
+ csna,
4187
+ btcAddress,
4163
4188
  env = "mainnet"
4164
4189
  }) {
4165
4190
  const config = getWalletConfig(env);
4166
- const provider = getBtcProvider();
4167
- const btcAddress = provider.account;
4168
- const csna = yield getCsnaAccountId(env);
4169
- const _feeRate = feeRate || (yield getBtcGasPrice());
4191
+ const _btcAddress = btcAddress || getBtcProvider().account;
4192
+ const _csna = csna || (yield getCsnaAccountId(env));
4170
4193
  const _a = yield calculateWithdraw({
4171
4194
  amount,
4172
- feeRate: _feeRate,
4173
- csna,
4174
- btcAddress,
4195
+ feeRate,
4196
+ csna: _csna,
4197
+ btcAddress: _btcAddress,
4175
4198
  env
4176
4199
  }), { inputs, outputs, isError, errorMsg } = _a, rest = __objRest(_a, ["inputs", "outputs", "isError", "errorMsg"]);
4177
4200
  if (isError || !inputs || !outputs) {
@@ -4187,7 +4210,7 @@ function getWithdrawTransaction(_0) {
4187
4210
  const btcNetwork = network === "mainnet" ? import_bitcoinjs_lib.default.networks.bitcoin : import_bitcoinjs_lib.default.networks.testnet;
4188
4211
  const psbt = new import_bitcoinjs_lib.default.Psbt({ network: btcNetwork });
4189
4212
  const btcRpcUrl = yield getBtcRpcUrl();
4190
- Promise.all(
4213
+ yield Promise.all(
4191
4214
  inputs.map((input) => __async(this, null, function* () {
4192
4215
  const txData = yield fetch(`${btcRpcUrl}/tx/${input.txid}`).then((res) => res.json());
4193
4216
  const inputOptions = {
@@ -4219,14 +4242,14 @@ function getWithdrawTransaction(_0) {
4219
4242
  });
4220
4243
  const msg = {
4221
4244
  Withdraw: {
4222
- target_btc_address: btcAddress,
4245
+ target_btc_address: _btcAddress,
4223
4246
  input: _inputs,
4224
4247
  output: txOutputs
4225
4248
  }
4226
4249
  };
4227
4250
  const transaction = {
4228
4251
  receiverId: config.btcToken,
4229
- signerId: csna,
4252
+ signerId: _csna,
4230
4253
  actions: [
4231
4254
  {
4232
4255
  type: "FunctionCall",
@@ -4494,6 +4517,8 @@ var BTCWallet = (_0) => __async(void 0, [_0], function* ({
4494
4517
  id,
4495
4518
  provider
4496
4519
  }) {
4520
+ let initializing = false;
4521
+ let connectionUpdateTimeout;
4497
4522
  const wallet = {
4498
4523
  signIn,
4499
4524
  signOut,
@@ -4517,15 +4542,52 @@ var BTCWallet = (_0) => __async(void 0, [_0], function* ({
4517
4542
  }
4518
4543
  return true;
4519
4544
  }
4545
+ function initBtcContext() {
4546
+ return __async(this, null, function* () {
4547
+ if (initializing) {
4548
+ console.log("BTC context initialization already in progress");
4549
+ return;
4550
+ }
4551
+ console.log("initBtcContext");
4552
+ try {
4553
+ initializing = true;
4554
+ const btcContext = yield retryOperation(
4555
+ () => __async(this, null, function* () {
4556
+ const ctx = window.btcContext;
4557
+ if (!ctx) {
4558
+ throw new Error("btcContext not found");
4559
+ }
4560
+ return ctx;
4561
+ }),
4562
+ (res) => !!res,
4563
+ {
4564
+ maxRetries: 10,
4565
+ delayMs: 500
4566
+ }
4567
+ );
4568
+ yield setupBtcContextListeners();
4569
+ return btcContext;
4570
+ } finally {
4571
+ initializing = false;
4572
+ }
4573
+ });
4574
+ }
4520
4575
  function setupBtcContextListeners() {
4521
4576
  return __async(this, null, function* () {
4522
4577
  const handleConnectionUpdate = () => __async(this, null, function* () {
4578
+ if (connectionUpdateTimeout) {
4579
+ clearTimeout(connectionUpdateTimeout);
4580
+ }
4523
4581
  yield checkBtcNetwork(currentConfig.network);
4524
4582
  if (!state_default.isValid()) {
4525
4583
  state_default.clear();
4526
4584
  console.log("setupBtcContextListeners clear");
4527
4585
  }
4528
- validateWalletState();
4586
+ const valid = validateWalletState();
4587
+ console.log("setupBtcContextListeners wallet state valid:", valid);
4588
+ if (!valid) {
4589
+ return;
4590
+ }
4529
4591
  const btcContext = window.btcContext;
4530
4592
  if (btcContext.account) {
4531
4593
  const btcPublicKey = yield btcContext.getPublicKey();
@@ -4536,7 +4598,7 @@ var BTCWallet = (_0) => __async(void 0, [_0], function* ({
4536
4598
  }
4537
4599
  } else {
4538
4600
  removeWalletButton();
4539
- setTimeout(() => {
4601
+ connectionUpdateTimeout = setTimeout(() => {
4540
4602
  handleConnectionUpdate();
4541
4603
  }, 5e3);
4542
4604
  }
@@ -4573,27 +4635,6 @@ var BTCWallet = (_0) => __async(void 0, [_0], function* ({
4573
4635
  }
4574
4636
  });
4575
4637
  }
4576
- function initBtcContext() {
4577
- return __async(this, null, function* () {
4578
- console.log("initBtcContext");
4579
- const btcContext = yield retryOperation(
4580
- () => __async(this, null, function* () {
4581
- const ctx = window.btcContext;
4582
- if (!ctx) {
4583
- throw new Error("btcContext not found");
4584
- }
4585
- return ctx;
4586
- }),
4587
- (res) => !!res,
4588
- {
4589
- maxRetries: 10,
4590
- delayMs: 500
4591
- }
4592
- );
4593
- yield setupBtcContextListeners();
4594
- return btcContext;
4595
- });
4596
- }
4597
4638
  function nearCall2(contractId, methodName, args) {
4598
4639
  return __async(this, null, function* () {
4599
4640
  return nearCallFunction(contractId, methodName, args, { provider });
@@ -4791,7 +4832,7 @@ function setupBTCWallet({
4791
4832
 
4792
4833
  // src/index.ts
4793
4834
  var getVersion = () => {
4794
- return "0.5.22-beta";
4835
+ return "0.5.23-beta";
4795
4836
  };
4796
4837
  if (typeof window !== "undefined") {
4797
4838
  window.__BTC_WALLET_VERSION = getVersion();