btc-wallet 0.3.10 → 0.3.12

Sign up to get free protection for your applications and to get access to all the features.
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();