btc-wallet 0.3.10 → 0.3.12

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/esm/index.js CHANGED
@@ -2714,9 +2714,7 @@ var nearRpcUrls = {
2714
2714
  "https://near.drpc.org"
2715
2715
  ],
2716
2716
  testnet: [
2717
- "https://rpc.testnet.near.org",
2718
- "https://near-testnet.lava.build",
2719
- "https://near-testnet.drpc.org"
2717
+ "https://rpc.testnet.near.org"
2720
2718
  ]
2721
2719
  };
2722
2720
  var btcRpcUrls = {
@@ -2724,6 +2722,73 @@ var btcRpcUrls = {
2724
2722
  testnet: "https://mempool.space/testnet/api"
2725
2723
  };
2726
2724
 
2725
+ // src/utils/nearUtils.ts
2726
+ import { providers } from "near-api-js";
2727
+ function nearCallFunction(contractId, methodName, args, options) {
2728
+ return __async(this, null, function* () {
2729
+ const nearProvider = (options == null ? void 0 : options.provider) || new providers.FailoverRpcProvider(
2730
+ nearRpcUrls[options == null ? void 0 : options.network].map(
2731
+ (url) => new providers.JsonRpcProvider({ url })
2732
+ )
2733
+ );
2734
+ const res = yield nearProvider.query({
2735
+ request_type: "call_function",
2736
+ account_id: contractId,
2737
+ method_name: methodName,
2738
+ args_base64: Buffer.from(JSON.stringify(args)).toString("base64"),
2739
+ finality: "final"
2740
+ });
2741
+ return JSON.parse(Buffer.from(res.result).toString());
2742
+ });
2743
+ }
2744
+ function pollTransactionStatuses(network, hashes) {
2745
+ return __async(this, null, function* () {
2746
+ const provider = new providers.FailoverRpcProvider(
2747
+ Object.values(nearRpcUrls[network]).map(
2748
+ (url) => new providers.JsonRpcProvider({ url })
2749
+ )
2750
+ );
2751
+ const maxAttempts = 30;
2752
+ let currentAttempt = 0;
2753
+ const pendingHashes = new Set(hashes);
2754
+ const results = /* @__PURE__ */ new Map();
2755
+ while (pendingHashes.size > 0 && currentAttempt < maxAttempts) {
2756
+ currentAttempt++;
2757
+ const promises = Array.from(pendingHashes).map((hash) => __async(this, null, function* () {
2758
+ try {
2759
+ const result = yield provider.txStatus(hash, "unused", "FINAL");
2760
+ if (result && result.status) {
2761
+ console.log(`Transaction ${hash} result:`, result);
2762
+ results.set(hash, result);
2763
+ pendingHashes.delete(hash);
2764
+ }
2765
+ } catch (error) {
2766
+ console.error(`Failed to fetch transaction status for ${hash}: ${error.message}`);
2767
+ }
2768
+ }));
2769
+ yield Promise.all(promises);
2770
+ if (pendingHashes.size > 0) {
2771
+ if (currentAttempt === maxAttempts) {
2772
+ throw new Error(
2773
+ `Transactions not found after max attempts: ${Array.from(pendingHashes).join(", ")}`
2774
+ );
2775
+ }
2776
+ console.log(
2777
+ `Waiting for ${pendingHashes.size} transactions, retrying ${maxAttempts - currentAttempt} more times`
2778
+ );
2779
+ yield delay(1e4);
2780
+ }
2781
+ }
2782
+ return hashes.map((hash) => results.get(hash));
2783
+ });
2784
+ }
2785
+
2786
+ // src/core/setupBTCWallet.ts
2787
+ import Big2 from "big.js";
2788
+
2789
+ // src/core/btcUtils.ts
2790
+ import Big from "big.js";
2791
+
2727
2792
  // src/utils/request.ts
2728
2793
  var cache = /* @__PURE__ */ new Map();
2729
2794
  var defaultCacheTimeout = 3e3;
@@ -2764,18 +2829,20 @@ function request(url, options) {
2764
2829
  if (!res.ok)
2765
2830
  throw new Error(res.statusText);
2766
2831
  const data = yield res.json();
2832
+ if (options == null ? void 0 : options.shouldStopPolling) {
2833
+ if (options.shouldStopPolling(data)) {
2834
+ return data;
2835
+ }
2836
+ throw new Error("Polling should continue");
2837
+ }
2767
2838
  if (cacheKey) {
2768
2839
  cache.set(cacheKey, { timestamp: Date.now(), data });
2769
2840
  setTimeout(() => {
2770
2841
  cache.delete(cacheKey);
2771
2842
  }, cacheTimeout);
2772
2843
  }
2773
- if ((options == null ? void 0 : options.shouldStopPolling) && options.shouldStopPolling(data)) {
2774
- return data;
2775
- }
2776
2844
  return data;
2777
2845
  } catch (err) {
2778
- console.error(err);
2779
2846
  if (retryCount > 0) {
2780
2847
  console.log(`Retrying... attempts left: ${retryCount}`);
2781
2848
  return request(url, __spreadProps(__spreadValues({}, options), { retryCount: retryCount - 1 }));
@@ -2789,65 +2856,471 @@ function request(url, options) {
2789
2856
  }));
2790
2857
  }
2791
2858
  }
2792
- return Promise.reject(err);
2859
+ throw err;
2793
2860
  }
2794
2861
  });
2795
2862
  }
2796
2863
 
2797
- // src/utils/nearUtils.ts
2798
- import { providers } from "near-api-js";
2799
- function nearCallFunction(contractId, methodName, args, options) {
2864
+ // src/utils/satoshi.ts
2865
+ function getNonce(url, accountId) {
2800
2866
  return __async(this, null, function* () {
2801
- const nearProvider = (options == null ? void 0 : options.provider) || new providers.FailoverRpcProvider(
2802
- nearRpcUrls[options == null ? void 0 : options.network].map(
2803
- (url) => new providers.JsonRpcProvider({ url })
2804
- )
2867
+ const { result_code, result_message, result_data } = yield request(
2868
+ `${url}/v1/nonce?csna=${accountId}`
2805
2869
  );
2806
- const res = yield nearProvider.query({
2807
- request_type: "call_function",
2808
- account_id: contractId,
2809
- method_name: methodName,
2810
- args_base64: Buffer.from(JSON.stringify(args)).toString("base64"),
2811
- finality: "final"
2870
+ if (result_code !== 0) {
2871
+ throw new Error(result_message);
2872
+ }
2873
+ return result_data;
2874
+ });
2875
+ }
2876
+ function getNearNonce(url, accountId) {
2877
+ return __async(this, null, function* () {
2878
+ const { result_code, result_message, result_data } = yield request(
2879
+ `${url}/v1/nonceNear?csna=${accountId}`
2880
+ );
2881
+ if (result_code !== 0) {
2882
+ throw new Error(result_message);
2883
+ }
2884
+ return result_data;
2885
+ });
2886
+ }
2887
+ function receiveTransaction(url, data) {
2888
+ return __async(this, null, function* () {
2889
+ const { result_code, result_message, result_data } = yield request(
2890
+ `${url}/v1/receiveTransaction`,
2891
+ {
2892
+ method: "POST",
2893
+ body: data
2894
+ }
2895
+ );
2896
+ if (result_code !== 0) {
2897
+ throw new Error(result_message);
2898
+ }
2899
+ return result_data;
2900
+ });
2901
+ }
2902
+ function receiveDepositMsg(_0, _1) {
2903
+ return __async(this, arguments, function* (url, {
2904
+ btcPublicKey,
2905
+ txHash,
2906
+ depositType = 1,
2907
+ postActions,
2908
+ extraMsg
2909
+ }) {
2910
+ const { result_code, result_message, result_data } = yield request(
2911
+ `${url}/v1/receiveDepositMsg`,
2912
+ {
2913
+ method: "POST",
2914
+ body: { btcPublicKey, txHash, depositType, postActions, extraMsg }
2915
+ }
2916
+ );
2917
+ console.log("receiveDepositMsg resp:", { result_code, result_message, result_data });
2918
+ if (result_code !== 0) {
2919
+ throw new Error(result_message);
2920
+ }
2921
+ return result_data;
2922
+ });
2923
+ }
2924
+ function checkBridgeTransactionStatus(url, txHash) {
2925
+ return __async(this, null, function* () {
2926
+ const { result_code, result_message, result_data } = yield request(`${url}/v1/bridgeFromTx?fromTxHash=${txHash}&fromChainId=1`, {
2927
+ timeout: 3e5,
2928
+ pollingInterval: 5e3,
2929
+ maxPollingAttempts: 30,
2930
+ shouldStopPolling: (res) => {
2931
+ var _a;
2932
+ return res.result_code === 0 && [4, 102].includes(((_a = res.result_data) == null ? void 0 : _a.status) || 0);
2933
+ }
2812
2934
  });
2813
- return JSON.parse(Buffer.from(res.result).toString());
2935
+ console.log("checkTransactionStatus resp:", { result_code, result_message, result_data });
2936
+ if ((result_data == null ? void 0 : result_data.status) !== 4) {
2937
+ throw new Error(result_message);
2938
+ }
2939
+ return result_data;
2814
2940
  });
2815
2941
  }
2816
- function pollTransactionStatuses(network, hashes) {
2942
+ function checkBtcTransactionStatus(url, sig) {
2817
2943
  return __async(this, null, function* () {
2818
- const provider = new providers.FailoverRpcProvider(
2819
- Object.values(nearRpcUrls[network]).map(
2820
- (url) => new providers.JsonRpcProvider({ url })
2821
- )
2944
+ const { result_code, result_message, result_data } = yield request(`${url}/v1/btcTx?sig=${sig}`, {
2945
+ timeout: 3e5,
2946
+ pollingInterval: 5e3,
2947
+ maxPollingAttempts: 30,
2948
+ shouldStopPolling: (res) => {
2949
+ var _a;
2950
+ return res.result_code === 0 && [3, 101, 102].includes(((_a = res.result_data) == null ? void 0 : _a.status) || 0);
2951
+ }
2952
+ });
2953
+ console.log("checkBtcTransactionStatus resp:", { result_code, result_message, result_data });
2954
+ if ((result_data == null ? void 0 : result_data.status) !== 3) {
2955
+ throw new Error(result_message);
2956
+ }
2957
+ return result_data;
2958
+ });
2959
+ }
2960
+
2961
+ // src/core/btcUtils.ts
2962
+ function getBtcProvider() {
2963
+ if (typeof window === "undefined" || !window.btcContext) {
2964
+ throw new Error("BTC Provider is not initialized.");
2965
+ }
2966
+ return window.btcContext;
2967
+ }
2968
+ function getNetwork() {
2969
+ return __async(this, null, function* () {
2970
+ const network = yield getBtcProvider().getNetwork();
2971
+ console.log("btc network:", network);
2972
+ return network === "livenet" ? "mainnet" : "testnet";
2973
+ });
2974
+ }
2975
+ function getBtcRpcUrl() {
2976
+ return __async(this, null, function* () {
2977
+ const network = yield getNetwork();
2978
+ return btcRpcUrls[network];
2979
+ });
2980
+ }
2981
+ function getConfig(isDev) {
2982
+ return __async(this, null, function* () {
2983
+ const network = yield getNetwork();
2984
+ return walletConfig[isDev ? "dev" : network];
2985
+ });
2986
+ }
2987
+ function nearCall(contractId, methodName, args) {
2988
+ return __async(this, null, function* () {
2989
+ const network = yield getNetwork();
2990
+ return nearCallFunction(contractId, methodName, args, { network });
2991
+ });
2992
+ }
2993
+ function getBtcGasPrice() {
2994
+ return __async(this, null, function* () {
2995
+ const defaultFeeRate = 100;
2996
+ try {
2997
+ const btcRpcUrl = yield getBtcRpcUrl();
2998
+ const res = yield fetch(`${btcRpcUrl}/v1/fees/recommended`).then((res2) => res2.json());
2999
+ const feeRate = res.fastestFee;
3000
+ return feeRate || defaultFeeRate;
3001
+ } catch (error) {
3002
+ return defaultFeeRate;
3003
+ }
3004
+ });
3005
+ }
3006
+ function getBtcBalance() {
3007
+ return __async(this, null, function* () {
3008
+ const { account } = yield retryOperation(getBtcProvider, (res) => !!res.account);
3009
+ if (!account) {
3010
+ console.error("BTC Account is not available.");
3011
+ return { rawBalance: 0, balance: 0, maxSpendableBalance: 0 };
3012
+ }
3013
+ const btcRpcUrl = yield getBtcRpcUrl();
3014
+ const utxos = yield fetch(`${btcRpcUrl}/address/${account}/utxo`).then((res) => res.json());
3015
+ const rawBalance = (utxos == null ? void 0 : utxos.reduce((acc, cur) => acc + cur.value, 0)) || 0;
3016
+ const balance = rawBalance / __pow(10, 8);
3017
+ const feeRate = yield getBtcGasPrice();
3018
+ const inputSize = ((utxos == null ? void 0 : utxos.length) || 0) * 66;
3019
+ const outputSize = 34;
3020
+ const overheadSize = 10;
3021
+ const estimatedTxSize = inputSize + outputSize + overheadSize;
3022
+ const estimatedFee = estimatedTxSize * feeRate / __pow(10, 8);
3023
+ console.log("estimated fee:", estimatedFee);
3024
+ const availableBalance = Math.max(0, balance - estimatedFee);
3025
+ return {
3026
+ rawBalance,
3027
+ balance,
3028
+ availableBalance
3029
+ };
3030
+ });
3031
+ }
3032
+ function sendBitcoin(address, amount, feeRate) {
3033
+ return __async(this, null, function* () {
3034
+ const { sendBitcoin: sendBitcoin2 } = getBtcProvider();
3035
+ const txHash = yield sendBitcoin2(address, amount, { feeRate });
3036
+ return txHash;
3037
+ });
3038
+ }
3039
+ function estimateDepositAmount(amount, option) {
3040
+ return __async(this, null, function* () {
3041
+ const config = yield getConfig((option == null ? void 0 : option.isDev) || false);
3042
+ const {
3043
+ deposit_bridge_fee: { fee_min, fee_rate }
3044
+ } = yield nearCall(
3045
+ config.bridgeContractId,
3046
+ "get_config",
3047
+ {}
2822
3048
  );
2823
- const maxAttempts = 3;
2824
- const pollStatus = (hash) => __async(this, null, function* () {
2825
- let attempt = 0;
2826
- while (attempt < maxAttempts) {
2827
- attempt++;
2828
- try {
2829
- const result = yield provider.txStatus(hash, "unused", "FINAL");
2830
- if (result && result.status) {
2831
- console.log(`Transaction ${hash} result:`, result);
2832
- return result;
2833
- }
2834
- } catch (error) {
2835
- console.error(`Failed to fetch transaction status for ${hash}: ${error.message}`);
3049
+ const fee = Math.max(Number(fee_min), Number(amount) * fee_rate);
3050
+ return new Big(amount).minus(fee).toFixed(0);
3051
+ });
3052
+ }
3053
+ function executeBTCDepositAndAction(_0) {
3054
+ return __async(this, arguments, function* ({
3055
+ action,
3056
+ feeRate,
3057
+ isDev = false
3058
+ }) {
3059
+ try {
3060
+ const { getPublicKey } = getBtcProvider();
3061
+ const config = yield getConfig(isDev);
3062
+ const btcPublicKey = yield getPublicKey();
3063
+ if (!btcPublicKey) {
3064
+ throw new Error("BTC Public Key is not available.");
3065
+ }
3066
+ if (!action.receiver_id) {
3067
+ throw new Error("receiver_id is required");
3068
+ }
3069
+ if (!action.amount) {
3070
+ throw new Error("amount is required");
3071
+ }
3072
+ const csna = yield nearCall(
3073
+ config.accountContractId,
3074
+ "get_chain_signature_near_account_id",
3075
+ {
3076
+ btc_public_key: btcPublicKey
2836
3077
  }
2837
- if (attempt === maxAttempts) {
2838
- throw new Error(`Transaction not found after max attempts: ${hash}`);
3078
+ );
3079
+ const depositMsg = {
3080
+ recipient_id: csna,
3081
+ post_actions: [
3082
+ __spreadProps(__spreadValues({}, action), {
3083
+ gas: new Big(100).mul(__pow(10, 12)).toFixed(0)
3084
+ })
3085
+ ]
3086
+ };
3087
+ const storageDepositMsg = {};
3088
+ const accountInfo = yield nearCall(
3089
+ config.accountContractId,
3090
+ "get_account",
3091
+ {
3092
+ account_id: csna
2839
3093
  }
2840
- yield delay(1e4);
2841
- console.log(`RPC request failed for ${hash}, retrying ${maxAttempts - attempt} more times`);
3094
+ );
3095
+ if (!(accountInfo == null ? void 0 : accountInfo.nonce)) {
3096
+ storageDepositMsg.btc_public_key = btcPublicKey;
2842
3097
  }
2843
- });
2844
- const results = yield Promise.all(hashes.map((hash) => pollStatus(hash)));
2845
- return results;
3098
+ const registerRes = yield nearCall(action.receiver_id, "storage_balance_of", {
3099
+ account_id: csna
3100
+ });
3101
+ if (!(registerRes == null ? void 0 : registerRes.available)) {
3102
+ storageDepositMsg.storage_deposit_msg = {
3103
+ contract_id: action.receiver_id,
3104
+ deposit: new Big(0.25).mul(__pow(10, 24)).toFixed(0),
3105
+ registration_only: true
3106
+ };
3107
+ }
3108
+ if (Object.keys(storageDepositMsg).length > 0) {
3109
+ depositMsg.extra_msg = JSON.stringify(storageDepositMsg);
3110
+ }
3111
+ console.log("get_user_deposit_address params:", { deposit_msg: depositMsg });
3112
+ const userDepositAddress = yield nearCall(
3113
+ config.bridgeContractId,
3114
+ "get_user_deposit_address",
3115
+ { deposit_msg: depositMsg }
3116
+ );
3117
+ const _feeRate = feeRate || (yield getBtcGasPrice());
3118
+ const minDepositAmount = 5e3;
3119
+ const sendAmount = Math.max(minDepositAmount, new Big(action.amount).toNumber());
3120
+ console.log("user deposit address:", userDepositAddress);
3121
+ console.log("send amount:", sendAmount);
3122
+ console.log("fee rate:", _feeRate);
3123
+ const txHash = yield sendBitcoin(userDepositAddress, sendAmount, _feeRate);
3124
+ yield receiveDepositMsg(config.base_url, {
3125
+ btcPublicKey,
3126
+ txHash,
3127
+ postActions: JSON.stringify(depositMsg.post_actions),
3128
+ extraMsg: depositMsg.extra_msg
3129
+ });
3130
+ const checkTransactionStatusRes = yield checkBridgeTransactionStatus(config.base_url, txHash);
3131
+ console.log("checkBridgeTransactionStatus resp:", checkTransactionStatusRes);
3132
+ const network = yield getNetwork();
3133
+ const result = yield pollTransactionStatuses(network, [checkTransactionStatusRes.ToTxHash]);
3134
+ return result;
3135
+ } catch (error) {
3136
+ console.error("executeBTCDepositAndAction error:", error);
3137
+ throw error;
3138
+ }
2846
3139
  });
2847
3140
  }
2848
3141
 
3142
+ // src/utils/Dialog.ts
3143
+ var Dialog = class {
3144
+ static injectStyles() {
3145
+ if (!document.querySelector("#dialog-styles")) {
3146
+ const styleSheet = document.createElement("style");
3147
+ styleSheet.id = "dialog-styles";
3148
+ styleSheet.textContent = this.style;
3149
+ document.head.appendChild(styleSheet);
3150
+ }
3151
+ }
3152
+ static confirm(options) {
3153
+ return new Promise((resolve) => {
3154
+ this.injectStyles();
3155
+ const container = document.createElement("div");
3156
+ container.innerHTML = this.template;
3157
+ document.body.appendChild(container);
3158
+ const titleEl = container.querySelector(".dialog-title");
3159
+ const messageEl = container.querySelector(".dialog-message");
3160
+ const confirmBtn = container.querySelector(".dialog-confirm-btn");
3161
+ const cancelBtn = container.querySelector(".dialog-cancel-btn");
3162
+ if (options.title) {
3163
+ titleEl.textContent = options.title;
3164
+ } else {
3165
+ titleEl.style.display = "none";
3166
+ }
3167
+ messageEl.textContent = options.message;
3168
+ const cleanup = () => {
3169
+ document.body.removeChild(container);
3170
+ };
3171
+ confirmBtn.addEventListener("click", () => {
3172
+ cleanup();
3173
+ resolve(true);
3174
+ });
3175
+ cancelBtn.addEventListener("click", () => {
3176
+ cleanup();
3177
+ resolve(false);
3178
+ });
3179
+ });
3180
+ }
3181
+ static alert(options) {
3182
+ return new Promise((resolve) => {
3183
+ this.injectStyles();
3184
+ const container = document.createElement("div");
3185
+ container.innerHTML = this.template;
3186
+ document.body.appendChild(container);
3187
+ const titleEl = container.querySelector(".dialog-title");
3188
+ const messageEl = container.querySelector(".dialog-message");
3189
+ const confirmBtn = container.querySelector(".dialog-confirm-btn");
3190
+ const cancelBtn = container.querySelector(".dialog-cancel-btn");
3191
+ if (options.title) {
3192
+ titleEl.textContent = options.title;
3193
+ } else {
3194
+ titleEl.style.display = "none";
3195
+ }
3196
+ messageEl.textContent = options.message;
3197
+ cancelBtn.style.display = "none";
3198
+ const cleanup = () => {
3199
+ document.body.removeChild(container);
3200
+ };
3201
+ confirmBtn.addEventListener("click", () => {
3202
+ cleanup();
3203
+ resolve();
3204
+ });
3205
+ });
3206
+ }
3207
+ };
3208
+ Dialog.template = `
3209
+ <div class="dialog-overlay">
3210
+ <div class="dialog-container">
3211
+ <div class="dialog-content">
3212
+ <div class="dialog-title"></div>
3213
+ <div class="dialog-message"></div>
3214
+ <div class="dialog-buttons">
3215
+ <button class="dialog-cancel-btn">Cancel</button>
3216
+ <button class="dialog-confirm-btn">Confirm</button>
3217
+ </div>
3218
+ </div>
3219
+ </div>
3220
+ </div>
3221
+ `;
3222
+ Dialog.style = `
3223
+ .dialog-overlay {
3224
+ position: fixed;
3225
+ top: 0;
3226
+ left: 0;
3227
+ right: 0;
3228
+ bottom: 0;
3229
+ background-color: rgba(0, 0, 0, 0.75);
3230
+ display: flex;
3231
+ align-items: center;
3232
+ justify-content: center;
3233
+ z-index: 999999;
3234
+ backdrop-filter: blur(4px);
3235
+ }
3236
+ .dialog-container {
3237
+ background: #21232f;
3238
+ border-radius: 12px;
3239
+ padding: 24px;
3240
+ width: 350px;
3241
+ box-shadow: 0 4px 24px rgba(0, 0, 0, 0.3);
3242
+ }
3243
+ .dialog-title {
3244
+ font-size: 18px;
3245
+ font-weight: 600;
3246
+ margin-bottom: 16px;
3247
+ color: #ffffff;
3248
+ }
3249
+ .dialog-message {
3250
+ margin-bottom: 24px;
3251
+ line-height: 1.6;
3252
+ color: rgba(255, 255, 255, 0.8);
3253
+ font-size: 14px;
3254
+ }
3255
+ .dialog-buttons {
3256
+ display: flex;
3257
+ justify-content: flex-end;
3258
+ gap: 12px;
3259
+ }
3260
+ .dialog-confirm-btn {
3261
+ padding: 8px 24px;
3262
+ background-color: #ff7a00;
3263
+ color: white;
3264
+ border: none;
3265
+ border-radius: 6px;
3266
+ cursor: pointer;
3267
+ font-size: 14px;
3268
+ font-weight: 500;
3269
+ transition: all 0.2s ease;
3270
+ }
3271
+ .dialog-confirm-btn:hover {
3272
+ background-color: #ff8f1f;
3273
+ transform: translateY(-1px);
3274
+ }
3275
+ .dialog-confirm-btn:active {
3276
+ transform: translateY(0);
3277
+ }
3278
+ .dialog-cancel-btn {
3279
+ padding: 8px 24px;
3280
+ background-color: rgba(255, 255, 255, 0.1);
3281
+ color: rgba(255, 255, 255, 0.8);
3282
+ border: none;
3283
+ border-radius: 6px;
3284
+ cursor: pointer;
3285
+ font-size: 14px;
3286
+ font-weight: 500;
3287
+ transition: all 0.2s ease;
3288
+ }
3289
+ .dialog-cancel-btn:hover {
3290
+ background-color: rgba(255, 255, 255, 0.15);
3291
+ transform: translateY(-1px);
3292
+ }
3293
+ .dialog-cancel-btn:active {
3294
+ transform: translateY(0);
3295
+ }
3296
+
3297
+ .dialog-overlay {
3298
+ animation: fadeIn 0.2s ease;
3299
+ }
3300
+ .dialog-container {
3301
+ animation: slideIn 0.2s ease;
3302
+ }
3303
+ @keyframes fadeIn {
3304
+ from {
3305
+ opacity: 0;
3306
+ }
3307
+ to {
3308
+ opacity: 1;
3309
+ }
3310
+ }
3311
+ @keyframes slideIn {
3312
+ from {
3313
+ transform: translateY(-20px);
3314
+ opacity: 0;
3315
+ }
3316
+ to {
3317
+ transform: translateY(0);
3318
+ opacity: 1;
3319
+ }
3320
+ }
3321
+ `;
3322
+
2849
3323
  // src/core/setupBTCWallet.ts
2850
- import Big from "big.js";
2851
3324
  var { transfer, functionCall } = actionCreators;
2852
3325
  var state = {
2853
3326
  saveAccount(account) {
@@ -2897,6 +3370,7 @@ var BTCWallet = (_0) => __async(void 0, [_0], function* ({
2897
3370
  id,
2898
3371
  provider
2899
3372
  }) {
3373
+ var _a;
2900
3374
  const wallet = {
2901
3375
  signIn,
2902
3376
  signOut,
@@ -2906,8 +3380,9 @@ var BTCWallet = (_0) => __async(void 0, [_0], function* ({
2906
3380
  signAndSendTransaction,
2907
3381
  signAndSendTransactions
2908
3382
  };
2909
- const currentConfig = "isDev" in metadata && metadata.isDev ? walletConfig.dev : walletConfig[options.network.networkId];
2910
- const walletNetwork = "isDev" in metadata && metadata.isDev ? "dev" : options.network.networkId;
3383
+ const isDev = (_a = "isDev" in metadata && metadata.isDev) != null ? _a : false;
3384
+ const currentConfig = isDev ? walletConfig.dev : walletConfig[options.network.networkId];
3385
+ const walletNetwork = isDev ? "dev" : options.network.networkId;
2911
3386
  initWalletButton(walletNetwork, wallet);
2912
3387
  if (!inter) {
2913
3388
  inter = setInterval(() => __async(void 0, null, function* () {
@@ -3045,105 +3520,140 @@ var BTCWallet = (_0) => __async(void 0, [_0], function* ({
3045
3520
  });
3046
3521
  }
3047
3522
  function signAndSendTransactions(params) {
3048
- return __async(this, null, function* () {
3049
- const btcContext = window.btcContext;
3050
- const accountId = state.getAccount();
3051
- const publicKey = state.getPublicKey();
3052
- const { header } = yield provider.block({ finality: "final" });
3053
- const rawAccessKey = yield provider.query({
3054
- request_type: "view_access_key",
3055
- account_id: accountId,
3056
- public_key: publicKey,
3057
- finality: "final"
3058
- });
3059
- const accessKey = __spreadProps(__spreadValues({}, rawAccessKey), {
3060
- nonce: BigInt(rawAccessKey.nonce || 0)
3061
- });
3062
- const publicKeyFormat = PublicKey.from(publicKey);
3063
- const { result_data: nearNonceFromApi } = yield getNearNonceFromApi(
3064
- currentConfig.base_url,
3065
- accountId
3066
- );
3067
- const { transferGasTransaction, useNearPayGas } = yield getGasConfig();
3068
- console.log("transferGasTransaction:", transferGasTransaction);
3069
- console.log("useNearPayGas:", useNearPayGas);
3070
- if (!useNearPayGas && transferGasTransaction) {
3071
- params.transactions.unshift(transferGasTransaction);
3072
- }
3073
- console.log("raw transactions:", params.transactions);
3074
- const newTransactions = params.transactions.map((transaction, index) => {
3075
- let nearNonceNumber = accessKey.nonce + BigInt(1);
3076
- if (nearNonceFromApi) {
3077
- nearNonceNumber = BigInt(nearNonceFromApi) > nearNonceNumber ? BigInt(nearNonceFromApi) : nearNonceNumber;
3078
- }
3079
- const newActions = transaction.actions.map((action) => {
3080
- switch (action.type) {
3081
- case "FunctionCall":
3082
- return functionCall(
3083
- action.params.methodName,
3084
- action.params.args,
3085
- BigInt(action.params.gas),
3086
- BigInt(action.params.deposit)
3087
- );
3088
- case "Transfer":
3089
- return transfer(BigInt(action.params.deposit));
3090
- }
3091
- }).filter(Boolean);
3092
- const _transaction = transactions.createTransaction(
3093
- accountId,
3094
- publicKeyFormat,
3095
- transaction.receiverId,
3096
- BigInt(nearNonceNumber) + BigInt(index),
3097
- newActions,
3098
- baseDecode(header.hash)
3099
- );
3100
- const txBytes = encodeTransaction(_transaction);
3101
- const txHex = Array.from(
3102
- txBytes,
3103
- (byte) => ("0" + (byte & 255).toString(16)).slice(-2)
3104
- ).join("");
3105
- console.log("txHex:", txHex);
3106
- const hash = bs58.encode(new Uint8Array(sha256.array(txBytes)));
3107
- return { txBytes, txHex, hash };
3108
- });
3109
- const accountInfo = yield nearCall2(
3110
- currentConfig.accountContractId,
3111
- "get_account",
3112
- { account_id: accountId }
3523
+ return __async(this, null, function* () {
3524
+ const btcContext = window.btcContext;
3525
+ const accountId = state.getAccount();
3526
+ const accountInfo = yield getAccountInfo();
3527
+ yield checkGasTokenArrears(accountInfo.debt_info);
3528
+ const trans = [...params.transactions];
3529
+ console.log("raw trans:", trans);
3530
+ const gasTokenBalance = accountInfo.gas_token[currentConfig.token] || "0";
3531
+ const { transferGasTransaction, useNearPayGas, gasLimit } = yield calculateGasStrategy(
3532
+ gasTokenBalance,
3533
+ trans
3113
3534
  );
3114
- const { result_data: nonceFromApi } = yield getNonceFromApi(
3115
- currentConfig.base_url,
3116
- accountId
3535
+ console.log("transferGasTransaction:", transferGasTransaction);
3536
+ console.log("useNearPayGas:", useNearPayGas);
3537
+ console.log("gasLimit:", gasLimit);
3538
+ if (transferGasTransaction) {
3539
+ trans.unshift(transferGasTransaction);
3540
+ }
3541
+ console.log("calculateGasStrategy trans:", trans);
3542
+ const newTrans = yield Promise.all(
3543
+ trans.map((transaction, index) => convertTransactionToTxHex(transaction, index))
3117
3544
  );
3545
+ const nonceFromApi = yield getNonce(currentConfig.base_url, accountId);
3118
3546
  const nonce = Number(nonceFromApi) > Number(accountInfo.nonce) ? String(nonceFromApi) : String(accountInfo.nonce);
3119
3547
  const intention = {
3120
3548
  chain_id: "397",
3121
3549
  csna: accountId,
3122
- near_transactions: newTransactions.map((t) => t.txHex),
3550
+ near_transactions: newTrans.map((t) => t.txHex),
3123
3551
  gas_token: currentConfig.token,
3124
- gas_limit: currentConfig.gasTokenLimit,
3552
+ gas_limit: gasLimit,
3125
3553
  use_near_pay_gas: useNearPayGas,
3126
3554
  nonce
3127
3555
  };
3128
3556
  const strIntention = JSON.stringify(intention);
3129
3557
  const signature = yield btcContext.signMessage(strIntention);
3130
- const result = yield uploadBTCTx(currentConfig.base_url, {
3558
+ yield receiveTransaction(currentConfig.base_url, {
3131
3559
  sig: signature,
3132
3560
  btcPubKey: state.getBtcPublicKey(),
3133
3561
  data: toHex(strIntention)
3134
3562
  });
3135
- if (result.result_code === 0) {
3136
- const hash = newTransactions.map((t) => t.hash);
3137
- console.log("txHash:", hash);
3138
- const result2 = yield pollTransactionStatuses(options.network.networkId, hash);
3139
- return result2;
3563
+ yield checkBtcTransactionStatus(currentConfig.base_url, signature);
3564
+ const hash = newTrans.map((t) => t.hash);
3565
+ console.log("txHash:", hash);
3566
+ const result = yield pollTransactionStatuses(options.network.networkId, hash);
3567
+ return result;
3568
+ });
3569
+ }
3570
+ function checkGasTokenArrears(debtInfo) {
3571
+ return __async(this, null, function* () {
3572
+ const transferAmount = (debtInfo == null ? void 0 : debtInfo.transfer_amount) || "0";
3573
+ console.log("get_account debtInfo:", debtInfo);
3574
+ if (transferAmount === "0")
3575
+ return;
3576
+ const confirmed = yield Dialog.confirm({
3577
+ title: "Has gas token arrears",
3578
+ message: "You have gas token arrears, please deposit gas token to continue."
3579
+ });
3580
+ if (confirmed) {
3581
+ const action = {
3582
+ receiver_id: currentConfig.token,
3583
+ amount: transferAmount,
3584
+ msg: JSON.stringify("Deposit")
3585
+ };
3586
+ yield executeBTCDepositAndAction({ action, isDev });
3587
+ yield Dialog.alert({
3588
+ title: "Deposit success",
3589
+ message: "Deposit success, will continue to execute transaction."
3590
+ });
3591
+ } else {
3592
+ throw new Error("Deposit failed, please deposit gas token first.");
3593
+ }
3594
+ });
3595
+ }
3596
+ function getAccountInfo() {
3597
+ return __async(this, null, function* () {
3598
+ const accountId = state.getAccount();
3599
+ const accountInfo = yield nearCall2(currentConfig.accountContractId, "get_account", { account_id: accountId });
3600
+ return accountInfo;
3601
+ });
3602
+ }
3603
+ function createGasTokenTransfer(accountId, amount) {
3604
+ return __async(this, null, function* () {
3605
+ return {
3606
+ signerId: accountId,
3607
+ receiverId: currentConfig.token,
3608
+ actions: [
3609
+ {
3610
+ type: "FunctionCall",
3611
+ params: {
3612
+ methodName: "ft_transfer_call",
3613
+ args: {
3614
+ receiver_id: currentConfig.accountContractId,
3615
+ amount,
3616
+ msg: JSON.stringify("Deposit")
3617
+ },
3618
+ gas: new Big2(50).mul(__pow(10, 12)).toFixed(0),
3619
+ deposit: "1"
3620
+ }
3621
+ }
3622
+ ]
3623
+ };
3624
+ });
3625
+ }
3626
+ function recalculateGasWithTransfer(transferTx, transactions2, useNearPayGas, perTxFee) {
3627
+ return __async(this, null, function* () {
3628
+ const { txHex: transferTxHex } = yield convertTransactionToTxHex(transferTx);
3629
+ let newGasLimit;
3630
+ if (useNearPayGas && perTxFee) {
3631
+ newGasLimit = new Big2(perTxFee).mul(transactions2.length + 1).toFixed(0);
3140
3632
  } else {
3141
- return null;
3633
+ newGasLimit = yield getPredictedGasAmount(
3634
+ currentConfig.accountContractId,
3635
+ currentConfig.token,
3636
+ [transferTxHex, ...transactions2.map((t) => t.txHex)]
3637
+ );
3142
3638
  }
3639
+ transferTx.actions[0].params.args.amount = newGasLimit;
3640
+ return { transferGasTransaction: transferTx, useNearPayGas, gasLimit: newGasLimit };
3641
+ });
3642
+ }
3643
+ function getPredictedGasAmount(accountContractId, tokenId, transactions2) {
3644
+ return __async(this, null, function* () {
3645
+ const predictedGas = yield nearCall2(accountContractId, "predict_txs_gas_token_amount", {
3646
+ gas_token_id: tokenId,
3647
+ near_transactions: transactions2
3648
+ });
3649
+ const predictedGasAmount = new Big2(predictedGas).mul(1.2).toFixed(0);
3650
+ console.log("predictedGas:", predictedGasAmount);
3651
+ return predictedGasAmount;
3143
3652
  });
3144
3653
  }
3145
- function getGasConfig() {
3654
+ function calculateGasStrategy(gasTokenBalance, transactions2) {
3146
3655
  return __async(this, null, function* () {
3656
+ var _a2;
3147
3657
  const accountId = state.getAccount();
3148
3658
  const nearAccount = yield provider.query({
3149
3659
  request_type: "view_account",
@@ -3151,39 +3661,102 @@ var BTCWallet = (_0) => __async(void 0, [_0], function* ({
3151
3661
  finality: "final"
3152
3662
  });
3153
3663
  const availableBalance = parseFloat(nearAccount.amount) / __pow(10, 24);
3664
+ console.log("available near balance:", availableBalance);
3665
+ console.log("available gas token balance:", gasTokenBalance);
3666
+ const convertTx = yield Promise.all(
3667
+ transactions2.map((transaction, index) => convertTransactionToTxHex(transaction, index))
3668
+ );
3154
3669
  if (availableBalance > 0.2) {
3155
- return { useNearPayGas: true };
3670
+ const gasTokens = yield nearCall2(
3671
+ currentConfig.accountContractId,
3672
+ "list_gas_token",
3673
+ { token_ids: [currentConfig.token] }
3674
+ );
3675
+ console.log("list_gas_token gas tokens:", gasTokens);
3676
+ const perTxFee = Math.max(
3677
+ Number(((_a2 = gasTokens[currentConfig.token]) == null ? void 0 : _a2.per_tx_protocol_fee) || 0),
3678
+ 100
3679
+ );
3680
+ console.log("perTxFee:", perTxFee);
3681
+ const protocolFee = new Big2(perTxFee || "0").mul(convertTx.length).toFixed(0);
3682
+ console.log("protocolFee:", protocolFee);
3683
+ if (new Big2(gasTokenBalance).gte(protocolFee)) {
3684
+ console.log("use near pay gas and enough gas token balance");
3685
+ return { useNearPayGas: true, gasLimit: protocolFee };
3686
+ } else {
3687
+ console.log("use near pay gas and not enough gas token balance");
3688
+ const transferTx = yield createGasTokenTransfer(accountId, protocolFee);
3689
+ return recalculateGasWithTransfer(transferTx, convertTx, true, perTxFee.toString());
3690
+ }
3156
3691
  } else {
3157
- const gasTokenBalance = yield nearCall2(currentConfig.token, "ft_balance_of", {
3158
- account_id: accountId
3159
- });
3160
- if (new Big(gasTokenBalance).gt(currentConfig.gasTokenLimit)) {
3161
- const transferGasTransaction = {
3162
- signerId: accountId,
3163
- receiverId: currentConfig.token,
3164
- actions: [
3165
- {
3166
- type: "FunctionCall",
3167
- params: {
3168
- methodName: "ft_transfer_call",
3169
- args: {
3170
- receiver_id: currentConfig.accountContractId,
3171
- amount: currentConfig.gasTokenLimit,
3172
- msg: "Deposit"
3173
- },
3174
- gas: new Big(50).mul(__pow(10, 12)).toFixed(0),
3175
- deposit: "1"
3176
- }
3177
- }
3178
- ]
3179
- };
3180
- return { transferGasTransaction, useNearPayGas: false };
3692
+ console.log("near balance is not enough, predict the gas token amount required");
3693
+ const adjustedGas = yield getPredictedGasAmount(
3694
+ currentConfig.accountContractId,
3695
+ currentConfig.token,
3696
+ convertTx.map((t) => t.txHex)
3697
+ );
3698
+ if (new Big2(gasTokenBalance).gte(adjustedGas)) {
3699
+ console.log("use gas token and gas token balance is enough");
3700
+ return { useNearPayGas: false, gasLimit: adjustedGas };
3181
3701
  } else {
3182
- throw new Error("No enough gas token balance");
3702
+ console.log("use gas token and gas token balance is not enough, need to transfer");
3703
+ const transferTx = yield createGasTokenTransfer(accountId, adjustedGas);
3704
+ return recalculateGasWithTransfer(transferTx, convertTx, false);
3183
3705
  }
3184
3706
  }
3185
3707
  });
3186
3708
  }
3709
+ function convertTransactionToTxHex(transaction, index = 0) {
3710
+ return __async(this, null, function* () {
3711
+ const accountId = state.getAccount();
3712
+ const publicKey = state.getPublicKey();
3713
+ const publicKeyFormat = PublicKey.from(publicKey);
3714
+ const { header } = yield provider.block({
3715
+ finality: "final"
3716
+ });
3717
+ const rawAccessKey = yield provider.query({
3718
+ request_type: "view_access_key",
3719
+ account_id: accountId,
3720
+ public_key: publicKey,
3721
+ finality: "final"
3722
+ });
3723
+ const accessKey = __spreadProps(__spreadValues({}, rawAccessKey), {
3724
+ nonce: BigInt(rawAccessKey.nonce || 0)
3725
+ });
3726
+ const nearNonceFromApi = yield getNearNonce(currentConfig.base_url, accountId);
3727
+ let nearNonceNumber = accessKey.nonce + BigInt(1);
3728
+ if (nearNonceFromApi) {
3729
+ nearNonceNumber = BigInt(nearNonceFromApi) > nearNonceNumber ? BigInt(nearNonceFromApi) : nearNonceNumber;
3730
+ }
3731
+ const newActions = transaction.actions.map((action) => {
3732
+ switch (action.type) {
3733
+ case "FunctionCall":
3734
+ return functionCall(
3735
+ action.params.methodName,
3736
+ action.params.args,
3737
+ BigInt(action.params.gas),
3738
+ BigInt(action.params.deposit)
3739
+ );
3740
+ case "Transfer":
3741
+ return transfer(BigInt(action.params.deposit));
3742
+ }
3743
+ }).filter(Boolean);
3744
+ const _transaction = transactions.createTransaction(
3745
+ accountId,
3746
+ publicKeyFormat,
3747
+ transaction.receiverId,
3748
+ BigInt(nearNonceNumber) + BigInt(index),
3749
+ newActions,
3750
+ baseDecode(header.hash)
3751
+ );
3752
+ const txBytes = encodeTransaction(_transaction);
3753
+ const txHex = Array.from(txBytes, (byte) => ("0" + (byte & 255).toString(16)).slice(-2)).join(
3754
+ ""
3755
+ );
3756
+ const hash = bs58.encode(new Uint8Array(sha256.array(txBytes)));
3757
+ return { txBytes, txHex, hash };
3758
+ });
3759
+ }
3187
3760
  function initWalletButton(network, wallet2) {
3188
3761
  return __async(this, null, function* () {
3189
3762
  const checkAndSetupWalletButton = () => {
@@ -3204,17 +3777,13 @@ var BTCWallet = (_0) => __async(void 0, [_0], function* ({
3204
3777
  }
3205
3778
  return wallet;
3206
3779
  });
3207
- function getNonceFromApi(url, accountId) {
3208
- return request(`${url}/v1/nonce?csna=${accountId}`);
3209
- }
3210
- function getNearNonceFromApi(url, accountId) {
3211
- return request(`${url}/v1/nonceNear?csna=${accountId}`);
3212
- }
3213
- function uploadBTCTx(url, data) {
3214
- return request(`${url}/v1/receiveTransaction`, {
3215
- method: "POST",
3216
- body: data
3217
- });
3780
+ function toHex(originalString) {
3781
+ const charArray = originalString.split("");
3782
+ const asciiArray = charArray.map((char) => char.charCodeAt(0));
3783
+ const hexArray = asciiArray.map((code) => code.toString(16));
3784
+ let hexString = hexArray.join("");
3785
+ hexString = hexString.replace(/(^0+)/g, "");
3786
+ return hexString;
3218
3787
  }
3219
3788
  function setupBTCWallet({
3220
3789
  iconUrl = "https://assets.deltatrade.ai/assets/chain/btc.svg",
@@ -3243,232 +3812,10 @@ function setupBTCWallet({
3243
3812
  });
3244
3813
  return btcWallet;
3245
3814
  }
3246
- function toHex(originalString) {
3247
- const charArray = originalString.split("");
3248
- const asciiArray = charArray.map((char) => char.charCodeAt(0));
3249
- const hexArray = asciiArray.map((code) => code.toString(16));
3250
- let hexString = hexArray.join("");
3251
- hexString = hexString.replace(/(^0+)/g, "");
3252
- return hexString;
3253
- }
3254
-
3255
- // src/core/btcUtils.ts
3256
- import Big2 from "big.js";
3257
- function getBtcProvider() {
3258
- if (typeof window === "undefined" || !window.btcContext) {
3259
- throw new Error("BTC Provider is not initialized.");
3260
- }
3261
- return window.btcContext;
3262
- }
3263
- function getNetwork() {
3264
- return __async(this, null, function* () {
3265
- const network = yield getBtcProvider().getNetwork();
3266
- console.log("btc network:", network);
3267
- return network === "livenet" ? "mainnet" : "testnet";
3268
- });
3269
- }
3270
- function getBtcRpcUrl() {
3271
- return __async(this, null, function* () {
3272
- const network = yield getNetwork();
3273
- return btcRpcUrls[network];
3274
- });
3275
- }
3276
- function getConfig(isDev) {
3277
- return __async(this, null, function* () {
3278
- const network = yield getNetwork();
3279
- return walletConfig[isDev ? "dev" : network];
3280
- });
3281
- }
3282
- function nearCall(contractId, methodName, args) {
3283
- return __async(this, null, function* () {
3284
- const network = yield getNetwork();
3285
- return nearCallFunction(contractId, methodName, args, { network });
3286
- });
3287
- }
3288
- function receiveDepositMsg(_0, _1) {
3289
- return __async(this, arguments, function* (baseUrl, {
3290
- btcPublicKey,
3291
- txHash,
3292
- depositType = 1,
3293
- postActions,
3294
- extraMsg
3295
- }) {
3296
- const res = yield request(`${baseUrl}/v1/receiveDepositMsg`, {
3297
- method: "POST",
3298
- body: { btcPublicKey, txHash, depositType, postActions, extraMsg }
3299
- });
3300
- console.log("receiveDepositMsg resp:", res);
3301
- return res;
3302
- });
3303
- }
3304
- function checkTransactionStatus(baseUrl, txHash) {
3305
- return __async(this, null, function* () {
3306
- const res = yield request(
3307
- `${baseUrl}/v1/bridgeFromTx?fromTxHash=${txHash}&fromChainId=1`,
3308
- {
3309
- timeout: 6e4,
3310
- pollingInterval: 5e3,
3311
- maxPollingAttempts: 10,
3312
- shouldStopPolling: (res2) => res2.result_code === 0
3313
- }
3314
- );
3315
- return res;
3316
- });
3317
- }
3318
- function getBtcGasPrice() {
3319
- return __async(this, null, function* () {
3320
- const defaultFeeRate = 100;
3321
- try {
3322
- const btcRpcUrl = yield getBtcRpcUrl();
3323
- const res = yield fetch(`${btcRpcUrl}/v1/fees/recommended`).then((res2) => res2.json());
3324
- const feeRate = res.fastestFee;
3325
- return feeRate || defaultFeeRate;
3326
- } catch (error) {
3327
- return defaultFeeRate;
3328
- }
3329
- });
3330
- }
3331
- function getBtcBalance() {
3332
- return __async(this, null, function* () {
3333
- const { account } = yield retryOperation(getBtcProvider, (res2) => !!res2.account);
3334
- if (!account) {
3335
- console.error("BTC Account is not available.");
3336
- return { rawBalance: 0, balance: 0, maxSpendableBalance: 0 };
3337
- }
3338
- const btcRpcUrl = yield getBtcRpcUrl();
3339
- const res = yield fetch(`${btcRpcUrl}/address/${account}/utxo`).then((res2) => res2.json());
3340
- const rawBalance = res == null ? void 0 : res.reduce((acc, cur) => acc + cur.value, 0);
3341
- const balance = rawBalance / __pow(10, 8);
3342
- const feeRate = yield getBtcGasPrice();
3343
- const maxGasFee = feeRate * 350 / __pow(10, 8);
3344
- const availableBalance = Math.max(0, balance - maxGasFee);
3345
- return {
3346
- rawBalance,
3347
- balance,
3348
- availableBalance
3349
- };
3350
- });
3351
- }
3352
- function sendBitcoin(address, amount, feeRate) {
3353
- return __async(this, null, function* () {
3354
- const { sendBitcoin: sendBitcoin2 } = getBtcProvider();
3355
- const txHash = yield sendBitcoin2(address, amount, { feeRate });
3356
- return txHash;
3357
- });
3358
- }
3359
- function estimateDepositAmount(amount, option) {
3360
- return __async(this, null, function* () {
3361
- const config = yield getConfig((option == null ? void 0 : option.isDev) || false);
3362
- const {
3363
- deposit_bridge_fee: { fee_min, fee_rate }
3364
- } = yield nearCall(
3365
- config.bridgeContractId,
3366
- "get_config",
3367
- {}
3368
- );
3369
- const fee = Math.max(Number(fee_min), Number(amount) * fee_rate);
3370
- return new Big2(amount).minus(fee).toFixed(0);
3371
- });
3372
- }
3373
- function executeBTCDepositAndAction(_0) {
3374
- return __async(this, arguments, function* ({
3375
- action,
3376
- feeRate,
3377
- isDev = false
3378
- }) {
3379
- try {
3380
- const { getPublicKey } = getBtcProvider();
3381
- const config = yield getConfig(isDev);
3382
- const btcPublicKey = yield getPublicKey();
3383
- const _action = Object.assign(
3384
- {},
3385
- __spreadProps(__spreadValues({}, action), {
3386
- gas: new Big2(100).mul(__pow(10, 12)).toFixed(0)
3387
- })
3388
- );
3389
- if (!btcPublicKey) {
3390
- throw new Error("BTC Public Key is not available.");
3391
- }
3392
- if (!_action.receiver_id) {
3393
- throw new Error("action.receiver_id is required");
3394
- }
3395
- const amountWithFee = yield estimateDepositAmount(_action.amount, {
3396
- isDev
3397
- });
3398
- _action.amount = amountWithFee;
3399
- if (!_action.amount || !new Big2(_action.amount || 0).gt(0)) {
3400
- throw new Error("action.amount is required or deposit amount is not enough");
3401
- }
3402
- const csna = yield nearCall(
3403
- config.accountContractId,
3404
- "get_chain_signature_near_account_id",
3405
- {
3406
- btc_public_key: btcPublicKey
3407
- }
3408
- );
3409
- const depositMsg = {
3410
- recipient_id: csna,
3411
- post_actions: [_action]
3412
- };
3413
- const storageDepositMsg = {};
3414
- const accountInfo = yield nearCall(
3415
- config.accountContractId,
3416
- "get_account",
3417
- {
3418
- account_id: csna
3419
- }
3420
- );
3421
- if (!(accountInfo == null ? void 0 : accountInfo.nonce)) {
3422
- storageDepositMsg.btc_public_key = btcPublicKey;
3423
- }
3424
- const registerRes = yield nearCall(action.receiver_id, "storage_balance_of", {
3425
- account_id: csna
3426
- });
3427
- if (!(registerRes == null ? void 0 : registerRes.available)) {
3428
- storageDepositMsg.storage_deposit_msg = {
3429
- contract_id: action.receiver_id,
3430
- deposit: new Big2(0.25).mul(__pow(10, 24)).toFixed(0),
3431
- registration_only: true
3432
- };
3433
- }
3434
- if (Object.keys(storageDepositMsg).length > 0) {
3435
- depositMsg.extra_msg = JSON.stringify(storageDepositMsg);
3436
- }
3437
- console.log("get_user_deposit_address params:", { deposit_msg: depositMsg });
3438
- const userDepositAddress = yield nearCall(
3439
- config.bridgeContractId,
3440
- "get_user_deposit_address",
3441
- { deposit_msg: depositMsg }
3442
- );
3443
- const _feeRate = feeRate || (yield getBtcGasPrice());
3444
- console.log("user deposit address:", userDepositAddress);
3445
- console.log("deposit amount:", new Big2(action.amount).toNumber());
3446
- console.log("receive amount:", new Big2(_action.amount).toNumber());
3447
- console.log("fee rate:", _feeRate);
3448
- const txHash = yield sendBitcoin(
3449
- userDepositAddress,
3450
- new Big2(action.amount).toNumber(),
3451
- _feeRate
3452
- );
3453
- yield receiveDepositMsg(config.base_url, {
3454
- btcPublicKey,
3455
- txHash,
3456
- postActions: JSON.stringify(depositMsg.post_actions),
3457
- extraMsg: depositMsg.extra_msg
3458
- });
3459
- const checkTransactionStatusRes = yield checkTransactionStatus(config.base_url, txHash);
3460
- console.log("checkTransactionStatus resp:", checkTransactionStatusRes);
3461
- return checkTransactionStatusRes.result_code === 0 ? { result: "success" } : { result: "failed", error: checkTransactionStatusRes.result_message };
3462
- } catch (error) {
3463
- console.error("Error executing Bridge+BurrowSupply:", error);
3464
- return { result: "failed", error: error.message };
3465
- }
3466
- });
3467
- }
3468
3815
 
3469
3816
  // src/index.ts
3470
3817
  var getVersion = () => {
3471
- return "0.3.10";
3818
+ return "0.3.12";
3472
3819
  };
3473
3820
  if (typeof window !== "undefined") {
3474
3821
  window.__PARTICLE_BTC_CONNECT_VERSION = getVersion();