btc-wallet 0.5.11-beta → 0.5.13-beta
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/config.d.ts +4 -1
- package/dist/core/btcUtils.d.ts +17 -9
- package/dist/index.js +270 -146
- package/dist/index.js.map +2 -2
- package/dist/utils/nearUtils.d.ts +7 -1
- package/dist/utils/request.d.ts +1 -0
- package/esm/index.js +270 -146
- package/esm/index.js.map +2 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
@@ -102,7 +102,7 @@ __export(src_exports, {
|
|
102
102
|
getConfig: () => getConfig,
|
103
103
|
getCsnaAccountId: () => getCsnaAccountId,
|
104
104
|
getDepositAmount: () => getDepositAmount,
|
105
|
-
|
105
|
+
getTokenBalance: () => getTokenBalance,
|
106
106
|
getVersion: () => getVersion,
|
107
107
|
getWithdrawTransaction: () => getWithdrawTransaction,
|
108
108
|
sendBitcoin: () => sendBitcoin,
|
@@ -432,11 +432,11 @@ var MobileWalletConnect = class {
|
|
432
432
|
}
|
433
433
|
static redirectToWallet(walletId) {
|
434
434
|
return __async(this, null, function* () {
|
435
|
-
var _a;
|
436
435
|
if (isMobile()) {
|
437
436
|
const currentUrl = window.location.href;
|
438
437
|
const universalLink = this.getUniversalLink(walletId, currentUrl);
|
439
|
-
|
438
|
+
const showGuideDialog = () => __async(this, null, function* () {
|
439
|
+
var _a;
|
440
440
|
try {
|
441
441
|
yield (_a = navigator.clipboard) == null ? void 0 : _a.writeText(currentUrl);
|
442
442
|
} catch (error) {
|
@@ -454,9 +454,23 @@ var MobileWalletConnect = class {
|
|
454
454
|
`,
|
455
455
|
dangerouslyUseHTML: true
|
456
456
|
});
|
457
|
+
});
|
458
|
+
if (!universalLink) {
|
459
|
+
yield showGuideDialog();
|
457
460
|
return false;
|
458
461
|
}
|
462
|
+
const openWallet = () => {
|
463
|
+
const iframe = document.createElement("iframe");
|
464
|
+
iframe.style.display = "none";
|
465
|
+
iframe.src = universalLink;
|
466
|
+
document.body.appendChild(iframe);
|
467
|
+
setTimeout(() => __async(this, null, function* () {
|
468
|
+
document.body.removeChild(iframe);
|
469
|
+
yield showGuideDialog();
|
470
|
+
}), 2e3);
|
471
|
+
};
|
459
472
|
window.location.href = universalLink;
|
473
|
+
setTimeout(openWallet, 100);
|
460
474
|
return true;
|
461
475
|
}
|
462
476
|
return false;
|
@@ -2870,7 +2884,10 @@ var import_js_sha256 = require("js-sha256");
|
|
2870
2884
|
var walletConfig = {
|
2871
2885
|
dev: {
|
2872
2886
|
base_url: "https://api.dev.satoshibridge.top",
|
2873
|
-
|
2887
|
+
btcToken: "nbtc-dev.testnet",
|
2888
|
+
btcTokenDecimals: 8,
|
2889
|
+
nearToken: "wrap.testnet",
|
2890
|
+
nearTokenDecimals: 24,
|
2874
2891
|
accountContractId: "acc-dev.testnet",
|
2875
2892
|
bridgeContractId: "brg-dev.testnet",
|
2876
2893
|
walletUrl: "https://wallet-dev.satoshibridge.top",
|
@@ -2878,7 +2895,10 @@ var walletConfig = {
|
|
2878
2895
|
},
|
2879
2896
|
testnet: {
|
2880
2897
|
base_url: "https://api.testnet.satoshibridge.top",
|
2881
|
-
|
2898
|
+
btcToken: "nbtc2-nsp.testnet",
|
2899
|
+
btcTokenDecimals: 8,
|
2900
|
+
nearToken: "wrap.testnet",
|
2901
|
+
nearTokenDecimals: 24,
|
2882
2902
|
accountContractId: "acc2-nsp.testnet",
|
2883
2903
|
bridgeContractId: "brg2-nsp.testnet",
|
2884
2904
|
walletUrl: "https://wallet-test.satoshibridge.top",
|
@@ -2886,7 +2906,10 @@ var walletConfig = {
|
|
2886
2906
|
},
|
2887
2907
|
private_mainnet: {
|
2888
2908
|
base_url: "https://api.stg.satoshibridge.top",
|
2889
|
-
|
2909
|
+
btcToken: "nbtc.toalice.near",
|
2910
|
+
btcTokenDecimals: 8,
|
2911
|
+
nearToken: "wrap.near",
|
2912
|
+
nearTokenDecimals: 24,
|
2890
2913
|
accountContractId: "acc.toalice.near",
|
2891
2914
|
bridgeContractId: "brg.toalice.near",
|
2892
2915
|
walletUrl: "https://wallet-stg.satoshibridge.top",
|
@@ -2894,7 +2917,10 @@ var walletConfig = {
|
|
2894
2917
|
},
|
2895
2918
|
mainnet: {
|
2896
2919
|
base_url: "https://api.satos.network",
|
2897
|
-
|
2920
|
+
btcToken: "nbtc.bridge.near",
|
2921
|
+
btcTokenDecimals: 8,
|
2922
|
+
nearToken: "wrap.near",
|
2923
|
+
nearTokenDecimals: 24,
|
2898
2924
|
accountContractId: "acc.ref-labs.near",
|
2899
2925
|
bridgeContractId: "btc-connector.bridge.near",
|
2900
2926
|
walletUrl: "https://wallet.satoshibridge.top",
|
@@ -2920,69 +2946,24 @@ var import_big = __toESM(require("big.js"), 1);
|
|
2920
2946
|
|
2921
2947
|
// src/utils/nearUtils.ts
|
2922
2948
|
var import_near_api_js = require("near-api-js");
|
2923
|
-
function nearCallFunction(contractId, methodName, args, options) {
|
2924
|
-
return __async(this, null, function* () {
|
2925
|
-
const nearProvider = (options == null ? void 0 : options.provider) || new import_near_api_js.providers.FailoverRpcProvider(
|
2926
|
-
nearRpcUrls[options == null ? void 0 : options.network].map(
|
2927
|
-
(url) => new import_near_api_js.providers.JsonRpcProvider({ url })
|
2928
|
-
)
|
2929
|
-
);
|
2930
|
-
const res = yield nearProvider.query({
|
2931
|
-
request_type: "call_function",
|
2932
|
-
account_id: contractId,
|
2933
|
-
method_name: methodName,
|
2934
|
-
args_base64: Buffer.from(JSON.stringify(args)).toString("base64"),
|
2935
|
-
finality: "final"
|
2936
|
-
});
|
2937
|
-
return JSON.parse(Buffer.from(res.result).toString());
|
2938
|
-
});
|
2939
|
-
}
|
2940
|
-
function pollTransactionStatuses(network, hashes) {
|
2941
|
-
return __async(this, null, function* () {
|
2942
|
-
const provider = new import_near_api_js.providers.FailoverRpcProvider(
|
2943
|
-
Object.values(nearRpcUrls[network]).map(
|
2944
|
-
(url) => new import_near_api_js.providers.JsonRpcProvider({ url })
|
2945
|
-
)
|
2946
|
-
);
|
2947
|
-
const maxAttempts = 30;
|
2948
|
-
let currentAttempt = 0;
|
2949
|
-
const pendingHashes = new Set(hashes);
|
2950
|
-
const results = /* @__PURE__ */ new Map();
|
2951
|
-
while (pendingHashes.size > 0 && currentAttempt < maxAttempts) {
|
2952
|
-
currentAttempt++;
|
2953
|
-
const promises = Array.from(pendingHashes).map((hash) => __async(this, null, function* () {
|
2954
|
-
try {
|
2955
|
-
const result2 = yield provider.txStatus(hash, "unused", "FINAL");
|
2956
|
-
if (result2 && result2.status) {
|
2957
|
-
console.log(`Transaction ${hash} result:`, result2);
|
2958
|
-
results.set(hash, result2);
|
2959
|
-
pendingHashes.delete(hash);
|
2960
|
-
}
|
2961
|
-
} catch (error) {
|
2962
|
-
console.error(`Failed to fetch transaction status for ${hash}: ${error.message}`);
|
2963
|
-
}
|
2964
|
-
}));
|
2965
|
-
yield Promise.all(promises);
|
2966
|
-
if (pendingHashes.size > 0) {
|
2967
|
-
if (currentAttempt === maxAttempts) {
|
2968
|
-
throw new Error(
|
2969
|
-
`Transactions not found after max attempts: ${Array.from(pendingHashes).join(", ")}`
|
2970
|
-
);
|
2971
|
-
}
|
2972
|
-
console.log(
|
2973
|
-
`Waiting for ${pendingHashes.size} transactions, retrying ${maxAttempts - currentAttempt} more times`
|
2974
|
-
);
|
2975
|
-
yield delay(1e4);
|
2976
|
-
}
|
2977
|
-
}
|
2978
|
-
const result = hashes.map((hash) => results.get(hash)).filter(Boolean);
|
2979
|
-
return result;
|
2980
|
-
});
|
2981
|
-
}
|
2982
2949
|
|
2983
2950
|
// src/utils/request.ts
|
2984
2951
|
var cache = /* @__PURE__ */ new Map();
|
2985
2952
|
var defaultCacheTimeout = 3e3;
|
2953
|
+
function withCache(key, fetcher, timeout = defaultCacheTimeout) {
|
2954
|
+
const cached = cache.get(key);
|
2955
|
+
const isCacheValid = cached && Date.now() - cached.timestamp < timeout;
|
2956
|
+
if (isCacheValid) {
|
2957
|
+
return Promise.resolve(cached.data);
|
2958
|
+
}
|
2959
|
+
return fetcher().then((data) => {
|
2960
|
+
cache.set(key, { timestamp: Date.now(), data });
|
2961
|
+
setTimeout(() => {
|
2962
|
+
cache.delete(key);
|
2963
|
+
}, timeout);
|
2964
|
+
return data;
|
2965
|
+
});
|
2966
|
+
}
|
2986
2967
|
function request(url, options) {
|
2987
2968
|
return __async(this, null, function* () {
|
2988
2969
|
var _a;
|
@@ -3024,13 +3005,7 @@ function request(url, options) {
|
|
3024
3005
|
if (options.shouldStopPolling(data)) {
|
3025
3006
|
return data;
|
3026
3007
|
}
|
3027
|
-
|
3028
|
-
yield new Promise((resolve) => setTimeout(resolve, options.pollingInterval));
|
3029
|
-
return request(url, __spreadProps(__spreadValues({}, options), {
|
3030
|
-
maxPollingAttempts: options.maxPollingAttempts - 1
|
3031
|
-
}));
|
3032
|
-
}
|
3033
|
-
throw new Error("Polling failed: maximum attempts reached without meeting the condition");
|
3008
|
+
throw new Error("Polling should continue");
|
3034
3009
|
}
|
3035
3010
|
if (cacheKey) {
|
3036
3011
|
cache.set(cacheKey, { timestamp: Date.now(), data });
|
@@ -3040,6 +3015,7 @@ function request(url, options) {
|
|
3040
3015
|
}
|
3041
3016
|
return data;
|
3042
3017
|
} catch (err) {
|
3018
|
+
console.error(err);
|
3043
3019
|
if (retryCount > 0) {
|
3044
3020
|
console.log(`Retrying... attempts left: ${retryCount}`);
|
3045
3021
|
return request(url, __spreadProps(__spreadValues({}, options), { retryCount: retryCount - 1 }));
|
@@ -3053,8 +3029,85 @@ function request(url, options) {
|
|
3053
3029
|
}));
|
3054
3030
|
}
|
3055
3031
|
}
|
3056
|
-
|
3032
|
+
return Promise.reject(err);
|
3033
|
+
}
|
3034
|
+
});
|
3035
|
+
}
|
3036
|
+
|
3037
|
+
// src/utils/nearUtils.ts
|
3038
|
+
function getNearProvider(option) {
|
3039
|
+
return option.provider || new import_near_api_js.providers.FailoverRpcProvider(
|
3040
|
+
nearRpcUrls[option == null ? void 0 : option.network].map(
|
3041
|
+
(url) => new import_near_api_js.providers.JsonRpcProvider({ url })
|
3042
|
+
)
|
3043
|
+
);
|
3044
|
+
}
|
3045
|
+
function nearCallFunction(_0, _1, _2) {
|
3046
|
+
return __async(this, arguments, function* (contractId, methodName, args, options = {}) {
|
3047
|
+
if (!options.skipCache) {
|
3048
|
+
const cacheKey = `near:${contractId}:${methodName}:${args ? JSON.stringify(args) : ""}`;
|
3049
|
+
return withCache(
|
3050
|
+
cacheKey,
|
3051
|
+
() => executeNearCall(contractId, methodName, args, options),
|
3052
|
+
options.cacheTimeout
|
3053
|
+
);
|
3054
|
+
}
|
3055
|
+
return executeNearCall(contractId, methodName, args, options);
|
3056
|
+
});
|
3057
|
+
}
|
3058
|
+
function executeNearCall(contractId, methodName, args, options) {
|
3059
|
+
return __async(this, null, function* () {
|
3060
|
+
const nearProvider = getNearProvider(options);
|
3061
|
+
const res = yield nearProvider.query({
|
3062
|
+
request_type: "call_function",
|
3063
|
+
account_id: contractId,
|
3064
|
+
method_name: methodName,
|
3065
|
+
args_base64: Buffer.from(JSON.stringify(args)).toString("base64"),
|
3066
|
+
finality: "final"
|
3067
|
+
});
|
3068
|
+
return JSON.parse(Buffer.from(res.result).toString());
|
3069
|
+
});
|
3070
|
+
}
|
3071
|
+
function pollTransactionStatuses(network, hashes) {
|
3072
|
+
return __async(this, null, function* () {
|
3073
|
+
const provider = new import_near_api_js.providers.FailoverRpcProvider(
|
3074
|
+
Object.values(nearRpcUrls[network]).map(
|
3075
|
+
(url) => new import_near_api_js.providers.JsonRpcProvider({ url })
|
3076
|
+
)
|
3077
|
+
);
|
3078
|
+
const maxAttempts = 30;
|
3079
|
+
let currentAttempt = 0;
|
3080
|
+
const pendingHashes = new Set(hashes);
|
3081
|
+
const results = /* @__PURE__ */ new Map();
|
3082
|
+
while (pendingHashes.size > 0 && currentAttempt < maxAttempts) {
|
3083
|
+
currentAttempt++;
|
3084
|
+
const promises = Array.from(pendingHashes).map((hash) => __async(this, null, function* () {
|
3085
|
+
try {
|
3086
|
+
const result2 = yield provider.txStatus(hash, "unused", "FINAL");
|
3087
|
+
if (result2 && result2.status) {
|
3088
|
+
console.log(`Transaction ${hash} result:`, result2);
|
3089
|
+
results.set(hash, result2);
|
3090
|
+
pendingHashes.delete(hash);
|
3091
|
+
}
|
3092
|
+
} catch (error) {
|
3093
|
+
console.error(`Failed to fetch transaction status for ${hash}: ${error.message}`);
|
3094
|
+
}
|
3095
|
+
}));
|
3096
|
+
yield Promise.all(promises);
|
3097
|
+
if (pendingHashes.size > 0) {
|
3098
|
+
if (currentAttempt === maxAttempts) {
|
3099
|
+
throw new Error(
|
3100
|
+
`Transactions not found after max attempts: ${Array.from(pendingHashes).join(", ")}`
|
3101
|
+
);
|
3102
|
+
}
|
3103
|
+
console.log(
|
3104
|
+
`Waiting for ${pendingHashes.size} transactions, retrying ${maxAttempts - currentAttempt} more times`
|
3105
|
+
);
|
3106
|
+
yield delay(1e4);
|
3107
|
+
}
|
3057
3108
|
}
|
3109
|
+
const result = hashes.map((hash) => results.get(hash)).filter(Boolean);
|
3110
|
+
return result;
|
3058
3111
|
});
|
3059
3112
|
}
|
3060
3113
|
|
@@ -3211,9 +3264,10 @@ function nearCall(contractId, methodName, args) {
|
|
3211
3264
|
return nearCallFunction(contractId, methodName, args, { network });
|
3212
3265
|
});
|
3213
3266
|
}
|
3214
|
-
function getAccountInfo(
|
3215
|
-
return __async(this,
|
3216
|
-
const
|
3267
|
+
function getAccountInfo(_0) {
|
3268
|
+
return __async(this, arguments, function* ({ csna, env }) {
|
3269
|
+
const config = yield getConfig(env);
|
3270
|
+
const accountInfo = yield nearCall(config.accountContractId, "get_account", {
|
3217
3271
|
account_id: csna
|
3218
3272
|
}).catch((error) => {
|
3219
3273
|
return void 0;
|
@@ -3222,16 +3276,46 @@ function getAccountInfo(csna, accountContractId) {
|
|
3222
3276
|
return accountInfo;
|
3223
3277
|
});
|
3224
3278
|
}
|
3225
|
-
function
|
3279
|
+
function getTokenBalance(_0) {
|
3280
|
+
return __async(this, arguments, function* ({
|
3281
|
+
csna,
|
3282
|
+
tokenId,
|
3283
|
+
env
|
3284
|
+
}) {
|
3285
|
+
const network = yield getNetwork();
|
3286
|
+
const config = yield getConfig(env);
|
3287
|
+
const nearProvider = getNearProvider({ network });
|
3288
|
+
try {
|
3289
|
+
if (tokenId === config.nearToken) {
|
3290
|
+
const nearAccount = yield nearProvider.query({
|
3291
|
+
request_type: "view_account",
|
3292
|
+
account_id: csna,
|
3293
|
+
finality: "final"
|
3294
|
+
});
|
3295
|
+
const balance = parseFloat(nearAccount.amount) / __pow(10, config.nearTokenDecimals);
|
3296
|
+
return { balance, rawBalance: nearAccount.amount };
|
3297
|
+
} else {
|
3298
|
+
const res = yield nearCall(tokenId, "ft_balance_of", { account_id: csna });
|
3299
|
+
const decimals = tokenId === config.btcToken ? config.btcTokenDecimals : (yield nearCall(tokenId, "ft_metadata", {})).decimals;
|
3300
|
+
const balance = parseFloat(res) / __pow(10, decimals);
|
3301
|
+
return { balance, rawBalance: res };
|
3302
|
+
}
|
3303
|
+
} catch (error) {
|
3304
|
+
console.error("getTokenBalance error:", error);
|
3305
|
+
return { balance: 0, rawBalance: "0" };
|
3306
|
+
}
|
3307
|
+
});
|
3308
|
+
}
|
3309
|
+
function checkGasTokenBalance(csna, minAmount, env) {
|
3226
3310
|
return __async(this, null, function* () {
|
3227
|
-
const
|
3228
|
-
|
3229
|
-
|
3311
|
+
const config = yield getConfig(env);
|
3312
|
+
const { rawBalance } = yield getTokenBalance({ csna, tokenId: config.btcToken, env });
|
3313
|
+
console.log("gas token balance:", rawBalance);
|
3314
|
+
if (new import_big.default(rawBalance).lt(minAmount)) {
|
3230
3315
|
yield Dialog.confirm({
|
3231
3316
|
title: "Gas token balance is insufficient",
|
3232
3317
|
message: "Please deposit gas token to continue, will open bridge website."
|
3233
3318
|
});
|
3234
|
-
const config = yield getConfig(env);
|
3235
3319
|
window.open(config.bridgeUrl, "_blank");
|
3236
3320
|
throw new Error("Gas token balance is insufficient");
|
3237
3321
|
}
|
@@ -3312,18 +3396,6 @@ function getBtcBalance() {
|
|
3312
3396
|
};
|
3313
3397
|
});
|
3314
3398
|
}
|
3315
|
-
function getNBTCBalance(address, env) {
|
3316
|
-
return __async(this, null, function* () {
|
3317
|
-
const config = yield getConfig(env || "mainnet");
|
3318
|
-
const rawBalance = yield nearCall(config.token, "ft_balance_of", {
|
3319
|
-
account_id: address
|
3320
|
-
});
|
3321
|
-
const balance = new import_big.default(rawBalance).div(__pow(10, 8)).round(8, import_big.default.roundDown).toNumber();
|
3322
|
-
const rawAvailableBalance = new import_big.default(rawBalance).minus(1e3).toNumber();
|
3323
|
-
const availableBalance = new import_big.default(rawAvailableBalance).div(__pow(10, 8)).round(8, import_big.default.roundDown).toNumber();
|
3324
|
-
return { balance, availableBalance, rawBalance, rawAvailableBalance };
|
3325
|
-
});
|
3326
|
-
}
|
3327
3399
|
function sendBitcoin(address, amount, feeRate) {
|
3328
3400
|
return __async(this, null, function* () {
|
3329
3401
|
const { sendBitcoin: sendBitcoin2 } = getBtcProvider();
|
@@ -3343,7 +3415,7 @@ function getDepositAmount(amount, option) {
|
|
3343
3415
|
const _newAccountMinDepositAmount = (_a = option == null ? void 0 : option.newAccountMinDepositAmount) != null ? _a : true;
|
3344
3416
|
const config = yield getConfig(env);
|
3345
3417
|
const csna = yield getCsnaAccountId(env);
|
3346
|
-
const accountInfo = yield getAccountInfo(csna,
|
3418
|
+
const accountInfo = yield getAccountInfo({ csna, env });
|
3347
3419
|
const debtAction = yield checkGasTokenDebt(accountInfo, env, false);
|
3348
3420
|
const repayAmount = (debtAction == null ? void 0 : debtAction.amount) || 0;
|
3349
3421
|
const {
|
@@ -3422,7 +3494,7 @@ function executeBTCDepositAndAction(_0) {
|
|
3422
3494
|
env,
|
3423
3495
|
newAccountMinDepositAmount
|
3424
3496
|
});
|
3425
|
-
const accountInfo = yield getAccountInfo(csna,
|
3497
|
+
const accountInfo = yield getAccountInfo({ csna, env });
|
3426
3498
|
const newActions = [];
|
3427
3499
|
const debtAction = yield checkGasTokenDebt(accountInfo, env, false);
|
3428
3500
|
if (debtAction) {
|
@@ -3436,12 +3508,12 @@ function executeBTCDepositAndAction(_0) {
|
|
3436
3508
|
}));
|
3437
3509
|
}
|
3438
3510
|
const storageDepositMsg = {};
|
3439
|
-
const registerRes = yield nearCall((action == null ? void 0 : action.receiver_id) || config.
|
3511
|
+
const registerRes = yield nearCall((action == null ? void 0 : action.receiver_id) || config.btcToken, "storage_balance_of", {
|
3440
3512
|
account_id: csna
|
3441
3513
|
});
|
3442
3514
|
if (!(registerRes == null ? void 0 : registerRes.available)) {
|
3443
3515
|
storageDepositMsg.storage_deposit_msg = {
|
3444
|
-
contract_id: (action == null ? void 0 : action.receiver_id) || config.
|
3516
|
+
contract_id: (action == null ? void 0 : action.receiver_id) || config.btcToken,
|
3445
3517
|
deposit: registerDeposit || NEAR_STORAGE_DEPOSIT_AMOUNT,
|
3446
3518
|
registration_only: true
|
3447
3519
|
};
|
@@ -3536,7 +3608,7 @@ function getWithdrawTransaction(_0) {
|
|
3536
3608
|
env = "mainnet"
|
3537
3609
|
}) {
|
3538
3610
|
const provider = getBtcProvider();
|
3539
|
-
const btcAddress =
|
3611
|
+
const btcAddress = provider.account;
|
3540
3612
|
const config = yield getConfig(env);
|
3541
3613
|
const brgConfig = yield nearCall(config.bridgeContractId, "get_config", {});
|
3542
3614
|
if (brgConfig.min_withdraw_amount) {
|
@@ -3560,7 +3632,7 @@ function getWithdrawTransaction(_0) {
|
|
3560
3632
|
};
|
3561
3633
|
});
|
3562
3634
|
const _feeRate = feeRate || (yield getBtcGasPrice());
|
3563
|
-
|
3635
|
+
let { inputs, outputs, fee } = (0, import_coinselect.default)(
|
3564
3636
|
utxos,
|
3565
3637
|
[{ address: btcAddress, value: Number(amount) }],
|
3566
3638
|
Math.ceil(_feeRate)
|
@@ -3569,32 +3641,61 @@ function getWithdrawTransaction(_0) {
|
|
3569
3641
|
throw new Error("The network is busy, please try again later.");
|
3570
3642
|
}
|
3571
3643
|
const maxBtcFee = Number(brgConfig.max_btc_gas_fee);
|
3572
|
-
const
|
3573
|
-
const
|
3574
|
-
if (
|
3644
|
+
const transactionFee = fee;
|
3645
|
+
const changeAddress = brgConfig.change_address;
|
3646
|
+
if (transactionFee > maxBtcFee) {
|
3575
3647
|
throw new Error("Gas exceeds maximum value");
|
3576
3648
|
}
|
3577
|
-
let
|
3649
|
+
let recipientOutput, changeOutput;
|
3578
3650
|
for (let i = 0; i < outputs.length; i++) {
|
3579
3651
|
const output = outputs[i];
|
3580
3652
|
if (output.value.toString() === amount.toString()) {
|
3581
|
-
|
3653
|
+
recipientOutput = output;
|
3582
3654
|
} else {
|
3583
|
-
|
3655
|
+
changeOutput = output;
|
3584
3656
|
}
|
3585
3657
|
if (!output.address) {
|
3586
|
-
output.address =
|
3658
|
+
output.address = changeAddress;
|
3587
3659
|
}
|
3588
3660
|
}
|
3589
|
-
|
3590
|
-
if (
|
3591
|
-
|
3661
|
+
recipientOutput.value = new import_big.default(recipientOutput.value).minus(transactionFee).minus(withdrawFee).toNumber();
|
3662
|
+
if (changeOutput) {
|
3663
|
+
changeOutput.value = new import_big.default(changeOutput.value).plus(transactionFee).plus(withdrawFee).toNumber();
|
3664
|
+
const remainingInputs = [...inputs];
|
3665
|
+
let smallestInput = Math.min.apply(
|
3666
|
+
null,
|
3667
|
+
remainingInputs.map((input) => input.value)
|
3668
|
+
);
|
3669
|
+
let remainingChangeAmount = changeOutput.value;
|
3670
|
+
while (remainingChangeAmount >= smallestInput && smallestInput > 0 && remainingInputs.length > 0) {
|
3671
|
+
remainingChangeAmount -= smallestInput;
|
3672
|
+
changeOutput.value = remainingChangeAmount;
|
3673
|
+
const smallestInputIndex = remainingInputs.findIndex(
|
3674
|
+
(input) => input.value === smallestInput
|
3675
|
+
);
|
3676
|
+
if (smallestInputIndex > -1) {
|
3677
|
+
remainingInputs.splice(smallestInputIndex, 1);
|
3678
|
+
}
|
3679
|
+
smallestInput = Math.min.apply(
|
3680
|
+
null,
|
3681
|
+
remainingInputs.map((input) => input.value)
|
3682
|
+
);
|
3683
|
+
}
|
3684
|
+
const minChangeAmount = Number(brgConfig.min_change_amount);
|
3685
|
+
let additionalFee = 0;
|
3686
|
+
if (changeOutput.value === 0) {
|
3687
|
+
outputs = outputs.filter((item) => item.value !== 0);
|
3688
|
+
} else if (changeOutput.value < minChangeAmount) {
|
3689
|
+
additionalFee = minChangeAmount - changeOutput.value;
|
3690
|
+
recipientOutput.value -= additionalFee;
|
3691
|
+
changeOutput.value = minChangeAmount;
|
3692
|
+
}
|
3592
3693
|
} else {
|
3593
|
-
|
3594
|
-
address:
|
3595
|
-
value: new import_big.default(
|
3694
|
+
changeOutput = {
|
3695
|
+
address: changeAddress,
|
3696
|
+
value: new import_big.default(transactionFee).plus(withdrawFee).toNumber()
|
3596
3697
|
};
|
3597
|
-
outputs.push(
|
3698
|
+
outputs.push(changeOutput);
|
3598
3699
|
}
|
3599
3700
|
const insufficientOutput = outputs.some((item) => item.value < 0);
|
3600
3701
|
if (insufficientOutput) {
|
@@ -3602,7 +3703,7 @@ function getWithdrawTransaction(_0) {
|
|
3602
3703
|
}
|
3603
3704
|
const inputSum = inputs.reduce((sum, cur) => sum + Number(cur.value), 0);
|
3604
3705
|
const outputSum = outputs.reduce((sum, cur) => sum + Number(cur.value), 0);
|
3605
|
-
if (
|
3706
|
+
if (transactionFee + outputSum !== inputSum) {
|
3606
3707
|
throw new Error("compute error");
|
3607
3708
|
}
|
3608
3709
|
const network = yield getNetwork();
|
@@ -3647,7 +3748,7 @@ function getWithdrawTransaction(_0) {
|
|
3647
3748
|
};
|
3648
3749
|
const csna = yield getCsnaAccountId(env);
|
3649
3750
|
const transaction = {
|
3650
|
-
receiverId: config.
|
3751
|
+
receiverId: config.btcToken,
|
3651
3752
|
signerId: csna,
|
3652
3753
|
actions: [
|
3653
3754
|
{
|
@@ -4191,20 +4292,16 @@ var BTCWallet = (_0) => __async(void 0, [_0], function* ({
|
|
4191
4292
|
throw new Error("Wallet state is invalid, please reconnect your wallet.");
|
4192
4293
|
}
|
4193
4294
|
const btcContext = window.btcContext;
|
4194
|
-
const
|
4195
|
-
const accountInfo = yield getAccountInfo(
|
4295
|
+
const csna = state.getAccount();
|
4296
|
+
const accountInfo = yield getAccountInfo({ csna, env });
|
4196
4297
|
yield checkGasTokenDebt(accountInfo, env, true);
|
4197
4298
|
const trans = [...params.transactions];
|
4198
4299
|
console.log("signAndSendTransactions raw trans:", trans);
|
4199
|
-
const
|
4200
|
-
const { transferGasTransaction, useNearPayGas, gasLimit } = yield calculateGasStrategy(
|
4201
|
-
gasTokenBalance,
|
4202
|
-
trans
|
4203
|
-
);
|
4300
|
+
const { transferGasTransaction, useNearPayGas, gasLimit } = yield calculateGasStrategy(trans);
|
4204
4301
|
console.log("transferGasTransaction:", transferGasTransaction);
|
4205
4302
|
console.log("useNearPayGas:", useNearPayGas);
|
4206
4303
|
console.log("gasLimit:", gasLimit);
|
4207
|
-
yield checkGasTokenBalance(
|
4304
|
+
yield checkGasTokenBalance(csna, gasLimit, env);
|
4208
4305
|
if (transferGasTransaction) {
|
4209
4306
|
trans.unshift(transferGasTransaction);
|
4210
4307
|
}
|
@@ -4212,14 +4309,14 @@ var BTCWallet = (_0) => __async(void 0, [_0], function* ({
|
|
4212
4309
|
const newTrans = yield Promise.all(
|
4213
4310
|
trans.map((transaction, index) => convertTransactionToTxHex(transaction, index))
|
4214
4311
|
);
|
4215
|
-
const nonceFromApi = yield getNonce(currentConfig.base_url,
|
4312
|
+
const nonceFromApi = yield getNonce(currentConfig.base_url, csna);
|
4216
4313
|
const nonceFromContract = (accountInfo == null ? void 0 : accountInfo.nonce) || 0;
|
4217
4314
|
const nonce = Number(nonceFromApi) > Number(nonceFromContract) ? String(nonceFromApi) : String(nonceFromContract);
|
4218
4315
|
const intention = {
|
4219
4316
|
chain_id: "397",
|
4220
|
-
csna
|
4317
|
+
csna,
|
4221
4318
|
near_transactions: newTrans.map((t) => t.txHex),
|
4222
|
-
gas_token: currentConfig.
|
4319
|
+
gas_token: currentConfig.btcToken,
|
4223
4320
|
gas_limit: gasLimit,
|
4224
4321
|
use_near_pay_gas: useNearPayGas,
|
4225
4322
|
nonce
|
@@ -4232,7 +4329,7 @@ var BTCWallet = (_0) => __async(void 0, [_0], function* ({
|
|
4232
4329
|
data: toHex(strIntention)
|
4233
4330
|
});
|
4234
4331
|
yield checkBtcTransactionStatus(currentConfig.base_url, signature);
|
4235
|
-
const hash = newTrans.map((t) => t.hash);
|
4332
|
+
const hash = newTrans.slice(1).map((t) => t.hash);
|
4236
4333
|
console.log("txHash:", hash);
|
4237
4334
|
const result = yield pollTransactionStatuses(options.network.networkId, hash);
|
4238
4335
|
return result;
|
@@ -4240,12 +4337,9 @@ var BTCWallet = (_0) => __async(void 0, [_0], function* ({
|
|
4240
4337
|
}
|
4241
4338
|
function calculateGasLimit(params) {
|
4242
4339
|
return __async(this, null, function* () {
|
4243
|
-
const accountId = state.getAccount();
|
4244
|
-
const accountInfo = yield getAccountInfo(accountId, currentConfig.accountContractId);
|
4245
4340
|
const trans = [...params.transactions];
|
4246
4341
|
console.log("raw trans:", trans);
|
4247
|
-
const
|
4248
|
-
const { gasLimit } = yield calculateGasStrategy(gasTokenBalance, trans);
|
4342
|
+
const { gasLimit } = yield calculateGasStrategy(trans);
|
4249
4343
|
return gasLimit;
|
4250
4344
|
});
|
4251
4345
|
}
|
@@ -4253,7 +4347,7 @@ var BTCWallet = (_0) => __async(void 0, [_0], function* ({
|
|
4253
4347
|
return __async(this, null, function* () {
|
4254
4348
|
return {
|
4255
4349
|
signerId: accountId,
|
4256
|
-
receiverId: currentConfig.
|
4350
|
+
receiverId: currentConfig.btcToken,
|
4257
4351
|
actions: [
|
4258
4352
|
{
|
4259
4353
|
type: "FunctionCall",
|
@@ -4281,7 +4375,7 @@ var BTCWallet = (_0) => __async(void 0, [_0], function* ({
|
|
4281
4375
|
} else {
|
4282
4376
|
newGasLimit = yield getPredictedGasAmount(
|
4283
4377
|
currentConfig.accountContractId,
|
4284
|
-
currentConfig.
|
4378
|
+
currentConfig.btcToken,
|
4285
4379
|
[transferTxHex, ...transactions2.map((t) => t.txHex)]
|
4286
4380
|
);
|
4287
4381
|
}
|
@@ -4302,31 +4396,61 @@ var BTCWallet = (_0) => __async(void 0, [_0], function* ({
|
|
4302
4396
|
return gasAmount.toString();
|
4303
4397
|
});
|
4304
4398
|
}
|
4305
|
-
function calculateGasStrategy(
|
4399
|
+
function calculateGasStrategy(transactions2) {
|
4306
4400
|
return __async(this, null, function* () {
|
4307
4401
|
var _a;
|
4308
4402
|
const accountId = state.getAccount();
|
4309
|
-
const
|
4310
|
-
|
4311
|
-
|
4312
|
-
|
4403
|
+
const accountInfo = yield getAccountInfo({ csna: accountId, env });
|
4404
|
+
const gasTokenBalance = (accountInfo == null ? void 0 : accountInfo.gas_token[currentConfig.btcToken]) || "0";
|
4405
|
+
const { balance: nearBalance } = yield getTokenBalance({
|
4406
|
+
csna: accountId,
|
4407
|
+
tokenId: currentConfig.nearToken,
|
4408
|
+
env
|
4313
4409
|
});
|
4314
|
-
const
|
4315
|
-
|
4410
|
+
const { balance: btcBalance } = yield getTokenBalance({
|
4411
|
+
csna: accountId,
|
4412
|
+
tokenId: currentConfig.btcToken,
|
4413
|
+
env
|
4414
|
+
});
|
4415
|
+
const transferAmount = transactions2.reduce(
|
4416
|
+
(acc, tx) => {
|
4417
|
+
tx.actions.forEach((action) => {
|
4418
|
+
if (action.params.deposit) {
|
4419
|
+
const amount = Number(action.params.deposit) / __pow(10, currentConfig.nearTokenDecimals);
|
4420
|
+
console.log("near deposit amount:", amount);
|
4421
|
+
acc.near = acc.near.plus(amount);
|
4422
|
+
}
|
4423
|
+
if (tx.receiverId === currentConfig.btcToken && ["ft_transfer_call", "ft_transfer"].includes(action.params.methodName)) {
|
4424
|
+
const amount = Number(action.params.args.amount) / __pow(10, currentConfig.btcTokenDecimals);
|
4425
|
+
console.log("btc transfer amount:", amount);
|
4426
|
+
acc.btc = acc.btc.plus(amount);
|
4427
|
+
}
|
4428
|
+
});
|
4429
|
+
return acc;
|
4430
|
+
},
|
4431
|
+
{ near: new import_big2.default(0), btc: new import_big2.default(0) }
|
4432
|
+
);
|
4433
|
+
const nearAvailableBalance = new import_big2.default(nearBalance).minus(transferAmount.near).toNumber();
|
4434
|
+
const btcAvailableBalance = new import_big2.default(btcBalance).minus(transferAmount.btc).toNumber();
|
4435
|
+
if (btcAvailableBalance < 8e-6) {
|
4436
|
+
throw new Error("BTC balance is not enough, please deposit more BTC.");
|
4437
|
+
}
|
4438
|
+
console.log("available near balance:", nearAvailableBalance);
|
4439
|
+
console.log("available btc balance:", btcAvailableBalance);
|
4316
4440
|
console.log("available gas token balance:", gasTokenBalance);
|
4317
4441
|
const convertTx = yield Promise.all(
|
4318
4442
|
transactions2.map((transaction, index) => convertTransactionToTxHex(transaction, index))
|
4319
4443
|
);
|
4320
|
-
if (
|
4444
|
+
if (nearAvailableBalance > 0.5) {
|
4321
4445
|
console.log("near balance is enough, get the protocol fee of each transaction");
|
4322
4446
|
const gasTokens = yield nearCall2(
|
4323
4447
|
currentConfig.accountContractId,
|
4324
4448
|
"list_gas_token",
|
4325
|
-
{ token_ids: [currentConfig.
|
4449
|
+
{ token_ids: [currentConfig.btcToken] }
|
4326
4450
|
);
|
4327
4451
|
console.log("list_gas_token gas tokens:", gasTokens);
|
4328
4452
|
const perTxFee = Math.max(
|
4329
|
-
Number(((_a = gasTokens[currentConfig.
|
4453
|
+
Number(((_a = gasTokens[currentConfig.btcToken]) == null ? void 0 : _a.per_tx_protocol_fee) || 0),
|
4330
4454
|
100
|
4331
4455
|
);
|
4332
4456
|
console.log("perTxFee:", perTxFee);
|
@@ -4344,7 +4468,7 @@ var BTCWallet = (_0) => __async(void 0, [_0], function* ({
|
|
4344
4468
|
console.log("near balance is not enough, predict the gas token amount required");
|
4345
4469
|
const adjustedGas = yield getPredictedGasAmount(
|
4346
4470
|
currentConfig.accountContractId,
|
4347
|
-
currentConfig.
|
4471
|
+
currentConfig.btcToken,
|
4348
4472
|
convertTx.map((t) => t.txHex)
|
4349
4473
|
);
|
4350
4474
|
if (new import_big2.default(gasTokenBalance).gte(adjustedGas)) {
|
@@ -4460,7 +4584,7 @@ function setupBTCWallet({
|
|
4460
4584
|
|
4461
4585
|
// src/index.ts
|
4462
4586
|
var getVersion = () => {
|
4463
|
-
return "0.5.
|
4587
|
+
return "0.5.13-beta";
|
4464
4588
|
};
|
4465
4589
|
if (typeof window !== "undefined") {
|
4466
4590
|
window.__BTC_WALLET_VERSION = getVersion();
|