btc-wallet 0.5.22-beta → 0.5.24-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,
@@ -3340,7 +3343,8 @@ function getAccountInfo(_0) {
3340
3343
  },
3341
3344
  { network: config.network }
3342
3345
  ).catch((error) => {
3343
- return void 0;
3346
+ console.log(`get_account error, please try again later`, error);
3347
+ throw error;
3344
3348
  });
3345
3349
  return accountInfo;
3346
3350
  });
@@ -3415,6 +3419,8 @@ function convertTransactionToTxHex(_0) {
3415
3419
  env,
3416
3420
  index = 0
3417
3421
  }) {
3422
+ if (!publicKey)
3423
+ return { txHex: "", txBytes: new Uint8Array(), hash: "" };
3418
3424
  const publicKeyFormat = import_key_pair.PublicKey.from(publicKey);
3419
3425
  const currentConfig = getWalletConfig(env);
3420
3426
  const provider = getNearProvider({ network: currentConfig.network });
@@ -3634,7 +3640,8 @@ function getPredictedGasAmount(_0) {
3634
3640
  env
3635
3641
  }) {
3636
3642
  const currentConfig = getWalletConfig(env);
3637
- const predictedGas = yield nearCallFunction(
3643
+ const isValidTransactions = transactions2.every((tx) => tx.length > 0);
3644
+ const predictedGas = isValidTransactions ? yield nearCallFunction(
3638
3645
  accountContractId,
3639
3646
  "predict_txs_gas_token_amount",
3640
3647
  {
@@ -3642,7 +3649,7 @@ function getPredictedGasAmount(_0) {
3642
3649
  near_transactions: transactions2
3643
3650
  },
3644
3651
  { network: currentConfig.network }
3645
- );
3652
+ ) : "0";
3646
3653
  const predictedGasAmount = new import_big.default(predictedGas).mul(1.2).toFixed(0);
3647
3654
  const miniGasAmount = 200 * transactions2.length;
3648
3655
  const gasAmount = Math.max(Number(predictedGasAmount), miniGasAmount);
@@ -3658,9 +3665,9 @@ function calculateWithdraw(_0) {
3658
3665
  btcAddress,
3659
3666
  env
3660
3667
  }) {
3661
- console.log("calculateWithdraw feeRate:", feeRate);
3662
3668
  try {
3663
3669
  const config = getWalletConfig(env);
3670
+ const _feeRate = feeRate || (yield getBtcGasPrice());
3664
3671
  const gasLimit = yield calculateGasLimit({
3665
3672
  csna,
3666
3673
  transactions: [
@@ -3697,7 +3704,7 @@ function calculateWithdraw(_0) {
3697
3704
  return {
3698
3705
  withdrawFee: 0,
3699
3706
  isError: true,
3700
- errorMsg: "Mini withdraw amount is " + (Number(brgConfig.min_withdraw_amount) + Number(gasLimit))
3707
+ errorMsg: `Mini withdraw amount is ${Number(brgConfig.min_withdraw_amount) + Number(gasLimit)} sats`
3701
3708
  };
3702
3709
  }
3703
3710
  }
@@ -3725,7 +3732,7 @@ function calculateWithdraw(_0) {
3725
3732
  const { inputs, outputs, fee } = (0, import_coinselect.default)(
3726
3733
  utxos,
3727
3734
  [{ address: btcAddress, value: userSatoshis }],
3728
- Math.ceil(feeRate || 0)
3735
+ Math.ceil(_feeRate)
3729
3736
  );
3730
3737
  const newInputs = inputs;
3731
3738
  let newOutputs = outputs;
@@ -3839,6 +3846,7 @@ function calculateWithdraw(_0) {
3839
3846
 
3840
3847
  // src/core/btcUtils.ts
3841
3848
  var import_bitcoinjs_lib = __toESM(require("bitcoinjs-lib"), 1);
3849
+ var import_coinselect2 = __toESM(require("coinselect"), 1);
3842
3850
  var ecc = __toESM(require("@bitcoinerlab/secp256k1"), 1);
3843
3851
  import_bitcoinjs_lib.default.initEccLib(ecc);
3844
3852
  var NEAR_STORAGE_DEPOSIT_AMOUNT = "1250000000000000000000";
@@ -3853,9 +3861,13 @@ function getBtcProvider() {
3853
3861
  }
3854
3862
  function getNetwork() {
3855
3863
  return __async(this, null, function* () {
3856
- const network = yield getBtcProvider().getNetwork();
3857
- console.log("btc network:", network);
3858
- return network === "livenet" ? "mainnet" : "testnet";
3864
+ try {
3865
+ const network = yield getBtcProvider().getNetwork();
3866
+ console.log("btc network:", network);
3867
+ return network === "livenet" ? "mainnet" : "testnet";
3868
+ } catch (error) {
3869
+ return "mainnet";
3870
+ }
3859
3871
  });
3860
3872
  }
3861
3873
  function getBtcRpcUrl() {
@@ -3918,25 +3930,37 @@ function getBtcGasPrice() {
3918
3930
  }
3919
3931
  });
3920
3932
  }
3921
- function getBtcBalance() {
3933
+ function getBtcUtxos(account) {
3922
3934
  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
3935
  const btcRpcUrl = yield getBtcRpcUrl();
3929
3936
  const utxos = yield fetch(`${btcRpcUrl}/address/${account}/utxo`).then((res) => res.json());
3937
+ return utxos;
3938
+ });
3939
+ }
3940
+ function calculateGasFee(account, amount, feeRate) {
3941
+ return __async(this, null, function* () {
3942
+ const _feeRate = feeRate || (yield getBtcGasPrice());
3943
+ const utxos = yield getBtcUtxos(account);
3944
+ const { fee } = (0, import_coinselect2.default)(utxos, [{ address: account, value: amount }], Math.ceil(_feeRate));
3945
+ console.log("calculateGasFee fee:", fee);
3946
+ return fee;
3947
+ });
3948
+ }
3949
+ function getBtcBalance(account) {
3950
+ return __async(this, null, function* () {
3951
+ if (!account) {
3952
+ const res = yield retryOperation(getBtcProvider, (res2) => !!res2.account);
3953
+ if (!res.account) {
3954
+ console.error("BTC Account is not available.");
3955
+ return { rawBalance: 0, balance: 0, availableBalance: 0 };
3956
+ }
3957
+ account = res.account;
3958
+ }
3959
+ const utxos = yield getBtcUtxos(account);
3930
3960
  const btcDecimals = 8;
3931
3961
  const rawBalance = (utxos == null ? void 0 : utxos.reduce((acc, cur) => acc + cur.value, 0)) || 0;
3932
3962
  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);
3963
+ const estimatedFee = yield calculateGasFee(account, rawBalance);
3940
3964
  const availableRawBalance = (rawBalance - estimatedFee).toFixed(0);
3941
3965
  const availableBalance = new import_big2.default(availableRawBalance).div(__pow(10, btcDecimals)).round(btcDecimals, import_big2.default.roundDown).toNumber();
3942
3966
  return {
@@ -3963,7 +3987,7 @@ function getDepositAmount(amount, option) {
3963
3987
  var _a;
3964
3988
  const env = (option == null ? void 0 : option.env) || "mainnet";
3965
3989
  const _newAccountMinDepositAmount = (_a = option == null ? void 0 : option.newAccountMinDepositAmount) != null ? _a : true;
3966
- const csna = yield getCsnaAccountId(env);
3990
+ const csna = (option == null ? void 0 : option.csna) || (yield getCsnaAccountId(env));
3967
3991
  const accountInfo = yield getAccountInfo({ csna, env });
3968
3992
  const debtAction = yield checkGasTokenDebt(csna, env, false);
3969
3993
  const repayAmount = (debtAction == null ? void 0 : debtAction.amount) || 0;
@@ -4160,18 +4184,18 @@ function getWithdrawTransaction(_0) {
4160
4184
  return __async(this, arguments, function* ({
4161
4185
  amount,
4162
4186
  feeRate,
4187
+ csna,
4188
+ btcAddress,
4163
4189
  env = "mainnet"
4164
4190
  }) {
4165
4191
  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());
4192
+ const _btcAddress = btcAddress || getBtcProvider().account;
4193
+ const _csna = csna || (yield getCsnaAccountId(env));
4170
4194
  const _a = yield calculateWithdraw({
4171
4195
  amount,
4172
- feeRate: _feeRate,
4173
- csna,
4174
- btcAddress,
4196
+ feeRate,
4197
+ csna: _csna,
4198
+ btcAddress: _btcAddress,
4175
4199
  env
4176
4200
  }), { inputs, outputs, isError, errorMsg } = _a, rest = __objRest(_a, ["inputs", "outputs", "isError", "errorMsg"]);
4177
4201
  if (isError || !inputs || !outputs) {
@@ -4187,7 +4211,7 @@ function getWithdrawTransaction(_0) {
4187
4211
  const btcNetwork = network === "mainnet" ? import_bitcoinjs_lib.default.networks.bitcoin : import_bitcoinjs_lib.default.networks.testnet;
4188
4212
  const psbt = new import_bitcoinjs_lib.default.Psbt({ network: btcNetwork });
4189
4213
  const btcRpcUrl = yield getBtcRpcUrl();
4190
- Promise.all(
4214
+ yield Promise.all(
4191
4215
  inputs.map((input) => __async(this, null, function* () {
4192
4216
  const txData = yield fetch(`${btcRpcUrl}/tx/${input.txid}`).then((res) => res.json());
4193
4217
  const inputOptions = {
@@ -4219,14 +4243,14 @@ function getWithdrawTransaction(_0) {
4219
4243
  });
4220
4244
  const msg = {
4221
4245
  Withdraw: {
4222
- target_btc_address: btcAddress,
4246
+ target_btc_address: _btcAddress,
4223
4247
  input: _inputs,
4224
4248
  output: txOutputs
4225
4249
  }
4226
4250
  };
4227
4251
  const transaction = {
4228
4252
  receiverId: config.btcToken,
4229
- signerId: csna,
4253
+ signerId: _csna,
4230
4254
  actions: [
4231
4255
  {
4232
4256
  type: "FunctionCall",
@@ -4301,7 +4325,6 @@ function createFloatingButtonWithIframe({
4301
4325
  zIndex: "100000",
4302
4326
  width: "60px",
4303
4327
  height: "60px",
4304
- borderRadius: "50%",
4305
4328
  cursor: "grab",
4306
4329
  transition: "transform 0.15s ease",
4307
4330
  userSelect: "none"
@@ -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.24-beta";
4795
4836
  };
4796
4837
  if (typeof window !== "undefined") {
4797
4838
  window.__BTC_WALLET_VERSION = getVersion();