btc-wallet 0.4.4-beta → 0.4.6-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.
@@ -19,4 +19,5 @@ export declare function checkBtcTransactionStatus(url: string, sig: string): Pro
19
19
  NearHashList: string[];
20
20
  }>;
21
21
  export declare function getWhitelist(url: string): Promise<string[]>;
22
+ export declare function receiveWithdrawMsg(url: string, txHash: string): Promise<any>;
22
23
  export {};
package/esm/index.js CHANGED
@@ -2354,6 +2354,7 @@ function BtcWalletSelectorContextProvider({
2354
2354
  const [isProcessing, setIsProcessing] = useState8(false);
2355
2355
  const connectors = [
2356
2356
  new UnisatConnector(),
2357
+ new XverseConnector(),
2357
2358
  new OKXConnector(),
2358
2359
  new BitgetConnector()
2359
2360
  ];
@@ -3193,9 +3194,10 @@ Dialog.style = `
3193
3194
  `;
3194
3195
 
3195
3196
  // src/core/btcUtils.ts
3196
- var MINIMUM_DEPOSIT_AMOUNT_BASE = 0;
3197
+ import bitcoin from "bitcoinjs-lib";
3198
+ import coinselect from "coinselect";
3197
3199
  var NEAR_STORAGE_DEPOSIT_AMOUNT = "1250000000000000000000";
3198
- var NBTC_STORAGE_DEPOSIT_AMOUNT = 3e3;
3200
+ var NBTC_STORAGE_DEPOSIT_AMOUNT = "3000";
3199
3201
  var GAS_LIMIT = "50000000000000";
3200
3202
  function getBtcProvider() {
3201
3203
  if (typeof window === "undefined" || !window.btcContext) {
@@ -3253,11 +3255,11 @@ function checkGasTokenBalance(csna, gasToken, minAmount, env) {
3253
3255
  }
3254
3256
  });
3255
3257
  }
3256
- function checkGasTokenArrears(accountInfo, env, autoDeposit) {
3258
+ function checkGasTokenDebt(accountInfo, env, autoDeposit) {
3257
3259
  return __async(this, null, function* () {
3258
3260
  var _a, _b, _c;
3259
3261
  const debtAmount = new Big(((_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();
3260
- const relayerFeeAmount = ((_c = accountInfo == null ? void 0 : accountInfo.relayer_fee) == null ? void 0 : _c.amount) || "0";
3262
+ 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;
3261
3263
  const hasDebtArrears = new Big(debtAmount).gt(0);
3262
3264
  const hasRelayerFeeArrears = new Big(relayerFeeAmount).gt(0);
3263
3265
  if (!hasDebtArrears && !hasRelayerFeeArrears)
@@ -3267,7 +3269,7 @@ function checkGasTokenArrears(accountInfo, env, autoDeposit) {
3267
3269
  console.log("get_account:", accountInfo);
3268
3270
  const action = {
3269
3271
  receiver_id: config.accountContractId,
3270
- amount: transferAmount,
3272
+ amount: transferAmount.toString(),
3271
3273
  msg: JSON.stringify(hasDebtArrears ? "Repay" : "RelayerFee")
3272
3274
  };
3273
3275
  if (!autoDeposit)
@@ -3287,14 +3289,6 @@ function checkGasTokenArrears(accountInfo, env, autoDeposit) {
3287
3289
  }
3288
3290
  });
3289
3291
  }
3290
- function queryGasTokenArrears(env) {
3291
- return __async(this, null, function* () {
3292
- const config = yield getConfig(env);
3293
- const csna = yield getCsnaAccountId(env);
3294
- const accountInfo = yield getAccountInfo(csna, config.accountContractId);
3295
- return accountInfo == null ? void 0 : accountInfo.debt_info;
3296
- });
3297
- }
3298
3292
  function getBtcGasPrice() {
3299
3293
  return __async(this, null, function* () {
3300
3294
  const network = yield getNetwork();
@@ -3336,6 +3330,18 @@ function getBtcBalance() {
3336
3330
  };
3337
3331
  });
3338
3332
  }
3333
+ function getNBTCBalance(address, env) {
3334
+ return __async(this, null, function* () {
3335
+ const config = yield getConfig(env || "mainnet");
3336
+ const rawBalance = yield nearCall(config.token, "ft_balance_of", {
3337
+ account_id: address
3338
+ });
3339
+ const balance = new Big(rawBalance).div(__pow(10, 8)).round(8, Big.roundDown).toNumber();
3340
+ const rawAvailableBalance = new Big(rawBalance).minus(1e3).toNumber();
3341
+ const availableBalance = new Big(rawAvailableBalance).div(__pow(10, 8)).round(8, Big.roundDown).toNumber();
3342
+ return { balance, availableBalance, rawBalance, rawAvailableBalance };
3343
+ });
3344
+ }
3339
3345
  function sendBitcoin(address, amount, feeRate) {
3340
3346
  return __async(this, null, function* () {
3341
3347
  const { sendBitcoin: sendBitcoin2 } = getBtcProvider();
@@ -3345,28 +3351,29 @@ function sendBitcoin(address, amount, feeRate) {
3345
3351
  }
3346
3352
  function estimateDepositAmount(amount, option) {
3347
3353
  return __async(this, null, function* () {
3348
- const config = yield getConfig((option == null ? void 0 : option.env) || "mainnet");
3349
- const csna = yield getCsnaAccountId((option == null ? void 0 : option.env) || "mainnet");
3350
- const accountInfo = yield getAccountInfo(csna, config.accountContractId);
3351
- const { receiveAmount } = yield getDepositAmount(amount, __spreadProps(__spreadValues({}, option), { isEstimate: true }));
3352
- return (accountInfo == null ? void 0 : accountInfo.nonce) ? receiveAmount : new Big(receiveAmount).minus(NBTC_STORAGE_DEPOSIT_AMOUNT).round(0, Big.roundDown).toNumber();
3354
+ return amount;
3353
3355
  });
3354
3356
  }
3355
3357
  function getDepositAmount(amount, option) {
3356
3358
  return __async(this, null, function* () {
3357
- const config = yield getConfig((option == null ? void 0 : option.env) || "mainnet");
3359
+ const env = (option == null ? void 0 : option.env) || "mainnet";
3360
+ const config = yield getConfig(env);
3361
+ const csna = yield getCsnaAccountId(env);
3362
+ const accountInfo = yield getAccountInfo(csna, config.accountContractId);
3363
+ const debtAction = yield checkGasTokenDebt(accountInfo, env, false);
3364
+ const repayAmount = (debtAction == null ? void 0 : debtAction.amount) || 0;
3358
3365
  const {
3359
3366
  deposit_bridge_fee: { fee_min, fee_rate },
3360
3367
  min_deposit_amount
3361
3368
  } = yield nearCall(config.bridgeContractId, "get_config", {});
3362
- const depositAmount = (option == null ? void 0 : option.isEstimate) ? Number(amount) : Math.max(Number(min_deposit_amount) + MINIMUM_DEPOSIT_AMOUNT_BASE, Number(amount));
3363
- const fee = Math.max(Number(fee_min), Number(depositAmount) * fee_rate);
3364
- const receiveAmount = new Big(depositAmount).minus(fee).minus(MINIMUM_DEPOSIT_AMOUNT_BASE).round(0, Big.roundDown).toNumber();
3365
- console.log("getDepositAmount:", { depositAmount, receiveAmount, fee });
3369
+ const depositAmount = Math.max(Number(min_deposit_amount), Number(amount));
3370
+ const protocolFee = Math.max(Number(fee_min), Number(depositAmount) * fee_rate);
3371
+ const totalDepositAmount = new Big(depositAmount).plus(protocolFee).plus(repayAmount).round(0, Big.roundDown).toNumber();
3366
3372
  return {
3367
3373
  depositAmount,
3368
- receiveAmount: Math.max(receiveAmount, 0),
3369
- fee
3374
+ totalDepositAmount,
3375
+ protocolFee,
3376
+ repayAmount
3370
3377
  };
3371
3378
  });
3372
3379
  }
@@ -3390,7 +3397,6 @@ function executeBTCDepositAndAction(_0) {
3390
3397
  action,
3391
3398
  amount,
3392
3399
  feeRate,
3393
- fixedAmount = true,
3394
3400
  pollResult = true,
3395
3401
  registerDeposit,
3396
3402
  env = "mainnet"
@@ -3407,24 +3413,23 @@ function executeBTCDepositAndAction(_0) {
3407
3413
  throw new Error("amount or action is required");
3408
3414
  }
3409
3415
  const csna = yield getCsnaAccountId(env);
3410
- const rawDepositAmount = (_a = action ? action.amount : amount) != null ? _a : "0";
3411
- if (new Big(rawDepositAmount).lt(0)) {
3416
+ const depositAmount = (_a = action ? action.amount : amount) != null ? _a : "0";
3417
+ if (new Big(depositAmount).lt(0)) {
3412
3418
  throw new Error("amount must be greater than 0");
3413
3419
  }
3414
- const { depositAmount, receiveAmount } = yield getDepositAmount(rawDepositAmount, {
3420
+ const { totalDepositAmount, protocolFee, repayAmount } = yield getDepositAmount(depositAmount, {
3415
3421
  env
3416
3422
  });
3417
3423
  const accountInfo = yield getAccountInfo(csna, config.accountContractId);
3418
3424
  const newActions = [];
3419
- const arrearsAction = yield checkGasTokenArrears(accountInfo, env, false);
3420
- if (arrearsAction) {
3421
- newActions.push(__spreadProps(__spreadValues({}, arrearsAction), {
3425
+ const debtAction = yield checkGasTokenDebt(accountInfo, env, false);
3426
+ if (debtAction) {
3427
+ newActions.push(__spreadProps(__spreadValues({}, debtAction), {
3422
3428
  gas: GAS_LIMIT
3423
3429
  }));
3424
3430
  }
3425
3431
  if (action) {
3426
3432
  newActions.push(__spreadProps(__spreadValues({}, action), {
3427
- amount: (arrearsAction == null ? void 0 : arrearsAction.amount) && !fixedAmount ? new Big(receiveAmount).minus(arrearsAction.amount).toString() : receiveAmount.toString(),
3428
3433
  gas: GAS_LIMIT
3429
3434
  }));
3430
3435
  }
@@ -3441,12 +3446,6 @@ function executeBTCDepositAndAction(_0) {
3441
3446
  }
3442
3447
  if (!(accountInfo == null ? void 0 : accountInfo.nonce)) {
3443
3448
  storageDepositMsg.btc_public_key = btcPublicKey;
3444
- newActions.push({
3445
- receiver_id: config.accountContractId,
3446
- amount: NBTC_STORAGE_DEPOSIT_AMOUNT.toString(),
3447
- msg: JSON.stringify("RelayerFee"),
3448
- gas: GAS_LIMIT
3449
- });
3450
3449
  }
3451
3450
  const depositMsg = {
3452
3451
  recipient_id: csna,
@@ -3460,10 +3459,14 @@ function executeBTCDepositAndAction(_0) {
3460
3459
  { deposit_msg: depositMsg }
3461
3460
  );
3462
3461
  const _feeRate = feeRate || (yield getBtcGasPrice());
3463
- const sendAmount = (arrearsAction == null ? void 0 : arrearsAction.amount) && fixedAmount ? new Big(depositAmount).plus((arrearsAction == null ? void 0 : arrearsAction.amount) || 0).toString() : depositAmount;
3464
- console.log("user deposit address:", userDepositAddress);
3465
- console.log("send amount:", sendAmount);
3466
- console.log("fee rate:", _feeRate);
3462
+ console.table({
3463
+ "User Deposit Address": userDepositAddress,
3464
+ "Deposit Amount": depositAmount,
3465
+ "Protocol Fee": protocolFee,
3466
+ "Repay Amount": repayAmount,
3467
+ "Total Deposit Amount": totalDepositAmount,
3468
+ "Fee Rate": _feeRate
3469
+ });
3467
3470
  const postActionsStr = newActions.length > 0 ? JSON.stringify(newActions) : void 0;
3468
3471
  yield preReceiveDepositMsg(config.base_url, {
3469
3472
  btcPublicKey,
@@ -3471,7 +3474,7 @@ function executeBTCDepositAndAction(_0) {
3471
3474
  postActions: postActionsStr,
3472
3475
  extraMsg: depositMsg.extra_msg
3473
3476
  });
3474
- const txHash = yield sendBitcoin(userDepositAddress, Number(sendAmount), _feeRate);
3477
+ const txHash = yield sendBitcoin(userDepositAddress, totalDepositAmount, _feeRate);
3475
3478
  yield receiveDepositMsg(config.base_url, {
3476
3479
  btcPublicKey,
3477
3480
  txHash,
@@ -3516,6 +3519,148 @@ Sign up now: <a style="color: #ff7a00; text-decoration: underline;" href="https:
3516
3519
  }
3517
3520
  });
3518
3521
  }
3522
+ function getWithdrawTransaction(_0) {
3523
+ return __async(this, arguments, function* ({
3524
+ amount,
3525
+ feeRate,
3526
+ env = "mainnet"
3527
+ }) {
3528
+ const provider = getBtcProvider();
3529
+ const btcAddress = yield provider.account;
3530
+ const config = yield getConfig(env);
3531
+ const brgConfig = yield nearCall(config.bridgeContractId, "get_config", {});
3532
+ if (brgConfig.min_withdraw_amount) {
3533
+ if (Number(amount) < Number(brgConfig.min_withdraw_amount)) {
3534
+ throw new Error("Mini withdraw amount is " + brgConfig.min_withdraw_amount);
3535
+ }
3536
+ }
3537
+ const feePercent = Number(brgConfig.withdraw_bridge_fee.fee_rate) * Number(amount);
3538
+ const withdrawFee = feePercent > Number(brgConfig.withdraw_bridge_fee.fee_min) ? feePercent : Number(brgConfig.withdraw_bridge_fee.fee_min);
3539
+ const allUTXO = yield nearCall(config.bridgeContractId, "get_utxos_paged", {});
3540
+ if (!allUTXO || Object.keys(allUTXO).length === 0) {
3541
+ throw new Error("The network is busy, please try again later.");
3542
+ }
3543
+ const utxos = Object.keys(allUTXO).map((key) => {
3544
+ const txid = key.split("@");
3545
+ return {
3546
+ txid: txid[0],
3547
+ vout: allUTXO[key].vout,
3548
+ value: Number(allUTXO[key].balance),
3549
+ script: allUTXO[key].script
3550
+ };
3551
+ });
3552
+ const _feeRate = feeRate || (yield getBtcGasPrice());
3553
+ const { inputs, outputs, fee } = coinselect(
3554
+ utxos,
3555
+ [{ address: btcAddress, value: Number(amount) }],
3556
+ Math.ceil(_feeRate)
3557
+ );
3558
+ if (!outputs || !inputs) {
3559
+ throw new Error("The network is busy, please try again later.");
3560
+ }
3561
+ const maxBtcFee = Number(brgConfig.max_btc_gas_fee);
3562
+ const newFee = fee;
3563
+ const withdrawChangeAddress = brgConfig.change_address;
3564
+ if (newFee > maxBtcFee) {
3565
+ throw new Error("Gas exceeds maximum value");
3566
+ }
3567
+ let userOutput, noUserOutput;
3568
+ for (let i = 0; i < outputs.length; i++) {
3569
+ const output = outputs[i];
3570
+ if (output.value.toString() === amount.toString()) {
3571
+ userOutput = output;
3572
+ } else {
3573
+ noUserOutput = output;
3574
+ }
3575
+ if (!output.address) {
3576
+ output.address = withdrawChangeAddress;
3577
+ }
3578
+ }
3579
+ userOutput.value = new Big(userOutput.value).minus(newFee).minus(withdrawFee).toNumber();
3580
+ if (noUserOutput) {
3581
+ noUserOutput.value = new Big(noUserOutput.value).plus(newFee).plus(withdrawFee).toNumber();
3582
+ } else {
3583
+ noUserOutput = {
3584
+ address: withdrawChangeAddress,
3585
+ value: new Big(newFee).plus(withdrawFee).toNumber()
3586
+ };
3587
+ outputs.push(noUserOutput);
3588
+ }
3589
+ const insufficientOutput = outputs.some((item) => item.value < 0);
3590
+ if (insufficientOutput) {
3591
+ throw new Error("Not enough gas");
3592
+ }
3593
+ const inputSum = inputs.reduce((sum, cur) => sum + Number(cur.value), 0);
3594
+ const outputSum = outputs.reduce((sum, cur) => sum + Number(cur.value), 0);
3595
+ if (newFee + outputSum !== inputSum) {
3596
+ throw new Error("compute error");
3597
+ }
3598
+ const network = yield getNetwork();
3599
+ const btcNetwork = network === "mainnet" ? bitcoin.networks.bitcoin : bitcoin.networks.testnet;
3600
+ const psbt = new bitcoin.Psbt({ network: btcNetwork });
3601
+ const btcRpcUrl = yield getBtcRpcUrl();
3602
+ for (let i = 0; i < inputs.length; i++) {
3603
+ const input = inputs[i];
3604
+ const txData = yield fetch(`${btcRpcUrl}/tx/${input.txid}`).then((res) => res.json());
3605
+ const inputOptions = {
3606
+ hash: input.txid,
3607
+ index: input.vout,
3608
+ sequence: 4294967293,
3609
+ witnessUtxo: {
3610
+ script: Buffer.from(txData.vout[input.vout].scriptpubkey, "hex"),
3611
+ value: input.value
3612
+ }
3613
+ };
3614
+ psbt.addInput(inputOptions);
3615
+ }
3616
+ outputs.forEach((output) => {
3617
+ psbt.addOutput({
3618
+ address: output.address,
3619
+ value: output.value
3620
+ });
3621
+ });
3622
+ const _inputs = inputs.map((item) => {
3623
+ return `${item.txid}:${item.vout}`;
3624
+ });
3625
+ const txOutputs = psbt.txOutputs.map((item) => {
3626
+ return {
3627
+ script_pubkey: uint8ArrayToHex(item.script),
3628
+ value: item.value
3629
+ };
3630
+ });
3631
+ const msg = {
3632
+ Withdraw: {
3633
+ target_btc_address: btcAddress,
3634
+ input: _inputs,
3635
+ output: txOutputs
3636
+ }
3637
+ };
3638
+ const csna = yield getCsnaAccountId(env);
3639
+ const transaction = {
3640
+ receiverId: config.token,
3641
+ signerId: csna,
3642
+ actions: [
3643
+ {
3644
+ type: "FunctionCall",
3645
+ params: {
3646
+ methodName: "ft_transfer_call",
3647
+ args: {
3648
+ receiver_id: config.bridgeContractId,
3649
+ amount: amount.toString(),
3650
+ msg: JSON.stringify(msg)
3651
+ },
3652
+ gas: "300000000000000",
3653
+ deposit: "1"
3654
+ }
3655
+ }
3656
+ ]
3657
+ };
3658
+ return transaction;
3659
+ });
3660
+ }
3661
+ function uint8ArrayToHex(uint8Array) {
3662
+ return Array.from(uint8Array).map((byte) => byte.toString(16).padStart(2, "0")).join("");
3663
+ }
3519
3664
 
3520
3665
  // src/core/setupBTCWallet.ts
3521
3666
  var { transfer, functionCall } = actionCreators;
@@ -3741,7 +3886,7 @@ var BTCWallet = (_0) => __async(void 0, [_0], function* ({
3741
3886
  const btcContext = window.btcContext;
3742
3887
  const accountId = state.getAccount();
3743
3888
  const accountInfo = yield getAccountInfo(accountId, currentConfig.accountContractId);
3744
- yield checkGasTokenArrears(accountInfo, env, true);
3889
+ yield checkGasTokenDebt(accountInfo, env, true);
3745
3890
  const trans = [...params.transactions];
3746
3891
  console.log("raw trans:", trans);
3747
3892
  const gasTokenBalance = (accountInfo == null ? void 0 : accountInfo.gas_token[currentConfig.token]) || "0";
@@ -3950,7 +4095,7 @@ function setupBTCWallet({
3950
4095
  if (!hasShownNotice) {
3951
4096
  Dialog.alert({
3952
4097
  title: "Notice",
3953
- message: "You are currently using Satoshi Private Mainnet. This is a private version for testing. Please try a small amount of assets in Bridge"
4098
+ message: "You are currently using Satoshi Private Mainnet. This is a private version for testing. Please try a small amount of assets in Ramp"
3954
4099
  });
3955
4100
  localStorage.setItem("satoshi_private_mainnet_notice", "true");
3956
4101
  }
@@ -3979,7 +4124,7 @@ function setupBTCWallet({
3979
4124
 
3980
4125
  // src/index.ts
3981
4126
  var getVersion = () => {
3982
- return "0.4.4-beta";
4127
+ return "0.4.6-beta";
3983
4128
  };
3984
4129
  if (typeof window !== "undefined") {
3985
4130
  window.__BTC_WALLET_VERSION = getVersion();
@@ -3997,8 +4142,8 @@ export {
3997
4142
  UnisatConnector,
3998
4143
  WizzConnector,
3999
4144
  XverseConnector,
4000
- checkGasTokenArrears,
4001
4145
  checkGasTokenBalance,
4146
+ checkGasTokenDebt,
4002
4147
  checkSatoshiWhitelist,
4003
4148
  estimateDepositAmount,
4004
4149
  executeBTCDepositAndAction,
@@ -4007,8 +4152,9 @@ export {
4007
4152
  getBtcGasPrice,
4008
4153
  getCsnaAccountId,
4009
4154
  getDepositAmount,
4155
+ getNBTCBalance,
4010
4156
  getVersion,
4011
- queryGasTokenArrears,
4157
+ getWithdrawTransaction,
4012
4158
  sendBitcoin,
4013
4159
  setupBTCWallet,
4014
4160
  useAccountContract,