btc-wallet 0.5.21-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,5 +1,7 @@
1
1
  import type { ENV } from '../config';
2
+ import { calculateWithdraw, calculateGasLimit } from '../utils/satoshi';
2
3
  import type { FinalExecutionOutcome, Transaction } from '@near-wallet-selector/core';
4
+ export { calculateGasLimit, calculateWithdraw };
3
5
  type CheckGasTokenDebtReturnType<T extends boolean> = T extends true ? void : {
4
6
  receiver_id: string;
5
7
  amount: string;
@@ -7,7 +9,9 @@ type CheckGasTokenDebtReturnType<T extends boolean> = T extends true ? void : {
7
9
  } | undefined;
8
10
  export declare function checkGasTokenDebt<T extends boolean>(csna: string, env: ENV, autoDeposit?: T): Promise<CheckGasTokenDebtReturnType<T>>;
9
11
  export declare function getBtcGasPrice(): Promise<number>;
10
- 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<{
11
15
  rawBalance: number;
12
16
  balance: number;
13
17
  availableBalance: number;
@@ -18,6 +22,7 @@ export declare function estimateDepositAmount(amount: string, option?: {
18
22
  env?: ENV;
19
23
  }): Promise<string>;
20
24
  export declare function getDepositAmount(amount: string, option?: {
25
+ csna?: string;
21
26
  env?: ENV;
22
27
  /** default is true, if true, new account minimum deposit amount 1000sat, otherwise 0 */
23
28
  newAccountMinDepositAmount?: boolean;
@@ -52,7 +57,8 @@ export declare function checkSatoshiWhitelist(btcAccountId: string, env?: ENV):
52
57
  interface WithdrawParams {
53
58
  amount: string | number;
54
59
  feeRate?: number;
60
+ csna?: string;
61
+ btcAddress?: string;
55
62
  env?: ENV;
56
63
  }
57
- export declare function getWithdrawTransaction({ amount, feeRate, env, }: WithdrawParams): Promise<Transaction>;
58
- export {};
64
+ export declare function getWithdrawTransaction({ amount, feeRate, csna, btcAddress, env, }: WithdrawParams): Promise<Transaction>;
package/dist/index.js CHANGED
@@ -104,12 +104,16 @@ __export(src_exports, {
104
104
  WizzConnector: () => WizzConnector,
105
105
  XverseConnector: () => XverseConnector,
106
106
  btcRpcUrls: () => btcRpcUrls,
107
+ calculateGasFee: () => calculateGasFee,
108
+ calculateGasLimit: () => calculateGasLimit,
109
+ calculateWithdraw: () => calculateWithdraw,
107
110
  checkGasTokenDebt: () => checkGasTokenDebt,
108
111
  checkSatoshiWhitelist: () => checkSatoshiWhitelist,
109
112
  estimateDepositAmount: () => estimateDepositAmount,
110
113
  executeBTCDepositAndAction: () => executeBTCDepositAndAction,
111
114
  getBtcBalance: () => getBtcBalance,
112
115
  getBtcGasPrice: () => getBtcGasPrice,
116
+ getBtcUtxos: () => getBtcUtxos,
113
117
  getCsnaAccountId: () => getCsnaAccountId,
114
118
  getDepositAmount: () => getDepositAmount,
115
119
  getVersion: () => getVersion,
@@ -3414,6 +3418,8 @@ function convertTransactionToTxHex(_0) {
3414
3418
  env,
3415
3419
  index = 0
3416
3420
  }) {
3421
+ if (!publicKey)
3422
+ return { txHex: "", txBytes: new Uint8Array(), hash: "" };
3417
3423
  const publicKeyFormat = import_key_pair.PublicKey.from(publicKey);
3418
3424
  const currentConfig = getWalletConfig(env);
3419
3425
  const provider = getNearProvider({ network: currentConfig.network });
@@ -3633,7 +3639,8 @@ function getPredictedGasAmount(_0) {
3633
3639
  env
3634
3640
  }) {
3635
3641
  const currentConfig = getWalletConfig(env);
3636
- const predictedGas = yield nearCallFunction(
3642
+ const isValidTransactions = transactions2.every((tx) => tx.length > 0);
3643
+ const predictedGas = isValidTransactions ? yield nearCallFunction(
3637
3644
  accountContractId,
3638
3645
  "predict_txs_gas_token_amount",
3639
3646
  {
@@ -3641,7 +3648,7 @@ function getPredictedGasAmount(_0) {
3641
3648
  near_transactions: transactions2
3642
3649
  },
3643
3650
  { network: currentConfig.network }
3644
- );
3651
+ ) : "0";
3645
3652
  const predictedGasAmount = new import_big.default(predictedGas).mul(1.2).toFixed(0);
3646
3653
  const miniGasAmount = 200 * transactions2.length;
3647
3654
  const gasAmount = Math.max(Number(predictedGasAmount), miniGasAmount);
@@ -3657,9 +3664,9 @@ function calculateWithdraw(_0) {
3657
3664
  btcAddress,
3658
3665
  env
3659
3666
  }) {
3660
- console.log("calculateWithdraw feeRate:", feeRate);
3661
3667
  try {
3662
3668
  const config = getWalletConfig(env);
3669
+ const _feeRate = feeRate || (yield getBtcGasPrice());
3663
3670
  const gasLimit = yield calculateGasLimit({
3664
3671
  csna,
3665
3672
  transactions: [
@@ -3724,7 +3731,7 @@ function calculateWithdraw(_0) {
3724
3731
  const { inputs, outputs, fee } = (0, import_coinselect.default)(
3725
3732
  utxos,
3726
3733
  [{ address: btcAddress, value: userSatoshis }],
3727
- Math.ceil(feeRate || 0)
3734
+ Math.ceil(_feeRate)
3728
3735
  );
3729
3736
  const newInputs = inputs;
3730
3737
  let newOutputs = outputs;
@@ -3838,6 +3845,7 @@ function calculateWithdraw(_0) {
3838
3845
 
3839
3846
  // src/core/btcUtils.ts
3840
3847
  var import_bitcoinjs_lib = __toESM(require("bitcoinjs-lib"), 1);
3848
+ var import_coinselect2 = __toESM(require("coinselect"), 1);
3841
3849
  var ecc = __toESM(require("@bitcoinerlab/secp256k1"), 1);
3842
3850
  import_bitcoinjs_lib.default.initEccLib(ecc);
3843
3851
  var NEAR_STORAGE_DEPOSIT_AMOUNT = "1250000000000000000000";
@@ -3852,9 +3860,13 @@ function getBtcProvider() {
3852
3860
  }
3853
3861
  function getNetwork() {
3854
3862
  return __async(this, null, function* () {
3855
- const network = yield getBtcProvider().getNetwork();
3856
- console.log("btc network:", network);
3857
- 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
+ }
3858
3870
  });
3859
3871
  }
3860
3872
  function getBtcRpcUrl() {
@@ -3917,25 +3929,37 @@ function getBtcGasPrice() {
3917
3929
  }
3918
3930
  });
3919
3931
  }
3920
- function getBtcBalance() {
3932
+ function getBtcUtxos(account) {
3921
3933
  return __async(this, null, function* () {
3922
- const { account } = yield retryOperation(getBtcProvider, (res) => !!res.account);
3923
- if (!account) {
3924
- console.error("BTC Account is not available.");
3925
- return { rawBalance: 0, balance: 0, availableBalance: 0 };
3926
- }
3927
3934
  const btcRpcUrl = yield getBtcRpcUrl();
3928
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);
3929
3959
  const btcDecimals = 8;
3930
3960
  const rawBalance = (utxos == null ? void 0 : utxos.reduce((acc, cur) => acc + cur.value, 0)) || 0;
3931
3961
  const balance = rawBalance / __pow(10, btcDecimals);
3932
- const feeRate = yield getBtcGasPrice();
3933
- const inputSize = ((utxos == null ? void 0 : utxos.length) || 0) * 69;
3934
- const outputSize = 33 * 2;
3935
- const overheadSize = 11;
3936
- const estimatedTxSize = inputSize + outputSize + overheadSize;
3937
- const estimatedFee = Math.ceil(estimatedTxSize * feeRate);
3938
- console.log("estimatedFee:", estimatedFee);
3962
+ const estimatedFee = yield calculateGasFee(account, rawBalance);
3939
3963
  const availableRawBalance = (rawBalance - estimatedFee).toFixed(0);
3940
3964
  const availableBalance = new import_big2.default(availableRawBalance).div(__pow(10, btcDecimals)).round(btcDecimals, import_big2.default.roundDown).toNumber();
3941
3965
  return {
@@ -3962,7 +3986,7 @@ function getDepositAmount(amount, option) {
3962
3986
  var _a;
3963
3987
  const env = (option == null ? void 0 : option.env) || "mainnet";
3964
3988
  const _newAccountMinDepositAmount = (_a = option == null ? void 0 : option.newAccountMinDepositAmount) != null ? _a : true;
3965
- const csna = yield getCsnaAccountId(env);
3989
+ const csna = (option == null ? void 0 : option.csna) || (yield getCsnaAccountId(env));
3966
3990
  const accountInfo = yield getAccountInfo({ csna, env });
3967
3991
  const debtAction = yield checkGasTokenDebt(csna, env, false);
3968
3992
  const repayAmount = (debtAction == null ? void 0 : debtAction.amount) || 0;
@@ -4159,18 +4183,18 @@ function getWithdrawTransaction(_0) {
4159
4183
  return __async(this, arguments, function* ({
4160
4184
  amount,
4161
4185
  feeRate,
4186
+ csna,
4187
+ btcAddress,
4162
4188
  env = "mainnet"
4163
4189
  }) {
4164
4190
  const config = getWalletConfig(env);
4165
- const provider = getBtcProvider();
4166
- const btcAddress = provider.account;
4167
- const csna = yield getCsnaAccountId(env);
4168
- const _feeRate = feeRate || (yield getBtcGasPrice());
4191
+ const _btcAddress = btcAddress || getBtcProvider().account;
4192
+ const _csna = csna || (yield getCsnaAccountId(env));
4169
4193
  const _a = yield calculateWithdraw({
4170
4194
  amount,
4171
- feeRate: _feeRate,
4172
- csna,
4173
- btcAddress,
4195
+ feeRate,
4196
+ csna: _csna,
4197
+ btcAddress: _btcAddress,
4174
4198
  env
4175
4199
  }), { inputs, outputs, isError, errorMsg } = _a, rest = __objRest(_a, ["inputs", "outputs", "isError", "errorMsg"]);
4176
4200
  if (isError || !inputs || !outputs) {
@@ -4186,7 +4210,7 @@ function getWithdrawTransaction(_0) {
4186
4210
  const btcNetwork = network === "mainnet" ? import_bitcoinjs_lib.default.networks.bitcoin : import_bitcoinjs_lib.default.networks.testnet;
4187
4211
  const psbt = new import_bitcoinjs_lib.default.Psbt({ network: btcNetwork });
4188
4212
  const btcRpcUrl = yield getBtcRpcUrl();
4189
- Promise.all(
4213
+ yield Promise.all(
4190
4214
  inputs.map((input) => __async(this, null, function* () {
4191
4215
  const txData = yield fetch(`${btcRpcUrl}/tx/${input.txid}`).then((res) => res.json());
4192
4216
  const inputOptions = {
@@ -4218,14 +4242,14 @@ function getWithdrawTransaction(_0) {
4218
4242
  });
4219
4243
  const msg = {
4220
4244
  Withdraw: {
4221
- target_btc_address: btcAddress,
4245
+ target_btc_address: _btcAddress,
4222
4246
  input: _inputs,
4223
4247
  output: txOutputs
4224
4248
  }
4225
4249
  };
4226
4250
  const transaction = {
4227
4251
  receiverId: config.btcToken,
4228
- signerId: csna,
4252
+ signerId: _csna,
4229
4253
  actions: [
4230
4254
  {
4231
4255
  type: "FunctionCall",
@@ -4493,6 +4517,8 @@ var BTCWallet = (_0) => __async(void 0, [_0], function* ({
4493
4517
  id,
4494
4518
  provider
4495
4519
  }) {
4520
+ let initializing = false;
4521
+ let connectionUpdateTimeout;
4496
4522
  const wallet = {
4497
4523
  signIn,
4498
4524
  signOut,
@@ -4501,8 +4527,7 @@ var BTCWallet = (_0) => __async(void 0, [_0], function* ({
4501
4527
  signMessage,
4502
4528
  isSignedIn,
4503
4529
  signAndSendTransaction,
4504
- signAndSendTransactions,
4505
- calculateGasLimit
4530
+ signAndSendTransactions
4506
4531
  };
4507
4532
  const env = metadata.env || options.network.networkId || "mainnet";
4508
4533
  const currentConfig = getWalletConfig(env);
@@ -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.21-beta";
4835
+ return "0.5.23-beta";
4795
4836
  };
4796
4837
  if (typeof window !== "undefined") {
4797
4838
  window.__BTC_WALLET_VERSION = getVersion();