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/dist/core/btcUtils.d.ts +1 -7
- package/dist/index.js +736 -389
- package/dist/index.js.map +4 -4
- package/dist/utils/Dialog.d.ts +13 -0
- package/dist/utils/nearUtils.d.ts +1 -2
- package/dist/utils/request.d.ts +1 -1
- package/dist/utils/satoshi.d.ts +18 -0
- package/esm/index.js +735 -388
- 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
|
|
@@ -2754,9 +2754,7 @@ var nearRpcUrls = {
|
|
2754
2754
|
"https://near.drpc.org"
|
2755
2755
|
],
|
2756
2756
|
testnet: [
|
2757
|
-
"https://rpc.testnet.near.org"
|
2758
|
-
"https://near-testnet.lava.build",
|
2759
|
-
"https://near-testnet.drpc.org"
|
2757
|
+
"https://rpc.testnet.near.org"
|
2760
2758
|
]
|
2761
2759
|
};
|
2762
2760
|
var btcRpcUrls = {
|
@@ -2764,6 +2762,73 @@ var btcRpcUrls = {
|
|
2764
2762
|
testnet: "https://mempool.space/testnet/api"
|
2765
2763
|
};
|
2766
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
|
+
|
2767
2832
|
// src/utils/request.ts
|
2768
2833
|
var cache = /* @__PURE__ */ new Map();
|
2769
2834
|
var defaultCacheTimeout = 3e3;
|
@@ -2804,18 +2869,20 @@ function request(url, options) {
|
|
2804
2869
|
if (!res.ok)
|
2805
2870
|
throw new Error(res.statusText);
|
2806
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
|
+
}
|
2807
2878
|
if (cacheKey) {
|
2808
2879
|
cache.set(cacheKey, { timestamp: Date.now(), data });
|
2809
2880
|
setTimeout(() => {
|
2810
2881
|
cache.delete(cacheKey);
|
2811
2882
|
}, cacheTimeout);
|
2812
2883
|
}
|
2813
|
-
if ((options == null ? void 0 : options.shouldStopPolling) && options.shouldStopPolling(data)) {
|
2814
|
-
return data;
|
2815
|
-
}
|
2816
2884
|
return data;
|
2817
2885
|
} catch (err) {
|
2818
|
-
console.error(err);
|
2819
2886
|
if (retryCount > 0) {
|
2820
2887
|
console.log(`Retrying... attempts left: ${retryCount}`);
|
2821
2888
|
return request(url, __spreadProps(__spreadValues({}, options), { retryCount: retryCount - 1 }));
|
@@ -2829,65 +2896,471 @@ function request(url, options) {
|
|
2829
2896
|
}));
|
2830
2897
|
}
|
2831
2898
|
}
|
2832
|
-
|
2899
|
+
throw err;
|
2833
2900
|
}
|
2834
2901
|
});
|
2835
2902
|
}
|
2836
2903
|
|
2837
|
-
// src/utils/
|
2838
|
-
|
2839
|
-
function nearCallFunction(contractId, methodName, args, options) {
|
2904
|
+
// src/utils/satoshi.ts
|
2905
|
+
function getNonce(url, accountId) {
|
2840
2906
|
return __async(this, null, function* () {
|
2841
|
-
const
|
2842
|
-
|
2843
|
-
(url) => new import_near_api_js.providers.JsonRpcProvider({ url })
|
2844
|
-
)
|
2907
|
+
const { result_code, result_message, result_data } = yield request(
|
2908
|
+
`${url}/v1/nonce?csna=${accountId}`
|
2845
2909
|
);
|
2846
|
-
|
2847
|
-
|
2848
|
-
|
2849
|
-
|
2850
|
-
|
2851
|
-
|
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
|
+
}
|
2852
2974
|
});
|
2853
|
-
|
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;
|
2854
2980
|
});
|
2855
2981
|
}
|
2856
|
-
function
|
2982
|
+
function checkBtcTransactionStatus(url, sig) {
|
2857
2983
|
return __async(this, null, function* () {
|
2858
|
-
const
|
2859
|
-
|
2860
|
-
|
2861
|
-
|
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
|
+
{}
|
2862
3088
|
);
|
2863
|
-
const
|
2864
|
-
|
2865
|
-
|
2866
|
-
|
2867
|
-
|
2868
|
-
|
2869
|
-
|
2870
|
-
|
2871
|
-
|
2872
|
-
|
2873
|
-
|
2874
|
-
|
2875
|
-
|
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
|
2876
3117
|
}
|
2877
|
-
|
2878
|
-
|
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
|
2879
3133
|
}
|
2880
|
-
|
2881
|
-
|
3134
|
+
);
|
3135
|
+
if (!(accountInfo == null ? void 0 : accountInfo.nonce)) {
|
3136
|
+
storageDepositMsg.btc_public_key = btcPublicKey;
|
2882
3137
|
}
|
2883
|
-
|
2884
|
-
|
2885
|
-
|
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);
|
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;
|
3178
|
+
}
|
2886
3179
|
});
|
2887
3180
|
}
|
2888
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
|
+
|
2889
3363
|
// src/core/setupBTCWallet.ts
|
2890
|
-
var import_big = __toESM(require("big.js"), 1);
|
2891
3364
|
var { transfer, functionCall } = import_transactions.actionCreators;
|
2892
3365
|
var state = {
|
2893
3366
|
saveAccount(account) {
|
@@ -2937,6 +3410,7 @@ var BTCWallet = (_0) => __async(void 0, [_0], function* ({
|
|
2937
3410
|
id,
|
2938
3411
|
provider
|
2939
3412
|
}) {
|
3413
|
+
var _a;
|
2940
3414
|
const wallet = {
|
2941
3415
|
signIn,
|
2942
3416
|
signOut,
|
@@ -2946,8 +3420,9 @@ var BTCWallet = (_0) => __async(void 0, [_0], function* ({
|
|
2946
3420
|
signAndSendTransaction,
|
2947
3421
|
signAndSendTransactions
|
2948
3422
|
};
|
2949
|
-
const
|
2950
|
-
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;
|
2951
3426
|
initWalletButton(walletNetwork, wallet);
|
2952
3427
|
if (!inter) {
|
2953
3428
|
inter = setInterval(() => __async(void 0, null, function* () {
|
@@ -3085,105 +3560,140 @@ var BTCWallet = (_0) => __async(void 0, [_0], function* ({
|
|
3085
3560
|
});
|
3086
3561
|
}
|
3087
3562
|
function signAndSendTransactions(params) {
|
3088
|
-
return __async(this, null, function* () {
|
3089
|
-
const btcContext = window.btcContext;
|
3090
|
-
const accountId = state.getAccount();
|
3091
|
-
const
|
3092
|
-
|
3093
|
-
const
|
3094
|
-
|
3095
|
-
|
3096
|
-
|
3097
|
-
|
3098
|
-
|
3099
|
-
const accessKey = __spreadProps(__spreadValues({}, rawAccessKey), {
|
3100
|
-
nonce: BigInt(rawAccessKey.nonce || 0)
|
3101
|
-
});
|
3102
|
-
const publicKeyFormat = import_key_pair.PublicKey.from(publicKey);
|
3103
|
-
const { result_data: nearNonceFromApi } = yield getNearNonceFromApi(
|
3104
|
-
currentConfig.base_url,
|
3105
|
-
accountId
|
3106
|
-
);
|
3107
|
-
const { transferGasTransaction, useNearPayGas } = yield getGasConfig();
|
3108
|
-
console.log("transferGasTransaction:", transferGasTransaction);
|
3109
|
-
console.log("useNearPayGas:", useNearPayGas);
|
3110
|
-
if (!useNearPayGas && transferGasTransaction) {
|
3111
|
-
params.transactions.unshift(transferGasTransaction);
|
3112
|
-
}
|
3113
|
-
console.log("raw transactions:", params.transactions);
|
3114
|
-
const newTransactions = params.transactions.map((transaction, index) => {
|
3115
|
-
let nearNonceNumber = accessKey.nonce + BigInt(1);
|
3116
|
-
if (nearNonceFromApi) {
|
3117
|
-
nearNonceNumber = BigInt(nearNonceFromApi) > nearNonceNumber ? BigInt(nearNonceFromApi) : nearNonceNumber;
|
3118
|
-
}
|
3119
|
-
const newActions = transaction.actions.map((action) => {
|
3120
|
-
switch (action.type) {
|
3121
|
-
case "FunctionCall":
|
3122
|
-
return functionCall(
|
3123
|
-
action.params.methodName,
|
3124
|
-
action.params.args,
|
3125
|
-
BigInt(action.params.gas),
|
3126
|
-
BigInt(action.params.deposit)
|
3127
|
-
);
|
3128
|
-
case "Transfer":
|
3129
|
-
return transfer(BigInt(action.params.deposit));
|
3130
|
-
}
|
3131
|
-
}).filter(Boolean);
|
3132
|
-
const _transaction = import_near_api_js2.transactions.createTransaction(
|
3133
|
-
accountId,
|
3134
|
-
publicKeyFormat,
|
3135
|
-
transaction.receiverId,
|
3136
|
-
BigInt(nearNonceNumber) + BigInt(index),
|
3137
|
-
newActions,
|
3138
|
-
(0, import_utils5.baseDecode)(header.hash)
|
3139
|
-
);
|
3140
|
-
const txBytes = (0, import_transaction.encodeTransaction)(_transaction);
|
3141
|
-
const txHex = Array.from(
|
3142
|
-
txBytes,
|
3143
|
-
(byte) => ("0" + (byte & 255).toString(16)).slice(-2)
|
3144
|
-
).join("");
|
3145
|
-
console.log("txHex:", txHex);
|
3146
|
-
const hash = import_bs58.default.encode(new Uint8Array(import_js_sha256.sha256.array(txBytes)));
|
3147
|
-
return { txBytes, txHex, hash };
|
3148
|
-
});
|
3149
|
-
const accountInfo = yield nearCall2(
|
3150
|
-
currentConfig.accountContractId,
|
3151
|
-
"get_account",
|
3152
|
-
{ account_id: accountId }
|
3563
|
+
return __async(this, null, function* () {
|
3564
|
+
const btcContext = window.btcContext;
|
3565
|
+
const accountId = state.getAccount();
|
3566
|
+
const accountInfo = yield getAccountInfo();
|
3567
|
+
yield checkGasTokenArrears(accountInfo.debt_info);
|
3568
|
+
const trans = [...params.transactions];
|
3569
|
+
console.log("raw trans:", trans);
|
3570
|
+
const gasTokenBalance = accountInfo.gas_token[currentConfig.token] || "0";
|
3571
|
+
const { transferGasTransaction, useNearPayGas, gasLimit } = yield calculateGasStrategy(
|
3572
|
+
gasTokenBalance,
|
3573
|
+
trans
|
3153
3574
|
);
|
3154
|
-
|
3155
|
-
|
3156
|
-
|
3575
|
+
console.log("transferGasTransaction:", transferGasTransaction);
|
3576
|
+
console.log("useNearPayGas:", useNearPayGas);
|
3577
|
+
console.log("gasLimit:", gasLimit);
|
3578
|
+
if (transferGasTransaction) {
|
3579
|
+
trans.unshift(transferGasTransaction);
|
3580
|
+
}
|
3581
|
+
console.log("calculateGasStrategy trans:", trans);
|
3582
|
+
const newTrans = yield Promise.all(
|
3583
|
+
trans.map((transaction, index) => convertTransactionToTxHex(transaction, index))
|
3157
3584
|
);
|
3585
|
+
const nonceFromApi = yield getNonce(currentConfig.base_url, accountId);
|
3158
3586
|
const nonce = Number(nonceFromApi) > Number(accountInfo.nonce) ? String(nonceFromApi) : String(accountInfo.nonce);
|
3159
3587
|
const intention = {
|
3160
3588
|
chain_id: "397",
|
3161
3589
|
csna: accountId,
|
3162
|
-
near_transactions:
|
3590
|
+
near_transactions: newTrans.map((t) => t.txHex),
|
3163
3591
|
gas_token: currentConfig.token,
|
3164
|
-
gas_limit:
|
3592
|
+
gas_limit: gasLimit,
|
3165
3593
|
use_near_pay_gas: useNearPayGas,
|
3166
3594
|
nonce
|
3167
3595
|
};
|
3168
3596
|
const strIntention = JSON.stringify(intention);
|
3169
3597
|
const signature = yield btcContext.signMessage(strIntention);
|
3170
|
-
|
3598
|
+
yield receiveTransaction(currentConfig.base_url, {
|
3171
3599
|
sig: signature,
|
3172
3600
|
btcPubKey: state.getBtcPublicKey(),
|
3173
3601
|
data: toHex(strIntention)
|
3174
3602
|
});
|
3175
|
-
|
3176
|
-
|
3177
|
-
|
3178
|
-
|
3179
|
-
|
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
|
+
});
|
3631
|
+
} else {
|
3632
|
+
throw new Error("Deposit failed, please deposit gas token first.");
|
3633
|
+
}
|
3634
|
+
});
|
3635
|
+
}
|
3636
|
+
function getAccountInfo() {
|
3637
|
+
return __async(this, null, function* () {
|
3638
|
+
const accountId = state.getAccount();
|
3639
|
+
const accountInfo = yield nearCall2(currentConfig.accountContractId, "get_account", { account_id: accountId });
|
3640
|
+
return accountInfo;
|
3641
|
+
});
|
3642
|
+
}
|
3643
|
+
function createGasTokenTransfer(accountId, amount) {
|
3644
|
+
return __async(this, null, function* () {
|
3645
|
+
return {
|
3646
|
+
signerId: accountId,
|
3647
|
+
receiverId: currentConfig.token,
|
3648
|
+
actions: [
|
3649
|
+
{
|
3650
|
+
type: "FunctionCall",
|
3651
|
+
params: {
|
3652
|
+
methodName: "ft_transfer_call",
|
3653
|
+
args: {
|
3654
|
+
receiver_id: currentConfig.accountContractId,
|
3655
|
+
amount,
|
3656
|
+
msg: JSON.stringify("Deposit")
|
3657
|
+
},
|
3658
|
+
gas: new import_big2.default(50).mul(__pow(10, 12)).toFixed(0),
|
3659
|
+
deposit: "1"
|
3660
|
+
}
|
3661
|
+
}
|
3662
|
+
]
|
3663
|
+
};
|
3664
|
+
});
|
3665
|
+
}
|
3666
|
+
function recalculateGasWithTransfer(transferTx, transactions2, useNearPayGas, perTxFee) {
|
3667
|
+
return __async(this, null, function* () {
|
3668
|
+
const { txHex: transferTxHex } = yield convertTransactionToTxHex(transferTx);
|
3669
|
+
let newGasLimit;
|
3670
|
+
if (useNearPayGas && perTxFee) {
|
3671
|
+
newGasLimit = new import_big2.default(perTxFee).mul(transactions2.length + 1).toFixed(0);
|
3180
3672
|
} else {
|
3181
|
-
|
3673
|
+
newGasLimit = yield getPredictedGasAmount(
|
3674
|
+
currentConfig.accountContractId,
|
3675
|
+
currentConfig.token,
|
3676
|
+
[transferTxHex, ...transactions2.map((t) => t.txHex)]
|
3677
|
+
);
|
3182
3678
|
}
|
3679
|
+
transferTx.actions[0].params.args.amount = newGasLimit;
|
3680
|
+
return { transferGasTransaction: transferTx, useNearPayGas, gasLimit: newGasLimit };
|
3681
|
+
});
|
3682
|
+
}
|
3683
|
+
function getPredictedGasAmount(accountContractId, tokenId, transactions2) {
|
3684
|
+
return __async(this, null, function* () {
|
3685
|
+
const predictedGas = yield nearCall2(accountContractId, "predict_txs_gas_token_amount", {
|
3686
|
+
gas_token_id: tokenId,
|
3687
|
+
near_transactions: transactions2
|
3688
|
+
});
|
3689
|
+
const predictedGasAmount = new import_big2.default(predictedGas).mul(1.2).toFixed(0);
|
3690
|
+
console.log("predictedGas:", predictedGasAmount);
|
3691
|
+
return predictedGasAmount;
|
3183
3692
|
});
|
3184
3693
|
}
|
3185
|
-
function
|
3694
|
+
function calculateGasStrategy(gasTokenBalance, transactions2) {
|
3186
3695
|
return __async(this, null, function* () {
|
3696
|
+
var _a2;
|
3187
3697
|
const accountId = state.getAccount();
|
3188
3698
|
const nearAccount = yield provider.query({
|
3189
3699
|
request_type: "view_account",
|
@@ -3191,39 +3701,102 @@ var BTCWallet = (_0) => __async(void 0, [_0], function* ({
|
|
3191
3701
|
finality: "final"
|
3192
3702
|
});
|
3193
3703
|
const availableBalance = parseFloat(nearAccount.amount) / __pow(10, 24);
|
3704
|
+
console.log("available near balance:", availableBalance);
|
3705
|
+
console.log("available gas token balance:", gasTokenBalance);
|
3706
|
+
const convertTx = yield Promise.all(
|
3707
|
+
transactions2.map((transaction, index) => convertTransactionToTxHex(transaction, index))
|
3708
|
+
);
|
3194
3709
|
if (availableBalance > 0.2) {
|
3195
|
-
|
3710
|
+
const gasTokens = yield nearCall2(
|
3711
|
+
currentConfig.accountContractId,
|
3712
|
+
"list_gas_token",
|
3713
|
+
{ token_ids: [currentConfig.token] }
|
3714
|
+
);
|
3715
|
+
console.log("list_gas_token gas tokens:", gasTokens);
|
3716
|
+
const perTxFee = Math.max(
|
3717
|
+
Number(((_a2 = gasTokens[currentConfig.token]) == null ? void 0 : _a2.per_tx_protocol_fee) || 0),
|
3718
|
+
100
|
3719
|
+
);
|
3720
|
+
console.log("perTxFee:", perTxFee);
|
3721
|
+
const protocolFee = new import_big2.default(perTxFee || "0").mul(convertTx.length).toFixed(0);
|
3722
|
+
console.log("protocolFee:", protocolFee);
|
3723
|
+
if (new import_big2.default(gasTokenBalance).gte(protocolFee)) {
|
3724
|
+
console.log("use near pay gas and enough gas token balance");
|
3725
|
+
return { useNearPayGas: true, gasLimit: protocolFee };
|
3726
|
+
} else {
|
3727
|
+
console.log("use near pay gas and not enough gas token balance");
|
3728
|
+
const transferTx = yield createGasTokenTransfer(accountId, protocolFee);
|
3729
|
+
return recalculateGasWithTransfer(transferTx, convertTx, true, perTxFee.toString());
|
3730
|
+
}
|
3196
3731
|
} else {
|
3197
|
-
|
3198
|
-
|
3199
|
-
|
3200
|
-
|
3201
|
-
|
3202
|
-
|
3203
|
-
|
3204
|
-
|
3205
|
-
|
3206
|
-
type: "FunctionCall",
|
3207
|
-
params: {
|
3208
|
-
methodName: "ft_transfer_call",
|
3209
|
-
args: {
|
3210
|
-
receiver_id: currentConfig.accountContractId,
|
3211
|
-
amount: currentConfig.gasTokenLimit,
|
3212
|
-
msg: "Deposit"
|
3213
|
-
},
|
3214
|
-
gas: new import_big.default(50).mul(__pow(10, 12)).toFixed(0),
|
3215
|
-
deposit: "1"
|
3216
|
-
}
|
3217
|
-
}
|
3218
|
-
]
|
3219
|
-
};
|
3220
|
-
return { transferGasTransaction, useNearPayGas: false };
|
3732
|
+
console.log("near balance is not enough, predict the gas token amount required");
|
3733
|
+
const adjustedGas = yield getPredictedGasAmount(
|
3734
|
+
currentConfig.accountContractId,
|
3735
|
+
currentConfig.token,
|
3736
|
+
convertTx.map((t) => t.txHex)
|
3737
|
+
);
|
3738
|
+
if (new import_big2.default(gasTokenBalance).gte(adjustedGas)) {
|
3739
|
+
console.log("use gas token and gas token balance is enough");
|
3740
|
+
return { useNearPayGas: false, gasLimit: adjustedGas };
|
3221
3741
|
} else {
|
3222
|
-
|
3742
|
+
console.log("use gas token and gas token balance is not enough, need to transfer");
|
3743
|
+
const transferTx = yield createGasTokenTransfer(accountId, adjustedGas);
|
3744
|
+
return recalculateGasWithTransfer(transferTx, convertTx, false);
|
3223
3745
|
}
|
3224
3746
|
}
|
3225
3747
|
});
|
3226
3748
|
}
|
3749
|
+
function convertTransactionToTxHex(transaction, index = 0) {
|
3750
|
+
return __async(this, null, function* () {
|
3751
|
+
const accountId = state.getAccount();
|
3752
|
+
const publicKey = state.getPublicKey();
|
3753
|
+
const publicKeyFormat = import_key_pair.PublicKey.from(publicKey);
|
3754
|
+
const { header } = yield provider.block({
|
3755
|
+
finality: "final"
|
3756
|
+
});
|
3757
|
+
const rawAccessKey = yield provider.query({
|
3758
|
+
request_type: "view_access_key",
|
3759
|
+
account_id: accountId,
|
3760
|
+
public_key: publicKey,
|
3761
|
+
finality: "final"
|
3762
|
+
});
|
3763
|
+
const accessKey = __spreadProps(__spreadValues({}, rawAccessKey), {
|
3764
|
+
nonce: BigInt(rawAccessKey.nonce || 0)
|
3765
|
+
});
|
3766
|
+
const nearNonceFromApi = yield getNearNonce(currentConfig.base_url, accountId);
|
3767
|
+
let nearNonceNumber = accessKey.nonce + BigInt(1);
|
3768
|
+
if (nearNonceFromApi) {
|
3769
|
+
nearNonceNumber = BigInt(nearNonceFromApi) > nearNonceNumber ? BigInt(nearNonceFromApi) : nearNonceNumber;
|
3770
|
+
}
|
3771
|
+
const newActions = transaction.actions.map((action) => {
|
3772
|
+
switch (action.type) {
|
3773
|
+
case "FunctionCall":
|
3774
|
+
return functionCall(
|
3775
|
+
action.params.methodName,
|
3776
|
+
action.params.args,
|
3777
|
+
BigInt(action.params.gas),
|
3778
|
+
BigInt(action.params.deposit)
|
3779
|
+
);
|
3780
|
+
case "Transfer":
|
3781
|
+
return transfer(BigInt(action.params.deposit));
|
3782
|
+
}
|
3783
|
+
}).filter(Boolean);
|
3784
|
+
const _transaction = import_near_api_js2.transactions.createTransaction(
|
3785
|
+
accountId,
|
3786
|
+
publicKeyFormat,
|
3787
|
+
transaction.receiverId,
|
3788
|
+
BigInt(nearNonceNumber) + BigInt(index),
|
3789
|
+
newActions,
|
3790
|
+
(0, import_utils6.baseDecode)(header.hash)
|
3791
|
+
);
|
3792
|
+
const txBytes = (0, import_transaction.encodeTransaction)(_transaction);
|
3793
|
+
const txHex = Array.from(txBytes, (byte) => ("0" + (byte & 255).toString(16)).slice(-2)).join(
|
3794
|
+
""
|
3795
|
+
);
|
3796
|
+
const hash = import_bs58.default.encode(new Uint8Array(import_js_sha256.sha256.array(txBytes)));
|
3797
|
+
return { txBytes, txHex, hash };
|
3798
|
+
});
|
3799
|
+
}
|
3227
3800
|
function initWalletButton(network, wallet2) {
|
3228
3801
|
return __async(this, null, function* () {
|
3229
3802
|
const checkAndSetupWalletButton = () => {
|
@@ -3244,17 +3817,13 @@ var BTCWallet = (_0) => __async(void 0, [_0], function* ({
|
|
3244
3817
|
}
|
3245
3818
|
return wallet;
|
3246
3819
|
});
|
3247
|
-
function
|
3248
|
-
|
3249
|
-
|
3250
|
-
|
3251
|
-
|
3252
|
-
|
3253
|
-
|
3254
|
-
return request(`${url}/v1/receiveTransaction`, {
|
3255
|
-
method: "POST",
|
3256
|
-
body: data
|
3257
|
-
});
|
3820
|
+
function toHex(originalString) {
|
3821
|
+
const charArray = originalString.split("");
|
3822
|
+
const asciiArray = charArray.map((char) => char.charCodeAt(0));
|
3823
|
+
const hexArray = asciiArray.map((code) => code.toString(16));
|
3824
|
+
let hexString = hexArray.join("");
|
3825
|
+
hexString = hexString.replace(/(^0+)/g, "");
|
3826
|
+
return hexString;
|
3258
3827
|
}
|
3259
3828
|
function setupBTCWallet({
|
3260
3829
|
iconUrl = "https://assets.deltatrade.ai/assets/chain/btc.svg",
|
@@ -3283,232 +3852,10 @@ function setupBTCWallet({
|
|
3283
3852
|
});
|
3284
3853
|
return btcWallet;
|
3285
3854
|
}
|
3286
|
-
function toHex(originalString) {
|
3287
|
-
const charArray = originalString.split("");
|
3288
|
-
const asciiArray = charArray.map((char) => char.charCodeAt(0));
|
3289
|
-
const hexArray = asciiArray.map((code) => code.toString(16));
|
3290
|
-
let hexString = hexArray.join("");
|
3291
|
-
hexString = hexString.replace(/(^0+)/g, "");
|
3292
|
-
return hexString;
|
3293
|
-
}
|
3294
|
-
|
3295
|
-
// src/core/btcUtils.ts
|
3296
|
-
var import_big2 = __toESM(require("big.js"), 1);
|
3297
|
-
function getBtcProvider() {
|
3298
|
-
if (typeof window === "undefined" || !window.btcContext) {
|
3299
|
-
throw new Error("BTC Provider is not initialized.");
|
3300
|
-
}
|
3301
|
-
return window.btcContext;
|
3302
|
-
}
|
3303
|
-
function getNetwork() {
|
3304
|
-
return __async(this, null, function* () {
|
3305
|
-
const network = yield getBtcProvider().getNetwork();
|
3306
|
-
console.log("btc network:", network);
|
3307
|
-
return network === "livenet" ? "mainnet" : "testnet";
|
3308
|
-
});
|
3309
|
-
}
|
3310
|
-
function getBtcRpcUrl() {
|
3311
|
-
return __async(this, null, function* () {
|
3312
|
-
const network = yield getNetwork();
|
3313
|
-
return btcRpcUrls[network];
|
3314
|
-
});
|
3315
|
-
}
|
3316
|
-
function getConfig(isDev) {
|
3317
|
-
return __async(this, null, function* () {
|
3318
|
-
const network = yield getNetwork();
|
3319
|
-
return walletConfig[isDev ? "dev" : network];
|
3320
|
-
});
|
3321
|
-
}
|
3322
|
-
function nearCall(contractId, methodName, args) {
|
3323
|
-
return __async(this, null, function* () {
|
3324
|
-
const network = yield getNetwork();
|
3325
|
-
return nearCallFunction(contractId, methodName, args, { network });
|
3326
|
-
});
|
3327
|
-
}
|
3328
|
-
function receiveDepositMsg(_0, _1) {
|
3329
|
-
return __async(this, arguments, function* (baseUrl, {
|
3330
|
-
btcPublicKey,
|
3331
|
-
txHash,
|
3332
|
-
depositType = 1,
|
3333
|
-
postActions,
|
3334
|
-
extraMsg
|
3335
|
-
}) {
|
3336
|
-
const res = yield request(`${baseUrl}/v1/receiveDepositMsg`, {
|
3337
|
-
method: "POST",
|
3338
|
-
body: { btcPublicKey, txHash, depositType, postActions, extraMsg }
|
3339
|
-
});
|
3340
|
-
console.log("receiveDepositMsg resp:", res);
|
3341
|
-
return res;
|
3342
|
-
});
|
3343
|
-
}
|
3344
|
-
function checkTransactionStatus(baseUrl, txHash) {
|
3345
|
-
return __async(this, null, function* () {
|
3346
|
-
const res = yield request(
|
3347
|
-
`${baseUrl}/v1/bridgeFromTx?fromTxHash=${txHash}&fromChainId=1`,
|
3348
|
-
{
|
3349
|
-
timeout: 6e4,
|
3350
|
-
pollingInterval: 5e3,
|
3351
|
-
maxPollingAttempts: 10,
|
3352
|
-
shouldStopPolling: (res2) => res2.result_code === 0
|
3353
|
-
}
|
3354
|
-
);
|
3355
|
-
return res;
|
3356
|
-
});
|
3357
|
-
}
|
3358
|
-
function getBtcGasPrice() {
|
3359
|
-
return __async(this, null, function* () {
|
3360
|
-
const defaultFeeRate = 100;
|
3361
|
-
try {
|
3362
|
-
const btcRpcUrl = yield getBtcRpcUrl();
|
3363
|
-
const res = yield fetch(`${btcRpcUrl}/v1/fees/recommended`).then((res2) => res2.json());
|
3364
|
-
const feeRate = res.fastestFee;
|
3365
|
-
return feeRate || defaultFeeRate;
|
3366
|
-
} catch (error) {
|
3367
|
-
return defaultFeeRate;
|
3368
|
-
}
|
3369
|
-
});
|
3370
|
-
}
|
3371
|
-
function getBtcBalance() {
|
3372
|
-
return __async(this, null, function* () {
|
3373
|
-
const { account } = yield retryOperation(getBtcProvider, (res2) => !!res2.account);
|
3374
|
-
if (!account) {
|
3375
|
-
console.error("BTC Account is not available.");
|
3376
|
-
return { rawBalance: 0, balance: 0, maxSpendableBalance: 0 };
|
3377
|
-
}
|
3378
|
-
const btcRpcUrl = yield getBtcRpcUrl();
|
3379
|
-
const res = yield fetch(`${btcRpcUrl}/address/${account}/utxo`).then((res2) => res2.json());
|
3380
|
-
const rawBalance = res == null ? void 0 : res.reduce((acc, cur) => acc + cur.value, 0);
|
3381
|
-
const balance = rawBalance / __pow(10, 8);
|
3382
|
-
const feeRate = yield getBtcGasPrice();
|
3383
|
-
const maxGasFee = feeRate * 350 / __pow(10, 8);
|
3384
|
-
const availableBalance = Math.max(0, balance - maxGasFee);
|
3385
|
-
return {
|
3386
|
-
rawBalance,
|
3387
|
-
balance,
|
3388
|
-
availableBalance
|
3389
|
-
};
|
3390
|
-
});
|
3391
|
-
}
|
3392
|
-
function sendBitcoin(address, amount, feeRate) {
|
3393
|
-
return __async(this, null, function* () {
|
3394
|
-
const { sendBitcoin: sendBitcoin2 } = getBtcProvider();
|
3395
|
-
const txHash = yield sendBitcoin2(address, amount, { feeRate });
|
3396
|
-
return txHash;
|
3397
|
-
});
|
3398
|
-
}
|
3399
|
-
function estimateDepositAmount(amount, option) {
|
3400
|
-
return __async(this, null, function* () {
|
3401
|
-
const config = yield getConfig((option == null ? void 0 : option.isDev) || false);
|
3402
|
-
const {
|
3403
|
-
deposit_bridge_fee: { fee_min, fee_rate }
|
3404
|
-
} = yield nearCall(
|
3405
|
-
config.bridgeContractId,
|
3406
|
-
"get_config",
|
3407
|
-
{}
|
3408
|
-
);
|
3409
|
-
const fee = Math.max(Number(fee_min), Number(amount) * fee_rate);
|
3410
|
-
return new import_big2.default(amount).minus(fee).toFixed(0);
|
3411
|
-
});
|
3412
|
-
}
|
3413
|
-
function executeBTCDepositAndAction(_0) {
|
3414
|
-
return __async(this, arguments, function* ({
|
3415
|
-
action,
|
3416
|
-
feeRate,
|
3417
|
-
isDev = false
|
3418
|
-
}) {
|
3419
|
-
try {
|
3420
|
-
const { getPublicKey } = getBtcProvider();
|
3421
|
-
const config = yield getConfig(isDev);
|
3422
|
-
const btcPublicKey = yield getPublicKey();
|
3423
|
-
const _action = Object.assign(
|
3424
|
-
{},
|
3425
|
-
__spreadProps(__spreadValues({}, action), {
|
3426
|
-
gas: new import_big2.default(100).mul(__pow(10, 12)).toFixed(0)
|
3427
|
-
})
|
3428
|
-
);
|
3429
|
-
if (!btcPublicKey) {
|
3430
|
-
throw new Error("BTC Public Key is not available.");
|
3431
|
-
}
|
3432
|
-
if (!_action.receiver_id) {
|
3433
|
-
throw new Error("action.receiver_id is required");
|
3434
|
-
}
|
3435
|
-
const amountWithFee = yield estimateDepositAmount(_action.amount, {
|
3436
|
-
isDev
|
3437
|
-
});
|
3438
|
-
_action.amount = amountWithFee;
|
3439
|
-
if (!_action.amount || !new import_big2.default(_action.amount || 0).gt(0)) {
|
3440
|
-
throw new Error("action.amount is required or deposit amount is not enough");
|
3441
|
-
}
|
3442
|
-
const csna = yield nearCall(
|
3443
|
-
config.accountContractId,
|
3444
|
-
"get_chain_signature_near_account_id",
|
3445
|
-
{
|
3446
|
-
btc_public_key: btcPublicKey
|
3447
|
-
}
|
3448
|
-
);
|
3449
|
-
const depositMsg = {
|
3450
|
-
recipient_id: csna,
|
3451
|
-
post_actions: [_action]
|
3452
|
-
};
|
3453
|
-
const storageDepositMsg = {};
|
3454
|
-
const accountInfo = yield nearCall(
|
3455
|
-
config.accountContractId,
|
3456
|
-
"get_account",
|
3457
|
-
{
|
3458
|
-
account_id: csna
|
3459
|
-
}
|
3460
|
-
);
|
3461
|
-
if (!(accountInfo == null ? void 0 : accountInfo.nonce)) {
|
3462
|
-
storageDepositMsg.btc_public_key = btcPublicKey;
|
3463
|
-
}
|
3464
|
-
const registerRes = yield nearCall(action.receiver_id, "storage_balance_of", {
|
3465
|
-
account_id: csna
|
3466
|
-
});
|
3467
|
-
if (!(registerRes == null ? void 0 : registerRes.available)) {
|
3468
|
-
storageDepositMsg.storage_deposit_msg = {
|
3469
|
-
contract_id: action.receiver_id,
|
3470
|
-
deposit: new import_big2.default(0.25).mul(__pow(10, 24)).toFixed(0),
|
3471
|
-
registration_only: true
|
3472
|
-
};
|
3473
|
-
}
|
3474
|
-
if (Object.keys(storageDepositMsg).length > 0) {
|
3475
|
-
depositMsg.extra_msg = JSON.stringify(storageDepositMsg);
|
3476
|
-
}
|
3477
|
-
console.log("get_user_deposit_address params:", { deposit_msg: depositMsg });
|
3478
|
-
const userDepositAddress = yield nearCall(
|
3479
|
-
config.bridgeContractId,
|
3480
|
-
"get_user_deposit_address",
|
3481
|
-
{ deposit_msg: depositMsg }
|
3482
|
-
);
|
3483
|
-
const _feeRate = feeRate || (yield getBtcGasPrice());
|
3484
|
-
console.log("user deposit address:", userDepositAddress);
|
3485
|
-
console.log("deposit amount:", new import_big2.default(action.amount).toNumber());
|
3486
|
-
console.log("receive amount:", new import_big2.default(_action.amount).toNumber());
|
3487
|
-
console.log("fee rate:", _feeRate);
|
3488
|
-
const txHash = yield sendBitcoin(
|
3489
|
-
userDepositAddress,
|
3490
|
-
new import_big2.default(action.amount).toNumber(),
|
3491
|
-
_feeRate
|
3492
|
-
);
|
3493
|
-
yield receiveDepositMsg(config.base_url, {
|
3494
|
-
btcPublicKey,
|
3495
|
-
txHash,
|
3496
|
-
postActions: JSON.stringify(depositMsg.post_actions),
|
3497
|
-
extraMsg: depositMsg.extra_msg
|
3498
|
-
});
|
3499
|
-
const checkTransactionStatusRes = yield checkTransactionStatus(config.base_url, txHash);
|
3500
|
-
console.log("checkTransactionStatus resp:", checkTransactionStatusRes);
|
3501
|
-
return checkTransactionStatusRes.result_code === 0 ? { result: "success" } : { result: "failed", error: checkTransactionStatusRes.result_message };
|
3502
|
-
} catch (error) {
|
3503
|
-
console.error("Error executing Bridge+BurrowSupply:", error);
|
3504
|
-
return { result: "failed", error: error.message };
|
3505
|
-
}
|
3506
|
-
});
|
3507
|
-
}
|
3508
3855
|
|
3509
3856
|
// src/index.ts
|
3510
3857
|
var getVersion = () => {
|
3511
|
-
return "0.3.
|
3858
|
+
return "0.3.12";
|
3512
3859
|
};
|
3513
3860
|
if (typeof window !== "undefined") {
|
3514
3861
|
window.__PARTICLE_BTC_CONNECT_VERSION = getVersion();
|