btc-wallet 0.3.6 → 0.3.8

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.
package/dist/config.d.ts CHANGED
@@ -4,6 +4,7 @@ export declare const walletConfig: Record<string, {
4
4
  accountContractId: string;
5
5
  bridgeContractId: string;
6
6
  walletUrl: string;
7
+ gasTokenLimit: string;
7
8
  }>;
8
9
  export declare const nearRpcUrls: {
9
10
  mainnet: string[];
@@ -1,9 +1,19 @@
1
1
  export declare function getBtcGasPrice(): Promise<number>;
2
2
  export declare function getBtcBalance(): Promise<{
3
+ rawBalance: number;
4
+ balance: number;
5
+ maxSpendableBalance: number;
6
+ availableBalance?: undefined;
7
+ } | {
3
8
  rawBalance: any;
4
9
  balance: number;
10
+ availableBalance: number;
11
+ maxSpendableBalance?: undefined;
5
12
  }>;
6
13
  export declare function sendBitcoin(address: string, amount: number, feeRate: number): Promise<string>;
14
+ export declare function estimateDepositAmount(amount: string, option?: {
15
+ isDev: boolean;
16
+ }): Promise<string>;
7
17
  interface ExecuteBTCDepositAndActionParams {
8
18
  action: {
9
19
  receiver_id: string;
package/dist/index.js CHANGED
@@ -90,6 +90,7 @@ __export(src_exports, {
90
90
  UnisatConnector: () => UnisatConnector,
91
91
  WizzConnector: () => WizzConnector,
92
92
  XverseConnector: () => XverseConnector,
93
+ estimateDepositAmount: () => estimateDepositAmount,
93
94
  executeBTCDepositAndAction: () => executeBTCDepositAndAction,
94
95
  getBtcBalance: () => getBtcBalance,
95
96
  getBtcGasPrice: () => getBtcGasPrice,
@@ -2725,21 +2726,24 @@ var walletConfig = {
2725
2726
  token: "nbtc-dev.testnet",
2726
2727
  accountContractId: "acc-dev.testnet",
2727
2728
  bridgeContractId: "brg-dev.testnet",
2728
- walletUrl: "https://wallet-dev.satoshibridge.top"
2729
+ walletUrl: "https://wallet-dev.satoshibridge.top",
2730
+ gasTokenLimit: "3000"
2729
2731
  },
2730
2732
  testnet: {
2731
2733
  base_url: "https://api.testnet.satoshibridge.top",
2732
2734
  token: "nbtc2-nsp.testnet",
2733
2735
  accountContractId: "dev2-nsp.testnet",
2734
2736
  bridgeContractId: "brg2-nsp.testnet",
2735
- walletUrl: "https://wallet-test.satoshibridge.top"
2737
+ walletUrl: "https://wallet-test.satoshibridge.top",
2738
+ gasTokenLimit: "3000"
2736
2739
  },
2737
2740
  mainnet: {
2738
2741
  base_url: "https://api.mainnet.satoshibridge.top",
2739
2742
  token: "",
2740
2743
  accountContractId: "",
2741
2744
  bridgeContractId: "",
2742
- walletUrl: "https://wallet.satoshibridge.top"
2745
+ walletUrl: "https://wallet.satoshibridge.top",
2746
+ gasTokenLimit: "3000"
2743
2747
  }
2744
2748
  };
2745
2749
  var nearRpcUrls = {
@@ -2883,6 +2887,7 @@ function pollTransactionStatuses(network, hashes) {
2883
2887
  }
2884
2888
 
2885
2889
  // src/core/setupBTCWallet.ts
2890
+ var import_big = __toESM(require("big.js"), 1);
2886
2891
  var { transfer, functionCall } = import_transactions.actionCreators;
2887
2892
  var state = {
2888
2893
  saveAccount(account) {
@@ -3099,6 +3104,10 @@ var BTCWallet = (_0) => __async(void 0, [_0], function* ({
3099
3104
  currentConfig.base_url,
3100
3105
  accountId
3101
3106
  );
3107
+ const { transferGasTransaction, useNearPayGas } = yield getGasConfig();
3108
+ if (!useNearPayGas && transferGasTransaction) {
3109
+ params.transactions.unshift(transferGasTransaction);
3110
+ }
3102
3111
  const newTransactions = params.transactions.map((transaction, index) => {
3103
3112
  let nearNonceNumber = accessKey.nonce + BigInt(1);
3104
3113
  if (nearNonceFromApi) {
@@ -3149,19 +3158,10 @@ var BTCWallet = (_0) => __async(void 0, [_0], function* ({
3149
3158
  csna: accountId,
3150
3159
  near_transactions: newTransactions.map((t) => t.txHex),
3151
3160
  gas_token: currentConfig.token,
3152
- gas_limit: "3000",
3153
- use_near_pay_gas: false,
3161
+ gas_limit: currentConfig.gasTokenLimit,
3162
+ use_near_pay_gas: useNearPayGas,
3154
3163
  nonce
3155
3164
  };
3156
- const nearAccount = yield provider.query({
3157
- request_type: "view_account",
3158
- account_id: accountId,
3159
- finality: "final"
3160
- });
3161
- const availableBalance = parseFloat(nearAccount.amount) / __pow(10, 24);
3162
- if (availableBalance > 0.2) {
3163
- intention.use_near_pay_gas = true;
3164
- }
3165
3165
  const strIntention = JSON.stringify(intention);
3166
3166
  const signature = yield btcContext.signMessage(strIntention);
3167
3167
  const result = yield uploadBTCTx(currentConfig.base_url, {
@@ -3179,6 +3179,48 @@ var BTCWallet = (_0) => __async(void 0, [_0], function* ({
3179
3179
  }
3180
3180
  });
3181
3181
  }
3182
+ function getGasConfig() {
3183
+ return __async(this, null, function* () {
3184
+ const accountId = state.getAccount();
3185
+ const nearAccount = yield provider.query({
3186
+ request_type: "view_account",
3187
+ account_id: accountId,
3188
+ finality: "final"
3189
+ });
3190
+ const availableBalance = parseFloat(nearAccount.amount) / __pow(10, 24);
3191
+ if (availableBalance > 0.2) {
3192
+ return { useNearPayGas: true };
3193
+ } else {
3194
+ const gasTokenBalance = yield nearCall2(currentConfig.token, "ft_balance_of", {
3195
+ account_id: accountId
3196
+ });
3197
+ if (new import_big.default(gasTokenBalance).gt(currentConfig.gasTokenLimit)) {
3198
+ const transferGasTransaction = {
3199
+ signerId: accountId,
3200
+ receiverId: currentConfig.token,
3201
+ actions: [
3202
+ {
3203
+ type: "FunctionCall",
3204
+ params: {
3205
+ methodName: "ft_transfer_call",
3206
+ args: {
3207
+ receiver_id: currentConfig.accountContractId,
3208
+ amount: currentConfig.gasTokenLimit,
3209
+ msg: "Deposit"
3210
+ },
3211
+ gas: new import_big.default(50).mul(__pow(10, 12)).toFixed(0),
3212
+ deposit: "1"
3213
+ }
3214
+ }
3215
+ ]
3216
+ };
3217
+ return { transferGasTransaction, useNearPayGas: false };
3218
+ } else {
3219
+ throw new Error("No enough gas token balance");
3220
+ }
3221
+ }
3222
+ });
3223
+ }
3182
3224
  function initWalletButton(network, wallet2) {
3183
3225
  return __async(this, null, function* () {
3184
3226
  const checkAndSetupWalletButton = () => {
@@ -3248,7 +3290,7 @@ function toHex(originalString) {
3248
3290
  }
3249
3291
 
3250
3292
  // src/core/btcUtils.ts
3251
- var import_big = __toESM(require("big.js"), 1);
3293
+ var import_big2 = __toESM(require("big.js"), 1);
3252
3294
  function getBtcProvider() {
3253
3295
  if (typeof window === "undefined" || !window.btcContext) {
3254
3296
  throw new Error("BTC Provider is not initialized.");
@@ -3268,6 +3310,12 @@ function getBtcRpcUrl() {
3268
3310
  return btcRpcUrls[network];
3269
3311
  });
3270
3312
  }
3313
+ function getConfig(isDev) {
3314
+ return __async(this, null, function* () {
3315
+ const network = yield getNetwork();
3316
+ return walletConfig[isDev ? "dev" : network];
3317
+ });
3318
+ }
3271
3319
  function nearCall(contractId, methodName, args) {
3272
3320
  return __async(this, null, function* () {
3273
3321
  const network = yield getNetwork();
@@ -3322,13 +3370,20 @@ function getBtcBalance() {
3322
3370
  const { account } = yield retryOperation(getBtcProvider, (res2) => !!res2.account);
3323
3371
  if (!account) {
3324
3372
  console.error("BTC Account is not available.");
3325
- return { rawBalance: 0, balance: 0 };
3373
+ return { rawBalance: 0, balance: 0, maxSpendableBalance: 0 };
3326
3374
  }
3327
3375
  const btcRpcUrl = yield getBtcRpcUrl();
3328
3376
  const res = yield fetch(`${btcRpcUrl}/address/${account}/utxo`).then((res2) => res2.json());
3329
3377
  const rawBalance = res == null ? void 0 : res.reduce((acc, cur) => acc + cur.value, 0);
3330
3378
  const balance = rawBalance / __pow(10, 8);
3331
- return { rawBalance, balance };
3379
+ const feeRate = yield getBtcGasPrice();
3380
+ const maxGasFee = feeRate * 250 / __pow(10, 8);
3381
+ const availableBalance = Math.max(0, balance - maxGasFee);
3382
+ return {
3383
+ rawBalance,
3384
+ balance,
3385
+ availableBalance
3386
+ };
3332
3387
  });
3333
3388
  }
3334
3389
  function sendBitcoin(address, amount, feeRate) {
@@ -3338,6 +3393,20 @@ function sendBitcoin(address, amount, feeRate) {
3338
3393
  return txHash;
3339
3394
  });
3340
3395
  }
3396
+ function estimateDepositAmount(amount, option) {
3397
+ return __async(this, null, function* () {
3398
+ const config = yield getConfig((option == null ? void 0 : option.isDev) || false);
3399
+ const {
3400
+ deposit_bridge_fee: { fee_min, fee_rate }
3401
+ } = yield nearCall(
3402
+ config.bridgeContractId,
3403
+ "get_config",
3404
+ {}
3405
+ );
3406
+ const fee = Math.max(Number(fee_min), Number(amount) * fee_rate);
3407
+ return new import_big2.default(amount).minus(fee).toFixed(0);
3408
+ });
3409
+ }
3341
3410
  function executeBTCDepositAndAction(_0) {
3342
3411
  return __async(this, arguments, function* ({
3343
3412
  action,
@@ -3346,18 +3415,26 @@ function executeBTCDepositAndAction(_0) {
3346
3415
  }) {
3347
3416
  try {
3348
3417
  const { getPublicKey } = getBtcProvider();
3349
- const network = yield getNetwork();
3350
- const config = walletConfig[isDev ? "dev" : network];
3418
+ const config = yield getConfig(isDev);
3351
3419
  const btcPublicKey = yield getPublicKey();
3352
- const _action = Object.assign({}, action);
3420
+ const _action = Object.assign(
3421
+ {},
3422
+ __spreadProps(__spreadValues({}, action), {
3423
+ gas: new import_big2.default(100).mul(__pow(10, 12)).toFixed(0)
3424
+ })
3425
+ );
3353
3426
  if (!btcPublicKey) {
3354
3427
  throw new Error("BTC Public Key is not available.");
3355
3428
  }
3356
3429
  if (!_action.receiver_id) {
3357
3430
  throw new Error("action.receiver_id is required");
3358
3431
  }
3359
- if (!_action.amount || !new import_big.default(_action.amount || 0).gt(0)) {
3360
- throw new Error("action.amount is required and must be greater than 0");
3432
+ const amountWithFee = yield estimateDepositAmount(_action.amount, {
3433
+ isDev
3434
+ });
3435
+ _action.amount = amountWithFee;
3436
+ if (!_action.amount || !new import_big2.default(_action.amount || 0).gt(0)) {
3437
+ throw new Error("action.amount is required or deposit amount is not enough");
3361
3438
  }
3362
3439
  const csna = yield nearCall(
3363
3440
  config.accountContractId,
@@ -3366,37 +3443,48 @@ function executeBTCDepositAndAction(_0) {
3366
3443
  btc_public_key: btcPublicKey
3367
3444
  }
3368
3445
  );
3369
- _action.amount = new import_big.default(_action.amount).toString();
3370
- _action.gas = new import_big.default(100).mul(__pow(10, 12)).toFixed(0);
3371
3446
  const depositMsg = {
3372
3447
  recipient_id: csna,
3373
3448
  post_actions: [_action]
3374
3449
  };
3450
+ const storageDepositMsg = {};
3451
+ const accountInfo = yield nearCall(
3452
+ config.accountContractId,
3453
+ "get_account",
3454
+ {
3455
+ account_id: csna
3456
+ }
3457
+ );
3458
+ if (!(accountInfo == null ? void 0 : accountInfo.nonce)) {
3459
+ storageDepositMsg.btc_public_key = btcPublicKey;
3460
+ }
3375
3461
  const registerRes = yield nearCall(action.receiver_id, "storage_balance_of", {
3376
3462
  account_id: csna
3377
3463
  });
3378
3464
  if (!(registerRes == null ? void 0 : registerRes.available)) {
3379
- const storageDepositMsg = {
3380
- storage_deposit_msg: {
3381
- contract_id: action.receiver_id,
3382
- deposit: new import_big.default(0.25).mul(__pow(10, 24)).toFixed(0),
3383
- registration_only: true
3384
- },
3385
- btc_public_key: btcPublicKey
3465
+ storageDepositMsg.storage_deposit_msg = {
3466
+ contract_id: action.receiver_id,
3467
+ deposit: new import_big2.default(0.25).mul(__pow(10, 24)).toFixed(0),
3468
+ registration_only: true
3386
3469
  };
3470
+ }
3471
+ if (Object.keys(storageDepositMsg).length > 0) {
3387
3472
  depositMsg.extra_msg = JSON.stringify(storageDepositMsg);
3388
3473
  }
3389
- console.log("depositMsg", depositMsg);
3474
+ console.log("get_user_deposit_address params:", { deposit_msg: depositMsg });
3390
3475
  const userDepositAddress = yield nearCall(
3391
3476
  config.bridgeContractId,
3392
3477
  "get_user_deposit_address",
3393
3478
  { deposit_msg: depositMsg }
3394
3479
  );
3395
- console.log("userDepositAddress", userDepositAddress);
3396
3480
  const _feeRate = feeRate || (yield getBtcGasPrice());
3481
+ console.log("user deposit address:", userDepositAddress);
3482
+ console.log("deposit amount:", new import_big2.default(action.amount).toNumber());
3483
+ console.log("receive amount:", new import_big2.default(_action.amount).toNumber());
3484
+ console.log("fee rate:", _feeRate);
3397
3485
  const txHash = yield sendBitcoin(
3398
3486
  userDepositAddress,
3399
- new import_big.default(action.amount).toNumber(),
3487
+ new import_big2.default(action.amount).toNumber(),
3400
3488
  _feeRate
3401
3489
  );
3402
3490
  yield receiveDepositMsg(config.base_url, {
@@ -3417,7 +3505,7 @@ function executeBTCDepositAndAction(_0) {
3417
3505
 
3418
3506
  // src/index.ts
3419
3507
  var getVersion = () => {
3420
- return "0.3.6";
3508
+ return "0.3.8";
3421
3509
  };
3422
3510
  if (typeof window !== "undefined") {
3423
3511
  window.__PARTICLE_BTC_CONNECT_VERSION = getVersion();