btc-wallet 0.4.6-beta → 0.4.7-beta

Sign up to get free protection for your applications and to get access to all the features.
@@ -50,6 +50,7 @@ export declare function getDepositAmount(amount: string, option?: {
50
50
  totalDepositAmount: number;
51
51
  protocolFee: number;
52
52
  repayAmount: string | number;
53
+ newAccountMinDepositAmount: string | number;
53
54
  }>;
54
55
  export declare function getCsnaAccountId(env: ENV): Promise<string>;
55
56
  interface ExecuteBTCDepositAndActionParams<T extends boolean = true> {
package/dist/index.js CHANGED
@@ -2675,35 +2675,107 @@ function createFloatingButtonWithIframe({
2675
2675
  }) {
2676
2676
  const button = document.createElement("img");
2677
2677
  button.id = "satoshi-wallet-button";
2678
- button.src = openImageUrl;
2678
+ const isIframeVisible = localStorage.getItem("btc-wallet-iframe-visible") === "true";
2679
+ button.src = isIframeVisible ? closeImageUrl : openImageUrl;
2680
+ iframe.style.display = isIframeVisible ? "block" : "none";
2681
+ const windowWidth = window.innerWidth;
2682
+ const windowHeight = window.innerHeight;
2683
+ const savedPosition = JSON.parse(
2684
+ localStorage.getItem("btc-wallet-button-position") || '{"right": "20px", "bottom": "20px"}'
2685
+ );
2686
+ const right = Math.min(Math.max(20, parseInt(savedPosition.right)), windowWidth - 80);
2687
+ const bottom = Math.min(Math.max(20, parseInt(savedPosition.bottom)), windowHeight - 80);
2679
2688
  Object.assign(button.style, {
2680
2689
  position: "fixed",
2681
- bottom: "20px",
2682
- right: "20px",
2690
+ bottom: `${bottom}px`,
2691
+ right: `${right}px`,
2683
2692
  zIndex: "100000",
2684
2693
  width: "60px",
2685
2694
  height: "60px",
2686
2695
  borderRadius: "50%",
2687
- cursor: "pointer",
2688
- transition: "transform 0.15s ease"
2696
+ cursor: "grab",
2697
+ transition: "transform 0.15s ease",
2698
+ userSelect: "none"
2689
2699
  });
2690
2700
  document.body.appendChild(button);
2691
- const iframeVisible = localStorage.getItem("iframeVisible") === "true" || localStorage.getItem("iframeVisible") === null;
2692
- button.src = iframeVisible ? closeImageUrl : openImageUrl;
2693
- iframe.style.display = iframeVisible ? "block" : "none";
2694
- button.onclick = function() {
2701
+ let isDragging = false;
2702
+ let startX = 0;
2703
+ let startY = 0;
2704
+ let initialRight = 0;
2705
+ let initialBottom = 0;
2706
+ let dragStartTime = 0;
2707
+ button.addEventListener("mousedown", (e) => {
2708
+ isDragging = true;
2709
+ startX = e.clientX;
2710
+ startY = e.clientY;
2711
+ initialRight = parseInt(button.style.right);
2712
+ initialBottom = parseInt(button.style.bottom);
2713
+ dragStartTime = Date.now();
2714
+ button.style.cursor = "grabbing";
2715
+ button.style.transition = "none";
2716
+ e.preventDefault();
2717
+ });
2718
+ document.addEventListener("mousemove", (e) => {
2719
+ if (!isDragging)
2720
+ return;
2721
+ const deltaX = startX - e.clientX;
2722
+ const deltaY = startY - e.clientY;
2723
+ let newRight = initialRight + deltaX;
2724
+ let newBottom = initialBottom + deltaY;
2725
+ newRight = Math.min(Math.max(20, newRight), windowWidth - 80);
2726
+ newBottom = Math.min(Math.max(20, newBottom), windowHeight - 80);
2727
+ const snapThreshold = 20;
2728
+ const buttonLeft = windowWidth - newRight - 60;
2729
+ if (buttonLeft < snapThreshold) {
2730
+ newRight = windowWidth - 80;
2731
+ } else if (buttonLeft > windowWidth - snapThreshold - 60) {
2732
+ newRight = 20;
2733
+ }
2734
+ if (newBottom < snapThreshold) {
2735
+ newBottom = 20;
2736
+ } else if (newBottom > windowHeight - snapThreshold - 60) {
2737
+ newBottom = windowHeight - 80;
2738
+ }
2739
+ button.style.right = `${newRight}px`;
2740
+ button.style.bottom = `${newBottom}px`;
2741
+ updateIframePosition(iframe, newRight, newBottom, windowWidth, windowHeight);
2742
+ });
2743
+ document.addEventListener("mouseup", () => {
2744
+ if (!isDragging)
2745
+ return;
2746
+ const dragEndTime = Date.now();
2747
+ const isDragEvent = dragEndTime - dragStartTime > 200;
2748
+ isDragging = false;
2749
+ button.style.cursor = "grab";
2750
+ button.style.transition = "transform 0.15s ease";
2751
+ localStorage.setItem(
2752
+ "btc-wallet-button-position",
2753
+ JSON.stringify({
2754
+ right: button.style.right,
2755
+ bottom: button.style.bottom
2756
+ })
2757
+ );
2758
+ if (!isDragEvent) {
2759
+ handleButtonClick();
2760
+ }
2761
+ });
2762
+ const handleButtonClick = () => {
2695
2763
  const isCurrentlyVisible = iframe.style.display === "block";
2696
2764
  button.style.transform = "scale(0.8)";
2697
2765
  setTimeout(() => {
2698
2766
  button.style.transform = "scale(1)";
2699
2767
  }, 150);
2700
- iframe.style.display = isCurrentlyVisible ? "none" : "block";
2701
- button.src = isCurrentlyVisible ? openImageUrl : closeImageUrl;
2702
- localStorage.setItem("iframeVisible", String(!isCurrentlyVisible));
2768
+ const newVisibleState = !isCurrentlyVisible;
2769
+ iframe.style.display = newVisibleState ? "block" : "none";
2770
+ button.src = newVisibleState ? closeImageUrl : openImageUrl;
2771
+ localStorage.setItem("btc-wallet-iframe-visible", String(newVisibleState));
2703
2772
  setTimeout(() => {
2704
- iframe.focus();
2773
+ if (newVisibleState) {
2774
+ iframe.focus();
2775
+ }
2705
2776
  }, 0);
2706
2777
  };
2778
+ button.onclick = null;
2707
2779
  return button;
2708
2780
  }
2709
2781
  function createIframe({
@@ -2714,6 +2786,7 @@ function createIframe({
2714
2786
  iframe.id = "satoshi-wallet-iframe";
2715
2787
  iframe.allow = "clipboard-read; clipboard-write";
2716
2788
  iframe.src = iframeUrl;
2789
+ const isVisible = localStorage.getItem("btc-wallet-iframe-visible") === "true";
2717
2790
  Object.assign(iframe.style, __spreadValues({
2718
2791
  position: "fixed",
2719
2792
  bottom: "90px",
@@ -2721,7 +2794,7 @@ function createIframe({
2721
2794
  zIndex: "100000",
2722
2795
  boxShadow: "0 0 10px rgba(0, 0, 0, 0.1)",
2723
2796
  borderRadius: "10px",
2724
- display: "block",
2797
+ display: isVisible ? "block" : "none",
2725
2798
  border: "none"
2726
2799
  }, iframeStyle));
2727
2800
  document.body.appendChild(iframe);
@@ -2779,6 +2852,20 @@ function removeWalletButton() {
2779
2852
  const iframe = document.getElementById("satoshi-wallet-iframe");
2780
2853
  iframe == null ? void 0 : iframe.remove();
2781
2854
  }
2855
+ function updateIframePosition(iframe, buttonRight, buttonBottom, windowWidth, windowHeight) {
2856
+ const iframeWidth = parseInt(iframe.style.width);
2857
+ const iframeHeight = parseInt(iframe.style.height);
2858
+ let iframeRight = buttonRight;
2859
+ let iframeBottom = buttonBottom + 70;
2860
+ if (iframeRight + iframeWidth > windowWidth - 20) {
2861
+ iframeRight = Math.max(20, windowWidth - iframeWidth - 20);
2862
+ }
2863
+ if (iframeBottom + iframeHeight > windowHeight - 20) {
2864
+ iframeBottom = Math.max(20, buttonBottom - iframeHeight - 10);
2865
+ }
2866
+ iframe.style.right = `${iframeRight}px`;
2867
+ iframe.style.bottom = `${iframeBottom}px`;
2868
+ }
2782
2869
 
2783
2870
  // src/utils/nearUtils.ts
2784
2871
  var import_near_api_js = require("near-api-js");
@@ -3247,6 +3334,7 @@ var import_coinselect = __toESM(require("coinselect"), 1);
3247
3334
  var NEAR_STORAGE_DEPOSIT_AMOUNT = "1250000000000000000000";
3248
3335
  var NBTC_STORAGE_DEPOSIT_AMOUNT = "3000";
3249
3336
  var GAS_LIMIT = "50000000000000";
3337
+ var NEW_ACCOUNT_MIN_DEPOSIT_AMOUNT = "1000";
3250
3338
  function getBtcProvider() {
3251
3339
  if (typeof window === "undefined" || !window.btcContext) {
3252
3340
  throw new Error("BTC Provider is not initialized.");
@@ -3416,12 +3504,14 @@ function getDepositAmount(amount, option) {
3416
3504
  } = yield nearCall(config.bridgeContractId, "get_config", {});
3417
3505
  const depositAmount = Math.max(Number(min_deposit_amount), Number(amount));
3418
3506
  const protocolFee = Math.max(Number(fee_min), Number(depositAmount) * fee_rate);
3419
- const totalDepositAmount = new import_big.default(depositAmount).plus(protocolFee).plus(repayAmount).round(0, import_big.default.roundDown).toNumber();
3507
+ const newAccountMinDepositAmount = !(accountInfo == null ? void 0 : accountInfo.nonce) ? NEW_ACCOUNT_MIN_DEPOSIT_AMOUNT : 0;
3508
+ const totalDepositAmount = new import_big.default(depositAmount).plus(protocolFee).plus(repayAmount).plus(newAccountMinDepositAmount).round(0, import_big.default.roundDown).toNumber();
3420
3509
  return {
3421
3510
  depositAmount,
3422
3511
  totalDepositAmount,
3423
3512
  protocolFee,
3424
- repayAmount
3513
+ repayAmount,
3514
+ newAccountMinDepositAmount
3425
3515
  };
3426
3516
  });
3427
3517
  }
@@ -3548,6 +3638,14 @@ function checkSatoshiWhitelist(btcAccountId, env = "mainnet") {
3548
3638
  return __async(this, null, function* () {
3549
3639
  if (env !== "private_mainnet")
3550
3640
  return;
3641
+ const hasShownNotice = localStorage.getItem("btc-wallet-private-mainnet-notice");
3642
+ if (!hasShownNotice) {
3643
+ Dialog.alert({
3644
+ title: "Notice",
3645
+ message: "You are currently using Satoshi Private Mainnet. This is a private version for testing. Please try a small amount of assets in Ramp"
3646
+ });
3647
+ localStorage.setItem("btc-wallet-private-mainnet-notice", "true");
3648
+ }
3551
3649
  if (!btcAccountId)
3552
3650
  return;
3553
3651
  const config = yield getConfig(env);
@@ -3712,24 +3810,41 @@ function uint8ArrayToHex(uint8Array) {
3712
3810
 
3713
3811
  // src/core/setupBTCWallet.ts
3714
3812
  var { transfer, functionCall } = import_transactions.actionCreators;
3813
+ var STORAGE_KEYS = {
3814
+ ACCOUNT: "btc-wallet-account",
3815
+ PUBLIC_KEY: "btc-wallet-publickey",
3816
+ BTC_PUBLIC_KEY: "btc-wallet-btc-publickey"
3817
+ };
3715
3818
  var state = {
3716
3819
  saveAccount(account) {
3717
- window.localStorage.setItem("btc-wallet-account", account);
3820
+ if (!account) {
3821
+ this.removeAccount();
3822
+ return;
3823
+ }
3824
+ window.localStorage.setItem(STORAGE_KEYS.ACCOUNT, account);
3718
3825
  },
3719
3826
  removeAccount() {
3720
- window.localStorage.removeItem("btc-wallet-account");
3827
+ window.localStorage.removeItem(STORAGE_KEYS.ACCOUNT);
3721
3828
  },
3722
3829
  savePublicKey(publicKey) {
3723
- window.localStorage.setItem("btc-wallet-publickey", publicKey);
3830
+ if (!publicKey) {
3831
+ this.removePublicKey();
3832
+ return;
3833
+ }
3834
+ window.localStorage.setItem(STORAGE_KEYS.PUBLIC_KEY, publicKey);
3724
3835
  },
3725
3836
  removePublicKey() {
3726
- window.localStorage.removeItem("btc-wallet-publickey");
3837
+ window.localStorage.removeItem(STORAGE_KEYS.PUBLIC_KEY);
3727
3838
  },
3728
3839
  saveBtcPublicKey(publicKey) {
3729
- window.localStorage.setItem("btc-wallet-btc-publickey", publicKey);
3840
+ if (!publicKey) {
3841
+ this.removeBtcPublicKey();
3842
+ return;
3843
+ }
3844
+ window.localStorage.setItem(STORAGE_KEYS.BTC_PUBLIC_KEY, publicKey);
3730
3845
  },
3731
3846
  removeBtcPublicKey() {
3732
- window.localStorage.removeItem("btc-wallet-btc-publickey");
3847
+ window.localStorage.removeItem(STORAGE_KEYS.BTC_PUBLIC_KEY);
3733
3848
  },
3734
3849
  clear() {
3735
3850
  this.removeAccount();
@@ -3737,17 +3852,39 @@ var state = {
3737
3852
  this.removeBtcPublicKey();
3738
3853
  },
3739
3854
  save(account, publicKey) {
3855
+ if (!account || !publicKey) {
3856
+ this.clear();
3857
+ return;
3858
+ }
3740
3859
  this.saveAccount(account);
3741
3860
  this.savePublicKey(publicKey);
3742
3861
  },
3743
3862
  getAccount() {
3744
- return window.localStorage.getItem("btc-wallet-account");
3863
+ return window.localStorage.getItem(STORAGE_KEYS.ACCOUNT);
3745
3864
  },
3746
3865
  getPublicKey() {
3747
- return window.localStorage.getItem("btc-wallet-publickey");
3866
+ return window.localStorage.getItem(STORAGE_KEYS.PUBLIC_KEY);
3748
3867
  },
3749
3868
  getBtcPublicKey() {
3750
- return window.localStorage.getItem("btc-wallet-btc-publickey");
3869
+ return window.localStorage.getItem(STORAGE_KEYS.BTC_PUBLIC_KEY);
3870
+ },
3871
+ isValid() {
3872
+ const account = this.getAccount();
3873
+ const publicKey = this.getPublicKey();
3874
+ const btcPublicKey = this.getBtcPublicKey();
3875
+ const allEmpty = !account && !publicKey && !btcPublicKey;
3876
+ const allExist = account && publicKey && btcPublicKey;
3877
+ return allEmpty || allExist;
3878
+ },
3879
+ syncSave(account, publicKey, btcPublicKey) {
3880
+ if (!account || !publicKey || !btcPublicKey) {
3881
+ this.clear();
3882
+ return;
3883
+ }
3884
+ this.clear();
3885
+ this.savePublicKey(publicKey);
3886
+ this.saveBtcPublicKey(btcPublicKey);
3887
+ this.saveAccount(account);
3751
3888
  }
3752
3889
  };
3753
3890
  var BTCWallet = (_0) => __async(void 0, [_0], function* ({
@@ -3774,16 +3911,33 @@ var BTCWallet = (_0) => __async(void 0, [_0], function* ({
3774
3911
  const currentConfig = walletConfig[env];
3775
3912
  const walletNetwork = ["mainnet", "private_mainnet"].includes(env) ? "mainnet" : "testnet";
3776
3913
  yield initBtcContext();
3914
+ function validateWalletState() {
3915
+ const accountId = state.getAccount();
3916
+ const publicKey = state.getPublicKey();
3917
+ const btcPublicKey = state.getBtcPublicKey();
3918
+ if (!accountId && publicKey || accountId && !publicKey || !publicKey && btcPublicKey) {
3919
+ state.clear();
3920
+ return false;
3921
+ }
3922
+ return true;
3923
+ }
3777
3924
  function setupBtcContextListeners() {
3778
3925
  return __async(this, null, function* () {
3779
3926
  const handleConnectionUpdate = () => __async(this, null, function* () {
3780
3927
  yield checkBtcNetwork(walletNetwork);
3781
- const accountId = state.getAccount();
3928
+ if (!state.isValid()) {
3929
+ state.clear();
3930
+ }
3931
+ validateWalletState();
3782
3932
  const btcContext = window.btcContext;
3783
- if (accountId && btcContext.account) {
3784
- yield checkSatoshiWhitelist(btcContext.account, env);
3785
- removeWalletButton();
3786
- setupWalletButton(env, wallet, btcContext);
3933
+ if (btcContext.account) {
3934
+ const btcPublicKey = yield btcContext.getPublicKey();
3935
+ if (btcPublicKey) {
3936
+ const { nearAddress, nearPublicKey } = yield getNearAccountByBtcPublicKey(btcPublicKey);
3937
+ yield checkSatoshiWhitelist(btcContext.account, env);
3938
+ removeWalletButton();
3939
+ setupWalletButton(env, wallet, btcContext);
3940
+ }
3787
3941
  } else {
3788
3942
  removeWalletButton();
3789
3943
  setTimeout(() => {
@@ -3794,19 +3948,31 @@ var BTCWallet = (_0) => __async(void 0, [_0], function* ({
3794
3948
  const context = window.btcContext.getContext();
3795
3949
  context.on("updatePublicKey", (btcPublicKey) => __async(this, null, function* () {
3796
3950
  console.log("updatePublicKey");
3797
- const { nearAddress } = yield getNearAccountByBtcPublicKey(btcPublicKey);
3798
- emitter.emit("accountsChanged", {
3799
- accounts: [{ accountId: nearAddress }]
3800
- });
3801
- yield handleConnectionUpdate();
3951
+ state.clear();
3952
+ try {
3953
+ const { nearAddress, nearPublicKey } = yield getNearAccountByBtcPublicKey(btcPublicKey);
3954
+ if (!nearAddress || !nearPublicKey) {
3955
+ throw new Error("Failed to get near account info");
3956
+ }
3957
+ emitter.emit("accountsChanged", {
3958
+ accounts: [{ accountId: nearAddress }]
3959
+ });
3960
+ yield handleConnectionUpdate();
3961
+ } catch (error) {
3962
+ console.error("Error updating public key:", error);
3963
+ state.clear();
3964
+ emitter.emit("accountsChanged", { accounts: [] });
3965
+ }
3802
3966
  }));
3803
3967
  context.on("btcLoginError", () => __async(this, null, function* () {
3804
3968
  console.log("btcLoginError");
3969
+ state.clear();
3805
3970
  emitter.emit("accountsChanged", { accounts: [] });
3806
3971
  yield handleConnectionUpdate();
3807
3972
  }));
3808
3973
  context.on("btcLogOut", () => __async(this, null, function* () {
3809
3974
  console.log("btcLogOut");
3975
+ state.clear();
3810
3976
  emitter.emit("accountsChanged", { accounts: [] });
3811
3977
  yield handleConnectionUpdate();
3812
3978
  }));
@@ -3850,9 +4016,7 @@ var BTCWallet = (_0) => __async(void 0, [_0], function* ({
3850
4016
  "get_chain_signature_near_account_public_key",
3851
4017
  { btc_public_key: btcPublicKey }
3852
4018
  );
3853
- state.saveAccount(csna);
3854
- state.savePublicKey(nearPublicKey);
3855
- state.saveBtcPublicKey(btcPublicKey);
4019
+ state.syncSave(csna, nearPublicKey, btcPublicKey);
3856
4020
  return {
3857
4021
  nearAddress: csna,
3858
4022
  nearPublicKey
@@ -3862,10 +4026,8 @@ var BTCWallet = (_0) => __async(void 0, [_0], function* ({
3862
4026
  function signIn(_02) {
3863
4027
  return __async(this, arguments, function* ({ contractId, methodNames }) {
3864
4028
  const btcContext = window.btcContext;
3865
- const accountId = state.getAccount();
3866
- const publicKey = state.getPublicKey();
3867
- console.log("isLogin:", accountId && publicKey);
3868
- if (!accountId || !publicKey) {
4029
+ state.clear();
4030
+ if (!state.getAccount() || !state.getPublicKey()) {
3869
4031
  yield btcContext.login();
3870
4032
  }
3871
4033
  const btcPublicKey = yield btcContext.getPublicKey();
@@ -3931,6 +4093,9 @@ var BTCWallet = (_0) => __async(void 0, [_0], function* ({
3931
4093
  }
3932
4094
  function signAndSendTransactions(params) {
3933
4095
  return __async(this, null, function* () {
4096
+ if (!validateWalletState()) {
4097
+ throw new Error("Wallet state is invalid, please reconnect your wallet.");
4098
+ }
3934
4099
  const btcContext = window.btcContext;
3935
4100
  const accountId = state.getAccount();
3936
4101
  const accountInfo = yield getAccountInfo(accountId, currentConfig.accountContractId);
@@ -4137,18 +4302,6 @@ function setupBTCWallet({
4137
4302
  env = "mainnet"
4138
4303
  } = {}) {
4139
4304
  console.log("\u26A1\uFE0F BTC Wallet Version:", getVersion(), "env:", env);
4140
- if (env === "private_mainnet" && typeof window !== "undefined") {
4141
- setTimeout(() => {
4142
- const hasShownNotice = localStorage.getItem("satoshi_private_mainnet_notice");
4143
- if (!hasShownNotice) {
4144
- Dialog.alert({
4145
- title: "Notice",
4146
- message: "You are currently using Satoshi Private Mainnet. This is a private version for testing. Please try a small amount of assets in Ramp"
4147
- });
4148
- localStorage.setItem("satoshi_private_mainnet_notice", "true");
4149
- }
4150
- }, 1e3);
4151
- }
4152
4305
  const btcWallet = () => __async(this, null, function* () {
4153
4306
  return {
4154
4307
  id: "btc-wallet",
@@ -4172,7 +4325,7 @@ function setupBTCWallet({
4172
4325
 
4173
4326
  // src/index.ts
4174
4327
  var getVersion = () => {
4175
- return "0.4.6-beta";
4328
+ return "0.4.7-beta";
4176
4329
  };
4177
4330
  if (typeof window !== "undefined") {
4178
4331
  window.__BTC_WALLET_VERSION = getVersion();