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