btc-wallet 0.4.3-beta → 0.4.5-beta

Sign up to get free protection for your applications and to get access to all the features.
package/README.md CHANGED
@@ -66,7 +66,6 @@ interface ExecuteBTCDepositAndActionParams<T extends boolean = true> {
66
66
 
67
67
  // Common optional parameters
68
68
  feeRate?: number; // optional: custom fee rate for the BTC transaction
69
- fixedAmount?: boolean; // optional: whether to use fixed amount
70
69
  env?: 'mainnet' | 'testnet' | 'private_mainnet' | 'dev'; // optional: defaults to NEAR network environment
71
70
  pollResult?: T; // optional: whether to poll for transaction result
72
71
  registerDeposit?: string; // optional: whether to register deposit,default 0.000125 NEAR
@@ -1,27 +1,25 @@
1
1
  import type { ENV } from '../config';
2
- import type { FinalExecutionOutcome } from '@near-wallet-selector/core';
2
+ import type { FinalExecutionOutcome, Transaction } from '@near-wallet-selector/core';
3
3
  export interface AccountInfo {
4
4
  nonce: string;
5
5
  gas_token: Record<string, string>;
6
- debt_info?: DebtInfo;
6
+ debt_info?: {
7
+ gas_token_id: string;
8
+ near_gas_debt_amount: string;
9
+ protocol_fee_debt_amount: string;
10
+ };
7
11
  relayer_fee?: {
8
12
  amount?: string;
9
13
  };
10
14
  }
11
- export interface DebtInfo {
12
- gas_token_id: string;
13
- near_gas_debt_amount: string;
14
- protocol_fee_debt_amount: string;
15
- }
16
15
  export declare function getAccountInfo(csna: string, accountContractId: string): Promise<AccountInfo | undefined>;
17
16
  export declare function checkGasTokenBalance(csna: string, gasToken: string, minAmount: string, env: ENV): Promise<void>;
18
- type CheckGasTokenArrearsReturnType<T extends boolean> = T extends true ? void : {
17
+ type CheckGasTokenDebtReturnType<T extends boolean> = T extends true ? void : {
19
18
  receiver_id: string;
20
19
  amount: string;
21
20
  msg: string;
22
21
  } | undefined;
23
- export declare function checkGasTokenArrears<T extends boolean>(accountInfo: AccountInfo | undefined, env: ENV, autoDeposit?: T): Promise<CheckGasTokenArrearsReturnType<T>>;
24
- export declare function queryGasTokenArrears(env: ENV): Promise<DebtInfo | undefined>;
22
+ export declare function checkGasTokenDebt<T extends boolean>(accountInfo: AccountInfo | undefined, env: ENV, autoDeposit?: T): Promise<CheckGasTokenDebtReturnType<T>>;
25
23
  export declare function getBtcGasPrice(): Promise<number>;
26
24
  export declare function getBtcBalance(): Promise<{
27
25
  rawBalance: number;
@@ -34,17 +32,24 @@ export declare function getBtcBalance(): Promise<{
34
32
  availableBalance: number;
35
33
  maxSpendableBalance?: undefined;
36
34
  }>;
35
+ export declare function getNBTCBalance(address: string, env?: ENV): Promise<{
36
+ balance: number;
37
+ availableBalance: number;
38
+ rawBalance: string;
39
+ rawAvailableBalance: number;
40
+ }>;
37
41
  export declare function sendBitcoin(address: string, amount: number, feeRate: number): Promise<string>;
42
+ /** estimate deposit receive amount, deduct protocol fee and repay amount */
38
43
  export declare function estimateDepositAmount(amount: string, option?: {
39
44
  env?: ENV;
40
- }): Promise<number>;
45
+ }): Promise<string>;
41
46
  export declare function getDepositAmount(amount: string, option?: {
42
- isEstimate?: boolean;
43
47
  env?: ENV;
44
48
  }): Promise<{
45
49
  depositAmount: number;
46
- receiveAmount: number;
47
- fee: number;
50
+ totalDepositAmount: number;
51
+ protocolFee: number;
52
+ repayAmount: string | number;
48
53
  }>;
49
54
  export declare function getCsnaAccountId(env: ENV): Promise<string>;
50
55
  interface ExecuteBTCDepositAndActionParams<T extends boolean = true> {
@@ -57,7 +62,6 @@ interface ExecuteBTCDepositAndActionParams<T extends boolean = true> {
57
62
  /** if registerDeposit is true, It will consume the deposit, otherwise it will be 0.000125 NEAR */
58
63
  registerDeposit?: string;
59
64
  feeRate?: number;
60
- fixedAmount?: boolean;
61
65
  env?: ENV;
62
66
  pollResult?: T;
63
67
  }
@@ -65,6 +69,12 @@ interface ExecuteBTCDepositAndActionParams<T extends boolean = true> {
65
69
  * @param T - if true, return the poll result, otherwise return the btcTxHash
66
70
  */
67
71
  type ExecuteBTCDepositAndActionReturn<T extends boolean> = T extends true ? FinalExecutionOutcome[] : string;
68
- export declare function executeBTCDepositAndAction<T extends boolean = true>({ action, amount, feeRate, fixedAmount, pollResult, registerDeposit, env, }: ExecuteBTCDepositAndActionParams<T>): Promise<ExecuteBTCDepositAndActionReturn<T>>;
72
+ export declare function executeBTCDepositAndAction<T extends boolean = true>({ action, amount, feeRate, pollResult, registerDeposit, env, }: ExecuteBTCDepositAndActionParams<T>): Promise<ExecuteBTCDepositAndActionReturn<T>>;
69
73
  export declare function checkSatoshiWhitelist(btcAccountId: string, env?: ENV): Promise<void>;
74
+ interface WithdrawParams {
75
+ amount: string | number;
76
+ feeRate?: number;
77
+ env?: ENV;
78
+ }
79
+ export declare function getWithdrawTransaction({ amount, feeRate, env, }: WithdrawParams): Promise<Transaction>;
70
80
  export {};
package/dist/index.js CHANGED
@@ -90,8 +90,8 @@ __export(src_exports, {
90
90
  UnisatConnector: () => UnisatConnector,
91
91
  WizzConnector: () => WizzConnector,
92
92
  XverseConnector: () => XverseConnector,
93
- checkGasTokenArrears: () => checkGasTokenArrears,
94
93
  checkGasTokenBalance: () => checkGasTokenBalance,
94
+ checkGasTokenDebt: () => checkGasTokenDebt,
95
95
  checkSatoshiWhitelist: () => checkSatoshiWhitelist,
96
96
  estimateDepositAmount: () => estimateDepositAmount,
97
97
  executeBTCDepositAndAction: () => executeBTCDepositAndAction,
@@ -100,8 +100,9 @@ __export(src_exports, {
100
100
  getBtcGasPrice: () => getBtcGasPrice,
101
101
  getCsnaAccountId: () => getCsnaAccountId,
102
102
  getDepositAmount: () => getDepositAmount,
103
+ getNBTCBalance: () => getNBTCBalance,
103
104
  getVersion: () => getVersion,
104
- queryGasTokenArrears: () => queryGasTokenArrears,
105
+ getWithdrawTransaction: () => getWithdrawTransaction,
105
106
  sendBitcoin: () => sendBitcoin,
106
107
  setupBTCWallet: () => setupBTCWallet,
107
108
  useAccountContract: () => useAccountContract,
@@ -479,39 +480,11 @@ var XverseConnector = class extends BaseConnector {
479
480
  if (!provider) {
480
481
  throw new Error(`${this.metadata.name} is not install!`);
481
482
  }
482
- const { sendBtcTransaction } = yield import("sats-connect");
483
- const addresses = yield this.getAccounts();
484
- if (addresses.length === 0) {
485
- throw new Error(`${this.metadata.name} not connected!`);
486
- }
487
- const result = yield new Promise((resolve, reject) => {
488
- const sendBtcOptions = {
489
- payload: {
490
- network: {
491
- type: __privateGet(this, _network)
492
- },
493
- recipients: [
494
- {
495
- address: toAddress,
496
- amountSats: BigInt(satoshis)
497
- }
498
- ],
499
- senderAddress: addresses[0]
500
- },
501
- onFinish: (response) => {
502
- resolve(response);
503
- },
504
- onCancel: () => {
505
- reject({
506
- code: 4001,
507
- message: "User rejected the request."
508
- });
509
- }
510
- };
511
- console.log("\u{1F680} ~ XverseConnector ~ sendBitcoin ~ sendBtcOptions:", sendBtcOptions);
512
- sendBtcTransaction(sendBtcOptions).catch((e) => reject(e));
483
+ const { result } = yield provider.request("sendTransfer", {
484
+ recipients: [{ address: toAddress, amount: satoshis }]
513
485
  });
514
- return result;
486
+ console.log("\u{1F680} ~ XverseConnector ~ sendBitcoin ~ res:", result);
487
+ return result.txid;
515
488
  });
516
489
  }
517
490
  disconnect() {
@@ -2429,6 +2402,7 @@ function BtcWalletSelectorContextProvider({
2429
2402
  const [isProcessing, setIsProcessing] = (0, import_react11.useState)(false);
2430
2403
  const connectors = [
2431
2404
  new UnisatConnector(),
2405
+ new XverseConnector(),
2432
2406
  new OKXConnector(),
2433
2407
  new BitgetConnector()
2434
2408
  ];
@@ -3268,9 +3242,10 @@ Dialog.style = `
3268
3242
  `;
3269
3243
 
3270
3244
  // src/core/btcUtils.ts
3271
- var MINIMUM_DEPOSIT_AMOUNT_BASE = 0;
3245
+ var import_bitcoinjs_lib = __toESM(require("bitcoinjs-lib"), 1);
3246
+ var import_coinselect = __toESM(require("coinselect"), 1);
3272
3247
  var NEAR_STORAGE_DEPOSIT_AMOUNT = "1250000000000000000000";
3273
- var NBTC_STORAGE_DEPOSIT_AMOUNT = 3e3;
3248
+ var NBTC_STORAGE_DEPOSIT_AMOUNT = "3000";
3274
3249
  var GAS_LIMIT = "50000000000000";
3275
3250
  function getBtcProvider() {
3276
3251
  if (typeof window === "undefined" || !window.btcContext) {
@@ -3328,11 +3303,11 @@ function checkGasTokenBalance(csna, gasToken, minAmount, env) {
3328
3303
  }
3329
3304
  });
3330
3305
  }
3331
- function checkGasTokenArrears(accountInfo, env, autoDeposit) {
3306
+ function checkGasTokenDebt(accountInfo, env, autoDeposit) {
3332
3307
  return __async(this, null, function* () {
3333
3308
  var _a, _b, _c;
3334
3309
  const debtAmount = new import_big.default(((_a = accountInfo == null ? void 0 : accountInfo.debt_info) == null ? void 0 : _a.near_gas_debt_amount) || 0).plus(((_b = accountInfo == null ? void 0 : accountInfo.debt_info) == null ? void 0 : _b.protocol_fee_debt_amount) || 0).toString();
3335
- const relayerFeeAmount = ((_c = accountInfo == null ? void 0 : accountInfo.relayer_fee) == null ? void 0 : _c.amount) || "0";
3310
+ const relayerFeeAmount = !(accountInfo == null ? void 0 : accountInfo.nonce) ? NBTC_STORAGE_DEPOSIT_AMOUNT : ((_c = accountInfo == null ? void 0 : accountInfo.relayer_fee) == null ? void 0 : _c.amount) || 0;
3336
3311
  const hasDebtArrears = new import_big.default(debtAmount).gt(0);
3337
3312
  const hasRelayerFeeArrears = new import_big.default(relayerFeeAmount).gt(0);
3338
3313
  if (!hasDebtArrears && !hasRelayerFeeArrears)
@@ -3342,7 +3317,7 @@ function checkGasTokenArrears(accountInfo, env, autoDeposit) {
3342
3317
  console.log("get_account:", accountInfo);
3343
3318
  const action = {
3344
3319
  receiver_id: config.accountContractId,
3345
- amount: transferAmount,
3320
+ amount: transferAmount.toString(),
3346
3321
  msg: JSON.stringify(hasDebtArrears ? "Repay" : "RelayerFee")
3347
3322
  };
3348
3323
  if (!autoDeposit)
@@ -3362,14 +3337,6 @@ function checkGasTokenArrears(accountInfo, env, autoDeposit) {
3362
3337
  }
3363
3338
  });
3364
3339
  }
3365
- function queryGasTokenArrears(env) {
3366
- return __async(this, null, function* () {
3367
- const config = yield getConfig(env);
3368
- const csna = yield getCsnaAccountId(env);
3369
- const accountInfo = yield getAccountInfo(csna, config.accountContractId);
3370
- return accountInfo == null ? void 0 : accountInfo.debt_info;
3371
- });
3372
- }
3373
3340
  function getBtcGasPrice() {
3374
3341
  return __async(this, null, function* () {
3375
3342
  const network = yield getNetwork();
@@ -3411,6 +3378,18 @@ function getBtcBalance() {
3411
3378
  };
3412
3379
  });
3413
3380
  }
3381
+ function getNBTCBalance(address, env) {
3382
+ return __async(this, null, function* () {
3383
+ const config = yield getConfig(env || "mainnet");
3384
+ const rawBalance = yield nearCall(config.token, "ft_balance_of", {
3385
+ account_id: address
3386
+ });
3387
+ const balance = new import_big.default(rawBalance).div(__pow(10, 8)).round(8, import_big.default.roundDown).toNumber();
3388
+ const rawAvailableBalance = new import_big.default(rawBalance).minus(1e3).toNumber();
3389
+ const availableBalance = new import_big.default(rawAvailableBalance).div(__pow(10, 8)).round(8, import_big.default.roundDown).toNumber();
3390
+ return { balance, availableBalance, rawBalance, rawAvailableBalance };
3391
+ });
3392
+ }
3414
3393
  function sendBitcoin(address, amount, feeRate) {
3415
3394
  return __async(this, null, function* () {
3416
3395
  const { sendBitcoin: sendBitcoin2 } = getBtcProvider();
@@ -3420,28 +3399,29 @@ function sendBitcoin(address, amount, feeRate) {
3420
3399
  }
3421
3400
  function estimateDepositAmount(amount, option) {
3422
3401
  return __async(this, null, function* () {
3423
- const config = yield getConfig((option == null ? void 0 : option.env) || "mainnet");
3424
- const csna = yield getCsnaAccountId((option == null ? void 0 : option.env) || "mainnet");
3425
- const accountInfo = yield getAccountInfo(csna, config.accountContractId);
3426
- const { receiveAmount } = yield getDepositAmount(amount, __spreadProps(__spreadValues({}, option), { isEstimate: true }));
3427
- return (accountInfo == null ? void 0 : accountInfo.nonce) ? receiveAmount : new import_big.default(receiveAmount).minus(NBTC_STORAGE_DEPOSIT_AMOUNT).round(0, import_big.default.roundDown).toNumber();
3402
+ return amount;
3428
3403
  });
3429
3404
  }
3430
3405
  function getDepositAmount(amount, option) {
3431
3406
  return __async(this, null, function* () {
3432
- const config = yield getConfig((option == null ? void 0 : option.env) || "mainnet");
3407
+ const env = (option == null ? void 0 : option.env) || "mainnet";
3408
+ const config = yield getConfig(env);
3409
+ const csna = yield getCsnaAccountId(env);
3410
+ const accountInfo = yield getAccountInfo(csna, config.accountContractId);
3411
+ const debtAction = yield checkGasTokenDebt(accountInfo, env, false);
3412
+ const repayAmount = (debtAction == null ? void 0 : debtAction.amount) || 0;
3433
3413
  const {
3434
3414
  deposit_bridge_fee: { fee_min, fee_rate },
3435
3415
  min_deposit_amount
3436
3416
  } = yield nearCall(config.bridgeContractId, "get_config", {});
3437
- const depositAmount = (option == null ? void 0 : option.isEstimate) ? Number(amount) : Math.max(Number(min_deposit_amount) + MINIMUM_DEPOSIT_AMOUNT_BASE, Number(amount));
3438
- const fee = Math.max(Number(fee_min), Number(depositAmount) * fee_rate);
3439
- const receiveAmount = new import_big.default(depositAmount).minus(fee).minus(MINIMUM_DEPOSIT_AMOUNT_BASE).round(0, import_big.default.roundDown).toNumber();
3440
- console.log("getDepositAmount:", { depositAmount, receiveAmount, fee });
3417
+ const depositAmount = Math.max(Number(min_deposit_amount), Number(amount));
3418
+ const protocolFee = Math.max(Number(fee_min), Number(depositAmount) * fee_rate);
3419
+ const totalDepositAmount = new import_big.default(depositAmount).plus(protocolFee).plus(repayAmount).round(0, import_big.default.roundDown).toNumber();
3441
3420
  return {
3442
3421
  depositAmount,
3443
- receiveAmount: Math.max(receiveAmount, 0),
3444
- fee
3422
+ totalDepositAmount,
3423
+ protocolFee,
3424
+ repayAmount
3445
3425
  };
3446
3426
  });
3447
3427
  }
@@ -3465,7 +3445,6 @@ function executeBTCDepositAndAction(_0) {
3465
3445
  action,
3466
3446
  amount,
3467
3447
  feeRate,
3468
- fixedAmount = true,
3469
3448
  pollResult = true,
3470
3449
  registerDeposit,
3471
3450
  env = "mainnet"
@@ -3482,33 +3461,25 @@ function executeBTCDepositAndAction(_0) {
3482
3461
  throw new Error("amount or action is required");
3483
3462
  }
3484
3463
  const csna = yield getCsnaAccountId(env);
3485
- const rawDepositAmount = (_a = action ? action.amount : amount) != null ? _a : "0";
3486
- if (new import_big.default(rawDepositAmount).lt(0)) {
3464
+ const depositAmount = (_a = action ? action.amount : amount) != null ? _a : "0";
3465
+ if (new import_big.default(depositAmount).lt(0)) {
3487
3466
  throw new Error("amount must be greater than 0");
3488
3467
  }
3489
- const { depositAmount, receiveAmount } = yield getDepositAmount(rawDepositAmount, {
3468
+ const { totalDepositAmount, protocolFee, repayAmount } = yield getDepositAmount(depositAmount, {
3490
3469
  env
3491
3470
  });
3492
3471
  const accountInfo = yield getAccountInfo(csna, config.accountContractId);
3493
3472
  const newActions = [];
3494
- const arrearsAction = yield checkGasTokenArrears(accountInfo, env, false);
3495
- if (arrearsAction) {
3496
- newActions.push(__spreadProps(__spreadValues({}, arrearsAction), {
3473
+ const debtAction = yield checkGasTokenDebt(accountInfo, env, false);
3474
+ if (debtAction) {
3475
+ newActions.push(__spreadProps(__spreadValues({}, debtAction), {
3497
3476
  gas: GAS_LIMIT
3498
3477
  }));
3499
3478
  }
3500
- if (action || !action && new import_big.default((accountInfo == null ? void 0 : accountInfo.gas_token[config.token]) || 0).lt(MINIMUM_DEPOSIT_AMOUNT_BASE)) {
3501
- newActions.push(
3502
- action ? __spreadProps(__spreadValues({}, action), {
3503
- amount: (arrearsAction == null ? void 0 : arrearsAction.amount) && !fixedAmount ? new import_big.default(receiveAmount).minus(arrearsAction.amount).toString() : receiveAmount.toString(),
3504
- gas: GAS_LIMIT
3505
- }) : {
3506
- receiver_id: config.accountContractId,
3507
- amount: MINIMUM_DEPOSIT_AMOUNT_BASE.toString(),
3508
- msg: JSON.stringify("Deposit"),
3509
- gas: GAS_LIMIT
3510
- }
3511
- );
3479
+ if (action) {
3480
+ newActions.push(__spreadProps(__spreadValues({}, action), {
3481
+ gas: GAS_LIMIT
3482
+ }));
3512
3483
  }
3513
3484
  const storageDepositMsg = {};
3514
3485
  const registerRes = yield nearCall((action == null ? void 0 : action.receiver_id) || config.token, "storage_balance_of", {
@@ -3523,12 +3494,6 @@ function executeBTCDepositAndAction(_0) {
3523
3494
  }
3524
3495
  if (!(accountInfo == null ? void 0 : accountInfo.nonce)) {
3525
3496
  storageDepositMsg.btc_public_key = btcPublicKey;
3526
- newActions.push({
3527
- receiver_id: config.accountContractId,
3528
- amount: NBTC_STORAGE_DEPOSIT_AMOUNT.toString(),
3529
- msg: JSON.stringify("RelayerFee"),
3530
- gas: GAS_LIMIT
3531
- });
3532
3497
  }
3533
3498
  const depositMsg = {
3534
3499
  recipient_id: csna,
@@ -3542,10 +3507,14 @@ function executeBTCDepositAndAction(_0) {
3542
3507
  { deposit_msg: depositMsg }
3543
3508
  );
3544
3509
  const _feeRate = feeRate || (yield getBtcGasPrice());
3545
- const sendAmount = (arrearsAction == null ? void 0 : arrearsAction.amount) && fixedAmount ? new import_big.default(depositAmount).plus((arrearsAction == null ? void 0 : arrearsAction.amount) || 0).toString() : depositAmount;
3546
- console.log("user deposit address:", userDepositAddress);
3547
- console.log("send amount:", sendAmount);
3548
- console.log("fee rate:", _feeRate);
3510
+ console.table({
3511
+ "User Deposit Address": userDepositAddress,
3512
+ "Deposit Amount": depositAmount,
3513
+ "Protocol Fee": protocolFee,
3514
+ "Repay Amount": repayAmount,
3515
+ "Total Deposit Amount": totalDepositAmount,
3516
+ "Fee Rate": _feeRate
3517
+ });
3549
3518
  const postActionsStr = newActions.length > 0 ? JSON.stringify(newActions) : void 0;
3550
3519
  yield preReceiveDepositMsg(config.base_url, {
3551
3520
  btcPublicKey,
@@ -3553,7 +3522,7 @@ function executeBTCDepositAndAction(_0) {
3553
3522
  postActions: postActionsStr,
3554
3523
  extraMsg: depositMsg.extra_msg
3555
3524
  });
3556
- const txHash = yield sendBitcoin(userDepositAddress, Number(sendAmount), _feeRate);
3525
+ const txHash = yield sendBitcoin(userDepositAddress, totalDepositAmount, _feeRate);
3557
3526
  yield receiveDepositMsg(config.base_url, {
3558
3527
  btcPublicKey,
3559
3528
  txHash,
@@ -3598,6 +3567,149 @@ Sign up now: <a style="color: #ff7a00; text-decoration: underline;" href="https:
3598
3567
  }
3599
3568
  });
3600
3569
  }
3570
+ function getWithdrawTransaction(_0) {
3571
+ return __async(this, arguments, function* ({
3572
+ amount,
3573
+ feeRate,
3574
+ env = "mainnet"
3575
+ }) {
3576
+ const provider = getBtcProvider();
3577
+ const btcAddress = yield provider.account;
3578
+ const config = yield getConfig(env);
3579
+ const brgConfig = yield nearCall(config.bridgeContractId, "get_config", {});
3580
+ const _amount = Number(new import_big.default(amount).mul(__pow(10, 8)).toFixed(0));
3581
+ if (brgConfig.min_withdraw_amount) {
3582
+ if (_amount < Number(brgConfig.min_withdraw_amount)) {
3583
+ throw new Error("Mini withdraw amount is " + brgConfig.min_withdraw_amount);
3584
+ }
3585
+ }
3586
+ const feePercent = Number(brgConfig.withdraw_bridge_fee.fee_rate) * _amount;
3587
+ const withdrawFee = feePercent > Number(brgConfig.withdraw_bridge_fee.fee_min) ? feePercent : Number(brgConfig.withdraw_bridge_fee.fee_min);
3588
+ const allUTXO = yield nearCall(config.bridgeContractId, "get_utxos_paged", {});
3589
+ if (!allUTXO || Object.keys(allUTXO).length === 0) {
3590
+ throw new Error("The network is busy, please try again later.");
3591
+ }
3592
+ const utxos = Object.keys(allUTXO).map((key) => {
3593
+ const txid = key.split("@");
3594
+ return {
3595
+ txid: txid[0],
3596
+ vout: allUTXO[key].vout,
3597
+ value: Number(allUTXO[key].balance),
3598
+ script: allUTXO[key].script
3599
+ };
3600
+ });
3601
+ const _feeRate = feeRate || (yield getBtcGasPrice());
3602
+ const { inputs, outputs, fee } = (0, import_coinselect.default)(
3603
+ utxos,
3604
+ [{ address: btcAddress, value: _amount }],
3605
+ Math.ceil(_feeRate)
3606
+ );
3607
+ if (!outputs || !inputs) {
3608
+ throw new Error("The network is busy, please try again later.");
3609
+ }
3610
+ const maxBtcFee = Number(brgConfig.max_btc_gas_fee);
3611
+ const newFee = fee;
3612
+ const withdrawChangeAddress = brgConfig.change_address;
3613
+ if (newFee > maxBtcFee) {
3614
+ throw new Error("Gas exceeds maximum value");
3615
+ }
3616
+ let userOutput, noUserOutput;
3617
+ for (let i = 0; i < outputs.length; i++) {
3618
+ const output = outputs[i];
3619
+ if (output.value.toString() === _amount.toString()) {
3620
+ userOutput = output;
3621
+ } else {
3622
+ noUserOutput = output;
3623
+ }
3624
+ if (!output.address) {
3625
+ output.address = withdrawChangeAddress;
3626
+ }
3627
+ }
3628
+ userOutput.value = new import_big.default(userOutput.value).minus(newFee).minus(withdrawFee).toNumber();
3629
+ if (noUserOutput) {
3630
+ noUserOutput.value = new import_big.default(noUserOutput.value).plus(newFee).plus(withdrawFee).toNumber();
3631
+ } else {
3632
+ noUserOutput = {
3633
+ address: withdrawChangeAddress,
3634
+ value: new import_big.default(newFee).plus(withdrawFee).toNumber()
3635
+ };
3636
+ outputs.push(noUserOutput);
3637
+ }
3638
+ const insufficientOutput = outputs.some((item) => item.value < 0);
3639
+ if (insufficientOutput) {
3640
+ throw new Error("Not enough gas");
3641
+ }
3642
+ const inputSum = inputs.reduce((sum, cur) => sum + Number(cur.value), 0);
3643
+ const outputSum = outputs.reduce((sum, cur) => sum + Number(cur.value), 0);
3644
+ if (newFee + outputSum !== inputSum) {
3645
+ throw new Error("compute error");
3646
+ }
3647
+ const network = yield getNetwork();
3648
+ const btcNetwork = network === "mainnet" ? import_bitcoinjs_lib.default.networks.bitcoin : import_bitcoinjs_lib.default.networks.testnet;
3649
+ const psbt = new import_bitcoinjs_lib.default.Psbt({ network: btcNetwork });
3650
+ const btcRpcUrl = yield getBtcRpcUrl();
3651
+ for (let i = 0; i < inputs.length; i++) {
3652
+ const input = inputs[i];
3653
+ const txData = yield fetch(`${btcRpcUrl}/tx/${input.txid}`).then((res) => res.json());
3654
+ const inputOptions = {
3655
+ hash: input.txid,
3656
+ index: input.vout,
3657
+ sequence: 4294967293,
3658
+ witnessUtxo: {
3659
+ script: Buffer.from(txData.vout[input.vout].scriptpubkey, "hex"),
3660
+ value: input.value
3661
+ }
3662
+ };
3663
+ psbt.addInput(inputOptions);
3664
+ }
3665
+ outputs.forEach((output) => {
3666
+ psbt.addOutput({
3667
+ address: output.address,
3668
+ value: output.value
3669
+ });
3670
+ });
3671
+ const _inputs = inputs.map((item) => {
3672
+ return `${item.txid}:${item.vout}`;
3673
+ });
3674
+ const txOutputs = psbt.txOutputs.map((item) => {
3675
+ return {
3676
+ script_pubkey: uint8ArrayToHex(item.script),
3677
+ value: item.value
3678
+ };
3679
+ });
3680
+ const msg = {
3681
+ Withdraw: {
3682
+ target_btc_address: btcAddress,
3683
+ input: _inputs,
3684
+ output: txOutputs
3685
+ }
3686
+ };
3687
+ const csna = yield getCsnaAccountId(env);
3688
+ const transaction = {
3689
+ receiverId: config.token,
3690
+ signerId: csna,
3691
+ actions: [
3692
+ {
3693
+ type: "FunctionCall",
3694
+ params: {
3695
+ methodName: "ft_transfer_call",
3696
+ args: {
3697
+ receiver_id: config.bridgeContractId,
3698
+ amount: _amount.toString(),
3699
+ msg: JSON.stringify(msg)
3700
+ },
3701
+ gas: "300000000000000",
3702
+ deposit: "1"
3703
+ }
3704
+ }
3705
+ ]
3706
+ };
3707
+ return transaction;
3708
+ });
3709
+ }
3710
+ function uint8ArrayToHex(uint8Array) {
3711
+ return Array.from(uint8Array).map((byte) => byte.toString(16).padStart(2, "0")).join("");
3712
+ }
3601
3713
 
3602
3714
  // src/core/setupBTCWallet.ts
3603
3715
  var { transfer, functionCall } = import_transactions.actionCreators;
@@ -3823,7 +3935,7 @@ var BTCWallet = (_0) => __async(void 0, [_0], function* ({
3823
3935
  const btcContext = window.btcContext;
3824
3936
  const accountId = state.getAccount();
3825
3937
  const accountInfo = yield getAccountInfo(accountId, currentConfig.accountContractId);
3826
- yield checkGasTokenArrears(accountInfo, env, true);
3938
+ yield checkGasTokenDebt(accountInfo, env, true);
3827
3939
  const trans = [...params.transactions];
3828
3940
  console.log("raw trans:", trans);
3829
3941
  const gasTokenBalance = (accountInfo == null ? void 0 : accountInfo.gas_token[currentConfig.token]) || "0";
@@ -3892,7 +4004,7 @@ var BTCWallet = (_0) => __async(void 0, [_0], function* ({
3892
4004
  args: {
3893
4005
  receiver_id: currentConfig.accountContractId,
3894
4006
  amount,
3895
- msg: JSON.stringify("Deposit")
4007
+ msg: JSON.stringify("Repay")
3896
4008
  },
3897
4009
  gas: new import_big2.default(50).mul(__pow(10, 12)).toFixed(0),
3898
4010
  deposit: "1"
@@ -4032,7 +4144,7 @@ function setupBTCWallet({
4032
4144
  if (!hasShownNotice) {
4033
4145
  Dialog.alert({
4034
4146
  title: "Notice",
4035
- message: "You are currently using Satoshi Private Mainnet. This is a private version for testing. Please try a small amount of assets in Bridge"
4147
+ message: "You are currently using Satoshi Private Mainnet. This is a private version for testing. Please try a small amount of assets in Ramp"
4036
4148
  });
4037
4149
  localStorage.setItem("satoshi_private_mainnet_notice", "true");
4038
4150
  }
@@ -4061,7 +4173,7 @@ function setupBTCWallet({
4061
4173
 
4062
4174
  // src/index.ts
4063
4175
  var getVersion = () => {
4064
- return "0.4.3-beta";
4176
+ return "0.4.5-beta";
4065
4177
  };
4066
4178
  if (typeof window !== "undefined") {
4067
4179
  window.__BTC_WALLET_VERSION = getVersion();