@spicenet-io/spiceflow-ui 1.7.2 → 1.7.3

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/index.cjs.js CHANGED
@@ -86,10 +86,10 @@ const CHAIN_CONFIGS = {
86
86
  moralisName: "",
87
87
  supportedTokens: [
88
88
  {
89
- address: "0x75faf114eafb1BDbe2F0316DF893fd58CE46AA4d",
89
+ address: "0xBeB51deb2018b67b35d5695Fd15bb30D452c7868",
90
90
  name: "USD Coin",
91
91
  symbol: "USDC",
92
- decimals: 6
92
+ decimals: 18
93
93
  }
94
94
  ]
95
95
  },
@@ -120,10 +120,10 @@ const CHAIN_CONFIGS = {
120
120
  moralisName: "0x14a34",
121
121
  supportedTokens: [
122
122
  {
123
- address: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
123
+ address: "0xf370dC3765f81aC9dD2FEBd59Fb4e710330B0BC8",
124
124
  name: "USD Coin",
125
125
  symbol: "USDC",
126
- decimals: 6
126
+ decimals: 18
127
127
  },
128
128
  {
129
129
  address: "0x4Fc381B6CC6Df8cF1c1bD46D184475bE5b7A3c62",
@@ -3166,6 +3166,39 @@ class RelayerService {
3166
3166
  throw error;
3167
3167
  }
3168
3168
  }
3169
+ async requestSpiceUsdAirdrop(params) {
3170
+ try {
3171
+ const response = await fetch(
3172
+ `${this.baseUrl}/airdrop/${params.chainId}/spiceUsd`,
3173
+ {
3174
+ method: "POST",
3175
+ headers: {
3176
+ "Content-Type": "application/json"
3177
+ },
3178
+ body: JSON.stringify({ wallet: params.address })
3179
+ }
3180
+ );
3181
+ const data = await response.json().catch(() => ({}));
3182
+ if (!response.ok) {
3183
+ const msg = data && (data.error || data.message) || "Failed to request airdrop";
3184
+ return { success: false, errorMessage: String(msg) };
3185
+ }
3186
+ if (data && typeof data.error === "string") {
3187
+ return { success: false, errorMessage: data.error };
3188
+ }
3189
+ if (data && (data.txHash || data.amount)) {
3190
+ return {
3191
+ success: true,
3192
+ txHash: data.txHash,
3193
+ amount: data.amount
3194
+ };
3195
+ }
3196
+ return { success: true };
3197
+ } catch (error) {
3198
+ const msg = error?.message && typeof error.message === "string" ? error.message : "Failed to request airdrop";
3199
+ return { success: false, errorMessage: msg };
3200
+ }
3201
+ }
3169
3202
  }
3170
3203
  const relayerService = new RelayerService();
3171
3204
  const createInitialSteps = (chainBatches, customGetChainName) => {
@@ -3914,7 +3947,8 @@ const SwapWidget = ({
3914
3947
 
3915
3948
  const DepositWidget = ({
3916
3949
  depositBatches,
3917
- tokenAddress = "0x0",
3950
+ tokenAddress,
3951
+ tokenDecimals,
3918
3952
  supportedChains,
3919
3953
  theme: themeMode = "light",
3920
3954
  styles,
@@ -4104,7 +4138,10 @@ const DepositWidget = ({
4104
4138
  [
4105
4139
  {
4106
4140
  tokenAddress,
4107
- tokenAmount: viem.parseEther(selectedDepositAsset.amount)
4141
+ tokenAmount: viem.parseUnits(
4142
+ selectedDepositAsset.amount,
4143
+ tokenDecimals
4144
+ )
4108
4145
  }
4109
4146
  ]
4110
4147
  ]
@@ -4615,6 +4652,7 @@ const DepositWidgetModal = ({
4615
4652
  // Pass through all DepositWidget props
4616
4653
  depositBatches,
4617
4654
  tokenAddress,
4655
+ tokenDecimals,
4618
4656
  supportedChains,
4619
4657
  theme: themeMode = "light",
4620
4658
  styles,
@@ -4680,6 +4718,7 @@ const DepositWidgetModal = ({
4680
4718
  {
4681
4719
  depositBatches,
4682
4720
  tokenAddress,
4721
+ tokenDecimals,
4683
4722
  supportedChains,
4684
4723
  theme: themeMode,
4685
4724
  styles: {
@@ -6974,6 +7013,9 @@ const DepositModal = React.memo(
6974
7013
  null
6975
7014
  );
6976
7015
  const [showAirdropTooltip, setShowAirdropTooltip] = React.useState(false);
7016
+ const [airdropLoading, setAirdropLoading] = React.useState(false);
7017
+ const [airdropMessage, setAirdropMessage] = React.useState(null);
7018
+ const [airdropError, setAirdropError] = React.useState(null);
6977
7019
  const {
6978
7020
  intentStatus,
6979
7021
  startStatusPolling,
@@ -7010,13 +7052,6 @@ const DepositModal = React.memo(
7010
7052
  "Submitting deposit data to backend after bridging completes:",
7011
7053
  depositData
7012
7054
  );
7013
- for (const data of depositData) {
7014
- console.log("Calling submitSpiceDeposit with:", data);
7015
- await relayerService.submitSpiceDeposit(data);
7016
- console.log(
7017
- `Successfully submitted deposit for txHash: ${data.txHash} on chainId: ${data.chainId}`
7018
- );
7019
- }
7020
7055
  }
7021
7056
  setPostDepositStatus("success");
7022
7057
  setPostDepositAmount(bridgedAmount);
@@ -7049,6 +7084,44 @@ const DepositModal = React.memo(
7049
7084
  }, [isOpen]);
7050
7085
  React.useMemo(() => {
7051
7086
  }, [depositAmount]);
7087
+ const handleAirdropClick = React.useCallback(async () => {
7088
+ const targetAddress = sourceAddress || address;
7089
+ setAirdropMessage(null);
7090
+ setAirdropError(null);
7091
+ if (!targetAddress) {
7092
+ setAirdropError("Connect your wallet before requesting an airdrop");
7093
+ return;
7094
+ }
7095
+ const selectedChainId = selectedDepositAssets[0]?.asset?.chainId ?? supportedChains[0];
7096
+ if (!selectedChainId) {
7097
+ setAirdropError("No chain selected for airdrop");
7098
+ return;
7099
+ }
7100
+ setAirdropLoading(true);
7101
+ try {
7102
+ const result = await relayerService.requestSpiceUsdAirdrop({
7103
+ chainId: selectedChainId,
7104
+ address: targetAddress
7105
+ });
7106
+ if (!result.success) {
7107
+ setAirdropError(result.errorMessage || "Failed to request airdrop");
7108
+ return;
7109
+ }
7110
+ if (result.txHash || result.amount) {
7111
+ const amountText = result.amount ? ` ${result.amount}` : "";
7112
+ setAirdropMessage(
7113
+ `Airdrop${amountText} requested successfully. Transaction will appear shortly.`
7114
+ );
7115
+ return;
7116
+ }
7117
+ setAirdropMessage("Airdrop requested successfully.");
7118
+ } catch (e) {
7119
+ const msg = e?.message && typeof e.message === "string" ? e.message : "Failed to request airdrop";
7120
+ setAirdropError(msg);
7121
+ } finally {
7122
+ setAirdropLoading(false);
7123
+ }
7124
+ }, [address, sourceAddress, selectedDepositAssets, supportedChains]);
7052
7125
  const handleDepositAssetSelect = (asset, index) => {
7053
7126
  setSelectedDepositAssets((prev) => {
7054
7127
  const updated = [...prev];
@@ -7663,94 +7736,107 @@ const DepositModal = React.memo(
7663
7736
  style: {
7664
7737
  display: "flex",
7665
7738
  justifyContent: "flex-end",
7666
- alignItems: "center",
7739
+ alignItems: "flex-start",
7740
+ flexDirection: "column",
7667
7741
  gap: "4px",
7668
7742
  marginBottom: "8px"
7669
7743
  },
7670
7744
  children: [
7671
- /* @__PURE__ */ jsxRuntime.jsx(
7672
- "button",
7673
- {
7674
- onClick: () => {
7675
- },
7676
- style: {
7677
- padding: "4px 8px",
7678
- borderRadius: "4px",
7679
- border: "1px solid #D1D5DB",
7680
- background: "#E5E7EB",
7681
- color: "#4B5563",
7682
- fontSize: "11px",
7683
- fontWeight: 500,
7684
- cursor: "pointer",
7685
- display: "flex",
7686
- alignItems: "center",
7687
- gap: "4px",
7688
- transition: "all 0.2s",
7689
- whiteSpace: "nowrap"
7690
- },
7691
- onMouseEnter: (e) => {
7692
- e.currentTarget.style.color = "#1F2937";
7693
- e.currentTarget.style.background = "#D1D5DB";
7694
- },
7695
- onMouseLeave: (e) => {
7696
- e.currentTarget.style.color = "#4B5563";
7697
- e.currentTarget.style.background = "#E5E7EB";
7698
- },
7699
- children: "Airdrop"
7700
- }
7701
- ),
7702
7745
  /* @__PURE__ */ jsxRuntime.jsxs(
7703
7746
  "div",
7704
7747
  {
7705
- onMouseEnter: () => setShowAirdropTooltip(true),
7706
- onMouseLeave: () => setShowAirdropTooltip(false),
7707
7748
  style: {
7708
- position: "relative",
7709
- width: "14px",
7710
- height: "14px",
7711
- borderRadius: "50%",
7712
- backgroundColor: "#9CA3AF",
7713
- color: "white",
7714
7749
  display: "flex",
7750
+ justifyContent: "flex-end",
7715
7751
  alignItems: "center",
7716
- justifyContent: "center",
7717
- fontSize: "9px",
7718
- fontWeight: "bold",
7719
- cursor: "help"
7752
+ gap: "4px"
7720
7753
  },
7721
7754
  children: [
7722
- "i",
7723
- showAirdropTooltip && /* @__PURE__ */ jsxRuntime.jsxs(
7755
+ /* @__PURE__ */ jsxRuntime.jsx(
7756
+ "button",
7757
+ {
7758
+ onClick: handleAirdropClick,
7759
+ style: {
7760
+ padding: "4px 8px",
7761
+ borderRadius: "4px",
7762
+ border: "1px solid #D1D5DB",
7763
+ background: "#E5E7EB",
7764
+ color: "#4B5563",
7765
+ fontSize: "11px",
7766
+ fontWeight: 500,
7767
+ cursor: airdropLoading ? "default" : "pointer",
7768
+ display: "flex",
7769
+ alignItems: "center",
7770
+ gap: "4px",
7771
+ transition: "all 0.2s",
7772
+ whiteSpace: "nowrap"
7773
+ },
7774
+ onMouseEnter: (e) => {
7775
+ e.currentTarget.style.color = "#1F2937";
7776
+ e.currentTarget.style.background = "#D1D5DB";
7777
+ },
7778
+ onMouseLeave: (e) => {
7779
+ e.currentTarget.style.color = "#4B5563";
7780
+ e.currentTarget.style.background = "#E5E7EB";
7781
+ },
7782
+ children: airdropLoading ? "Requesting..." : "Airdrop"
7783
+ }
7784
+ ),
7785
+ /* @__PURE__ */ jsxRuntime.jsxs(
7724
7786
  "div",
7725
7787
  {
7788
+ onMouseEnter: () => setShowAirdropTooltip(true),
7789
+ onMouseLeave: () => setShowAirdropTooltip(false),
7726
7790
  style: {
7727
- position: "absolute",
7728
- bottom: "calc(100% + 8px)",
7729
- right: 0,
7730
- backgroundColor: "#1F2937",
7791
+ position: "relative",
7792
+ width: "14px",
7793
+ height: "14px",
7794
+ borderRadius: "50%",
7795
+ backgroundColor: "#9CA3AF",
7731
7796
  color: "white",
7732
- padding: "8px 12px",
7733
- borderRadius: "6px",
7734
- fontSize: "12px",
7735
- whiteSpace: "nowrap",
7736
- boxShadow: "0 4px 6px rgba(0, 0, 0, 0.1)",
7737
- zIndex: 100
7797
+ display: "flex",
7798
+ alignItems: "center",
7799
+ justifyContent: "center",
7800
+ fontSize: "9px",
7801
+ fontWeight: "bold",
7802
+ cursor: "help"
7738
7803
  },
7739
7804
  children: [
7740
- "This is testnet USDC, and it won't be available on mainnet",
7741
- /* @__PURE__ */ jsxRuntime.jsx(
7805
+ "i",
7806
+ showAirdropTooltip && /* @__PURE__ */ jsxRuntime.jsxs(
7742
7807
  "div",
7743
7808
  {
7744
7809
  style: {
7745
7810
  position: "absolute",
7746
- top: "100%",
7747
- right: "10px",
7748
- width: 0,
7749
- height: 0,
7750
- borderLeft: "6px solid transparent",
7751
- borderRight: "6px solid transparent",
7752
- borderTop: "6px solid #1F2937"
7753
- }
7811
+ bottom: "calc(100% + 8px)",
7812
+ right: 0,
7813
+ backgroundColor: "#1F2937",
7814
+ color: "white",
7815
+ padding: "8px 12px",
7816
+ borderRadius: "6px",
7817
+ fontSize: "12px",
7818
+ whiteSpace: "nowrap",
7819
+ boxShadow: "0 4px 6px rgba(0, 0, 0, 0.1)",
7820
+ zIndex: 100
7821
+ },
7822
+ children: [
7823
+ "This is testnet USDC, and it won't be available on mainnet",
7824
+ /* @__PURE__ */ jsxRuntime.jsx(
7825
+ "div",
7826
+ {
7827
+ style: {
7828
+ position: "absolute",
7829
+ top: "100%",
7830
+ right: "10px",
7831
+ width: 0,
7832
+ height: 0,
7833
+ borderLeft: "6px solid transparent",
7834
+ borderRight: "6px solid transparent",
7835
+ borderTop: "6px solid #1F2937"
7836
+ }
7837
+ }
7838
+ )
7839
+ ]
7754
7840
  }
7755
7841
  )
7756
7842
  ]
@@ -7758,6 +7844,18 @@ const DepositModal = React.memo(
7758
7844
  )
7759
7845
  ]
7760
7846
  }
7847
+ ),
7848
+ (airdropMessage || airdropError) && /* @__PURE__ */ jsxRuntime.jsx(
7849
+ "div",
7850
+ {
7851
+ style: {
7852
+ marginTop: "6px",
7853
+ fontSize: "11px",
7854
+ color: airdropError ? "#b91c1c" : "#047857",
7855
+ fontFamily: styles?.fontFamily || theme.typography.fontFamily
7856
+ },
7857
+ children: airdropError || airdropMessage
7858
+ }
7761
7859
  )
7762
7860
  ]
7763
7861
  }
@@ -7836,8 +7934,7 @@ const DepositModal = React.memo(
7836
7934
  /* @__PURE__ */ jsxRuntime.jsx(
7837
7935
  "button",
7838
7936
  {
7839
- onClick: () => {
7840
- },
7937
+ onClick: handleAirdropClick,
7841
7938
  style: {
7842
7939
  padding: "4px 8px",
7843
7940
  borderRadius: "4px",
@@ -7846,7 +7943,7 @@ const DepositModal = React.memo(
7846
7943
  color: "#4B5563",
7847
7944
  fontSize: "11px",
7848
7945
  fontWeight: 500,
7849
- cursor: "pointer",
7946
+ cursor: airdropLoading ? "default" : "pointer",
7850
7947
  display: "flex",
7851
7948
  alignItems: "center",
7852
7949
  gap: "4px",
@@ -7861,7 +7958,7 @@ const DepositModal = React.memo(
7861
7958
  e.currentTarget.style.color = "#4B5563";
7862
7959
  e.currentTarget.style.background = "#E5E7EB";
7863
7960
  },
7864
- children: "Airdrop"
7961
+ children: airdropLoading ? "Requesting..." : "Airdrop"
7865
7962
  }
7866
7963
  ),
7867
7964
  /* @__PURE__ */ jsxRuntime.jsxs(
@@ -7923,6 +8020,18 @@ const DepositModal = React.memo(
7923
8020
  )
7924
8021
  ]
7925
8022
  }
8023
+ ),
8024
+ (airdropMessage || airdropError) && /* @__PURE__ */ jsxRuntime.jsx(
8025
+ "div",
8026
+ {
8027
+ style: {
8028
+ marginTop: "6px",
8029
+ fontSize: "11px",
8030
+ color: airdropError ? "#b91c1c" : "#047857",
8031
+ fontFamily: styles?.fontFamily || theme.typography.fontFamily
8032
+ },
8033
+ children: airdropError || airdropMessage
8034
+ }
7926
8035
  )
7927
8036
  ]
7928
8037
  }
@@ -10012,105 +10121,8 @@ const formatCurrencyWithDecimals = (amount) => {
10012
10121
  maximumFractionDigits: 5
10013
10122
  }).format(rounded);
10014
10123
  };
10015
- const defaultBalanceData = {
10016
- totalBalance: 10333,
10017
- percentageChange: 2.15,
10018
- tradingAccounts: [
10019
- { id: "hyperliquid", name: "HYPERLIQUID", balance: 800 },
10020
- { id: "lighter", name: "LIGHTER", balance: 1200 }
10021
- ],
10022
- freeCollateral: 8e3,
10023
- freeCollateralItems: [
10024
- {
10025
- id: "usdc-eth",
10026
- name: "USDC",
10027
- balance: 3e3,
10028
- subtitle: "USD COIN",
10029
- iconColor: "#2775CA",
10030
- networks: [11155111]
10031
- },
10032
- // Ethereum Sepolia
10033
- {
10034
- id: "usdc-arb",
10035
- name: "USDC",
10036
- balance: 2e3,
10037
- subtitle: "USD COIN",
10038
- iconColor: "#2775CA",
10039
- networks: [42161]
10040
- },
10041
- // Arbitrum
10042
- {
10043
- id: "usdc-base",
10044
- name: "USDC",
10045
- balance: 1500,
10046
- subtitle: "USD COIN",
10047
- iconColor: "#2775CA",
10048
- networks: [84532]
10049
- },
10050
- // Base Sepolia
10051
- {
10052
- id: "weth",
10053
- name: "WETH",
10054
- balance: 500,
10055
- subtitle: "WRAPPED ETH",
10056
- iconColor: "#627EEA",
10057
- networks: [11155111]
10058
- },
10059
- {
10060
- id: "uniswap-pt",
10061
- name: "UNISWAP PT",
10062
- balance: 500,
10063
- iconColor: "#FF007A",
10064
- networks: [11155111]
10065
- },
10066
- {
10067
- id: "pendle-pt",
10068
- name: "PENDLE PT",
10069
- balance: 500,
10070
- iconColor: "#6366F1",
10071
- networks: [11155111]
10072
- }
10073
- ],
10074
- defiPositions: 2333,
10075
- defiPositionsItems: [
10076
- {
10077
- id: "uniswap-v4",
10078
- name: "UNISWAP V4",
10079
- balance: 1166.5,
10080
- iconColor: "#FF007A"
10081
- },
10082
- {
10083
- id: "pendle-pt-defi",
10084
- name: "PENDLE PT",
10085
- balance: 1166.5,
10086
- iconColor: "#6366F1"
10087
- }
10088
- ],
10089
- credit: 2333,
10090
- creditItems: [
10091
- {
10092
- id: "usdc-credit",
10093
- name: "USDC",
10094
- balance: 1e3,
10095
- subtitle: "USD COIN",
10096
- iconColor: "#2775CA"
10097
- },
10098
- {
10099
- id: "uniswap-lp",
10100
- name: "UNISWAP LP",
10101
- balance: 666.5,
10102
- iconColor: "#FF007A"
10103
- },
10104
- {
10105
- id: "pendle-pt-credit",
10106
- name: "PENDLE PT",
10107
- balance: 666.5,
10108
- iconColor: "#6366F1"
10109
- }
10110
- ]
10111
- };
10112
10124
  const SpiceBalance = ({
10113
- balanceData = defaultBalanceData,
10125
+ balanceData,
10114
10126
  isLoading = false,
10115
10127
  styles,
10116
10128
  className = "",
@@ -10206,24 +10218,6 @@ const SpiceBalance = ({
10206
10218
  balanceData.freeCollateralItems,
10207
10219
  balanceData.freeCollateral
10208
10220
  ]);
10209
- React.useMemo(() => {
10210
- if (balanceData.defiPositionsItems) {
10211
- return balanceData.defiPositionsItems.reduce(
10212
- (sum, item) => sum + item.balance,
10213
- 0
10214
- );
10215
- }
10216
- return balanceData.defiPositions;
10217
- }, [balanceData.defiPositionsItems, balanceData.defiPositions]);
10218
- React.useMemo(() => {
10219
- if (balanceData.creditItems) {
10220
- return balanceData.creditItems.reduce(
10221
- (sum, item) => sum + item.balance,
10222
- 0
10223
- );
10224
- }
10225
- return balanceData.credit;
10226
- }, [balanceData.creditItems, balanceData.credit]);
10227
10221
  const maskBalance = (value) => {
10228
10222
  return isBalanceVisible ? value : "******";
10229
10223
  };
@@ -11958,7 +11952,7 @@ const LpModal = ({
11958
11952
  };
11959
11953
 
11960
11954
  const useFromInput = () => {
11961
- const [fromAmount, setFromAmount] = React.useState("");
11955
+ const [fromAmount, setFromAmount] = React.useState("0");
11962
11956
  return {
11963
11957
  fromAmount,
11964
11958
  setFromAmount
@@ -11966,7 +11960,7 @@ const useFromInput = () => {
11966
11960
  };
11967
11961
 
11968
11962
  const useToInputUpdate = () => {
11969
- const [toAmount, setToAmount] = React.useState("");
11963
+ const [toAmount, setToAmount] = React.useState("0");
11970
11964
  const updateToAmount = React.useCallback((amount) => {
11971
11965
  setToAmount(amount);
11972
11966
  }, []);
@@ -11978,7 +11972,7 @@ const useToInputUpdate = () => {
11978
11972
  };
11979
11973
 
11980
11974
  const useDepositInput = () => {
11981
- const [depositAmount, setDepositAmount] = React.useState("");
11975
+ const [depositAmount, setDepositAmount] = React.useState("0");
11982
11976
  return {
11983
11977
  depositAmount,
11984
11978
  setDepositAmount
package/dist/index.js CHANGED
@@ -84,10 +84,10 @@ const CHAIN_CONFIGS = {
84
84
  moralisName: "",
85
85
  supportedTokens: [
86
86
  {
87
- address: "0x75faf114eafb1BDbe2F0316DF893fd58CE46AA4d",
87
+ address: "0xBeB51deb2018b67b35d5695Fd15bb30D452c7868",
88
88
  name: "USD Coin",
89
89
  symbol: "USDC",
90
- decimals: 6
90
+ decimals: 18
91
91
  }
92
92
  ]
93
93
  },
@@ -118,10 +118,10 @@ const CHAIN_CONFIGS = {
118
118
  moralisName: "0x14a34",
119
119
  supportedTokens: [
120
120
  {
121
- address: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
121
+ address: "0xf370dC3765f81aC9dD2FEBd59Fb4e710330B0BC8",
122
122
  name: "USD Coin",
123
123
  symbol: "USDC",
124
- decimals: 6
124
+ decimals: 18
125
125
  },
126
126
  {
127
127
  address: "0x4Fc381B6CC6Df8cF1c1bD46D184475bE5b7A3c62",
@@ -3164,6 +3164,39 @@ class RelayerService {
3164
3164
  throw error;
3165
3165
  }
3166
3166
  }
3167
+ async requestSpiceUsdAirdrop(params) {
3168
+ try {
3169
+ const response = await fetch(
3170
+ `${this.baseUrl}/airdrop/${params.chainId}/spiceUsd`,
3171
+ {
3172
+ method: "POST",
3173
+ headers: {
3174
+ "Content-Type": "application/json"
3175
+ },
3176
+ body: JSON.stringify({ wallet: params.address })
3177
+ }
3178
+ );
3179
+ const data = await response.json().catch(() => ({}));
3180
+ if (!response.ok) {
3181
+ const msg = data && (data.error || data.message) || "Failed to request airdrop";
3182
+ return { success: false, errorMessage: String(msg) };
3183
+ }
3184
+ if (data && typeof data.error === "string") {
3185
+ return { success: false, errorMessage: data.error };
3186
+ }
3187
+ if (data && (data.txHash || data.amount)) {
3188
+ return {
3189
+ success: true,
3190
+ txHash: data.txHash,
3191
+ amount: data.amount
3192
+ };
3193
+ }
3194
+ return { success: true };
3195
+ } catch (error) {
3196
+ const msg = error?.message && typeof error.message === "string" ? error.message : "Failed to request airdrop";
3197
+ return { success: false, errorMessage: msg };
3198
+ }
3199
+ }
3167
3200
  }
3168
3201
  const relayerService = new RelayerService();
3169
3202
  const createInitialSteps = (chainBatches, customGetChainName) => {
@@ -3912,7 +3945,8 @@ const SwapWidget = ({
3912
3945
 
3913
3946
  const DepositWidget = ({
3914
3947
  depositBatches,
3915
- tokenAddress = "0x0",
3948
+ tokenAddress,
3949
+ tokenDecimals,
3916
3950
  supportedChains,
3917
3951
  theme: themeMode = "light",
3918
3952
  styles,
@@ -4102,7 +4136,10 @@ const DepositWidget = ({
4102
4136
  [
4103
4137
  {
4104
4138
  tokenAddress,
4105
- tokenAmount: parseEther(selectedDepositAsset.amount)
4139
+ tokenAmount: parseUnits(
4140
+ selectedDepositAsset.amount,
4141
+ tokenDecimals
4142
+ )
4106
4143
  }
4107
4144
  ]
4108
4145
  ]
@@ -4613,6 +4650,7 @@ const DepositWidgetModal = ({
4613
4650
  // Pass through all DepositWidget props
4614
4651
  depositBatches,
4615
4652
  tokenAddress,
4653
+ tokenDecimals,
4616
4654
  supportedChains,
4617
4655
  theme: themeMode = "light",
4618
4656
  styles,
@@ -4678,6 +4716,7 @@ const DepositWidgetModal = ({
4678
4716
  {
4679
4717
  depositBatches,
4680
4718
  tokenAddress,
4719
+ tokenDecimals,
4681
4720
  supportedChains,
4682
4721
  theme: themeMode,
4683
4722
  styles: {
@@ -6972,6 +7011,9 @@ const DepositModal = React.memo(
6972
7011
  null
6973
7012
  );
6974
7013
  const [showAirdropTooltip, setShowAirdropTooltip] = useState(false);
7014
+ const [airdropLoading, setAirdropLoading] = useState(false);
7015
+ const [airdropMessage, setAirdropMessage] = useState(null);
7016
+ const [airdropError, setAirdropError] = useState(null);
6975
7017
  const {
6976
7018
  intentStatus,
6977
7019
  startStatusPolling,
@@ -7008,13 +7050,6 @@ const DepositModal = React.memo(
7008
7050
  "Submitting deposit data to backend after bridging completes:",
7009
7051
  depositData
7010
7052
  );
7011
- for (const data of depositData) {
7012
- console.log("Calling submitSpiceDeposit with:", data);
7013
- await relayerService.submitSpiceDeposit(data);
7014
- console.log(
7015
- `Successfully submitted deposit for txHash: ${data.txHash} on chainId: ${data.chainId}`
7016
- );
7017
- }
7018
7053
  }
7019
7054
  setPostDepositStatus("success");
7020
7055
  setPostDepositAmount(bridgedAmount);
@@ -7047,6 +7082,44 @@ const DepositModal = React.memo(
7047
7082
  }, [isOpen]);
7048
7083
  useMemo(() => {
7049
7084
  }, [depositAmount]);
7085
+ const handleAirdropClick = useCallback(async () => {
7086
+ const targetAddress = sourceAddress || address;
7087
+ setAirdropMessage(null);
7088
+ setAirdropError(null);
7089
+ if (!targetAddress) {
7090
+ setAirdropError("Connect your wallet before requesting an airdrop");
7091
+ return;
7092
+ }
7093
+ const selectedChainId = selectedDepositAssets[0]?.asset?.chainId ?? supportedChains[0];
7094
+ if (!selectedChainId) {
7095
+ setAirdropError("No chain selected for airdrop");
7096
+ return;
7097
+ }
7098
+ setAirdropLoading(true);
7099
+ try {
7100
+ const result = await relayerService.requestSpiceUsdAirdrop({
7101
+ chainId: selectedChainId,
7102
+ address: targetAddress
7103
+ });
7104
+ if (!result.success) {
7105
+ setAirdropError(result.errorMessage || "Failed to request airdrop");
7106
+ return;
7107
+ }
7108
+ if (result.txHash || result.amount) {
7109
+ const amountText = result.amount ? ` ${result.amount}` : "";
7110
+ setAirdropMessage(
7111
+ `Airdrop${amountText} requested successfully. Transaction will appear shortly.`
7112
+ );
7113
+ return;
7114
+ }
7115
+ setAirdropMessage("Airdrop requested successfully.");
7116
+ } catch (e) {
7117
+ const msg = e?.message && typeof e.message === "string" ? e.message : "Failed to request airdrop";
7118
+ setAirdropError(msg);
7119
+ } finally {
7120
+ setAirdropLoading(false);
7121
+ }
7122
+ }, [address, sourceAddress, selectedDepositAssets, supportedChains]);
7050
7123
  const handleDepositAssetSelect = (asset, index) => {
7051
7124
  setSelectedDepositAssets((prev) => {
7052
7125
  const updated = [...prev];
@@ -7661,94 +7734,107 @@ const DepositModal = React.memo(
7661
7734
  style: {
7662
7735
  display: "flex",
7663
7736
  justifyContent: "flex-end",
7664
- alignItems: "center",
7737
+ alignItems: "flex-start",
7738
+ flexDirection: "column",
7665
7739
  gap: "4px",
7666
7740
  marginBottom: "8px"
7667
7741
  },
7668
7742
  children: [
7669
- /* @__PURE__ */ jsx(
7670
- "button",
7671
- {
7672
- onClick: () => {
7673
- },
7674
- style: {
7675
- padding: "4px 8px",
7676
- borderRadius: "4px",
7677
- border: "1px solid #D1D5DB",
7678
- background: "#E5E7EB",
7679
- color: "#4B5563",
7680
- fontSize: "11px",
7681
- fontWeight: 500,
7682
- cursor: "pointer",
7683
- display: "flex",
7684
- alignItems: "center",
7685
- gap: "4px",
7686
- transition: "all 0.2s",
7687
- whiteSpace: "nowrap"
7688
- },
7689
- onMouseEnter: (e) => {
7690
- e.currentTarget.style.color = "#1F2937";
7691
- e.currentTarget.style.background = "#D1D5DB";
7692
- },
7693
- onMouseLeave: (e) => {
7694
- e.currentTarget.style.color = "#4B5563";
7695
- e.currentTarget.style.background = "#E5E7EB";
7696
- },
7697
- children: "Airdrop"
7698
- }
7699
- ),
7700
7743
  /* @__PURE__ */ jsxs(
7701
7744
  "div",
7702
7745
  {
7703
- onMouseEnter: () => setShowAirdropTooltip(true),
7704
- onMouseLeave: () => setShowAirdropTooltip(false),
7705
7746
  style: {
7706
- position: "relative",
7707
- width: "14px",
7708
- height: "14px",
7709
- borderRadius: "50%",
7710
- backgroundColor: "#9CA3AF",
7711
- color: "white",
7712
7747
  display: "flex",
7748
+ justifyContent: "flex-end",
7713
7749
  alignItems: "center",
7714
- justifyContent: "center",
7715
- fontSize: "9px",
7716
- fontWeight: "bold",
7717
- cursor: "help"
7750
+ gap: "4px"
7718
7751
  },
7719
7752
  children: [
7720
- "i",
7721
- showAirdropTooltip && /* @__PURE__ */ jsxs(
7753
+ /* @__PURE__ */ jsx(
7754
+ "button",
7755
+ {
7756
+ onClick: handleAirdropClick,
7757
+ style: {
7758
+ padding: "4px 8px",
7759
+ borderRadius: "4px",
7760
+ border: "1px solid #D1D5DB",
7761
+ background: "#E5E7EB",
7762
+ color: "#4B5563",
7763
+ fontSize: "11px",
7764
+ fontWeight: 500,
7765
+ cursor: airdropLoading ? "default" : "pointer",
7766
+ display: "flex",
7767
+ alignItems: "center",
7768
+ gap: "4px",
7769
+ transition: "all 0.2s",
7770
+ whiteSpace: "nowrap"
7771
+ },
7772
+ onMouseEnter: (e) => {
7773
+ e.currentTarget.style.color = "#1F2937";
7774
+ e.currentTarget.style.background = "#D1D5DB";
7775
+ },
7776
+ onMouseLeave: (e) => {
7777
+ e.currentTarget.style.color = "#4B5563";
7778
+ e.currentTarget.style.background = "#E5E7EB";
7779
+ },
7780
+ children: airdropLoading ? "Requesting..." : "Airdrop"
7781
+ }
7782
+ ),
7783
+ /* @__PURE__ */ jsxs(
7722
7784
  "div",
7723
7785
  {
7786
+ onMouseEnter: () => setShowAirdropTooltip(true),
7787
+ onMouseLeave: () => setShowAirdropTooltip(false),
7724
7788
  style: {
7725
- position: "absolute",
7726
- bottom: "calc(100% + 8px)",
7727
- right: 0,
7728
- backgroundColor: "#1F2937",
7789
+ position: "relative",
7790
+ width: "14px",
7791
+ height: "14px",
7792
+ borderRadius: "50%",
7793
+ backgroundColor: "#9CA3AF",
7729
7794
  color: "white",
7730
- padding: "8px 12px",
7731
- borderRadius: "6px",
7732
- fontSize: "12px",
7733
- whiteSpace: "nowrap",
7734
- boxShadow: "0 4px 6px rgba(0, 0, 0, 0.1)",
7735
- zIndex: 100
7795
+ display: "flex",
7796
+ alignItems: "center",
7797
+ justifyContent: "center",
7798
+ fontSize: "9px",
7799
+ fontWeight: "bold",
7800
+ cursor: "help"
7736
7801
  },
7737
7802
  children: [
7738
- "This is testnet USDC, and it won't be available on mainnet",
7739
- /* @__PURE__ */ jsx(
7803
+ "i",
7804
+ showAirdropTooltip && /* @__PURE__ */ jsxs(
7740
7805
  "div",
7741
7806
  {
7742
7807
  style: {
7743
7808
  position: "absolute",
7744
- top: "100%",
7745
- right: "10px",
7746
- width: 0,
7747
- height: 0,
7748
- borderLeft: "6px solid transparent",
7749
- borderRight: "6px solid transparent",
7750
- borderTop: "6px solid #1F2937"
7751
- }
7809
+ bottom: "calc(100% + 8px)",
7810
+ right: 0,
7811
+ backgroundColor: "#1F2937",
7812
+ color: "white",
7813
+ padding: "8px 12px",
7814
+ borderRadius: "6px",
7815
+ fontSize: "12px",
7816
+ whiteSpace: "nowrap",
7817
+ boxShadow: "0 4px 6px rgba(0, 0, 0, 0.1)",
7818
+ zIndex: 100
7819
+ },
7820
+ children: [
7821
+ "This is testnet USDC, and it won't be available on mainnet",
7822
+ /* @__PURE__ */ jsx(
7823
+ "div",
7824
+ {
7825
+ style: {
7826
+ position: "absolute",
7827
+ top: "100%",
7828
+ right: "10px",
7829
+ width: 0,
7830
+ height: 0,
7831
+ borderLeft: "6px solid transparent",
7832
+ borderRight: "6px solid transparent",
7833
+ borderTop: "6px solid #1F2937"
7834
+ }
7835
+ }
7836
+ )
7837
+ ]
7752
7838
  }
7753
7839
  )
7754
7840
  ]
@@ -7756,6 +7842,18 @@ const DepositModal = React.memo(
7756
7842
  )
7757
7843
  ]
7758
7844
  }
7845
+ ),
7846
+ (airdropMessage || airdropError) && /* @__PURE__ */ jsx(
7847
+ "div",
7848
+ {
7849
+ style: {
7850
+ marginTop: "6px",
7851
+ fontSize: "11px",
7852
+ color: airdropError ? "#b91c1c" : "#047857",
7853
+ fontFamily: styles?.fontFamily || theme.typography.fontFamily
7854
+ },
7855
+ children: airdropError || airdropMessage
7856
+ }
7759
7857
  )
7760
7858
  ]
7761
7859
  }
@@ -7834,8 +7932,7 @@ const DepositModal = React.memo(
7834
7932
  /* @__PURE__ */ jsx(
7835
7933
  "button",
7836
7934
  {
7837
- onClick: () => {
7838
- },
7935
+ onClick: handleAirdropClick,
7839
7936
  style: {
7840
7937
  padding: "4px 8px",
7841
7938
  borderRadius: "4px",
@@ -7844,7 +7941,7 @@ const DepositModal = React.memo(
7844
7941
  color: "#4B5563",
7845
7942
  fontSize: "11px",
7846
7943
  fontWeight: 500,
7847
- cursor: "pointer",
7944
+ cursor: airdropLoading ? "default" : "pointer",
7848
7945
  display: "flex",
7849
7946
  alignItems: "center",
7850
7947
  gap: "4px",
@@ -7859,7 +7956,7 @@ const DepositModal = React.memo(
7859
7956
  e.currentTarget.style.color = "#4B5563";
7860
7957
  e.currentTarget.style.background = "#E5E7EB";
7861
7958
  },
7862
- children: "Airdrop"
7959
+ children: airdropLoading ? "Requesting..." : "Airdrop"
7863
7960
  }
7864
7961
  ),
7865
7962
  /* @__PURE__ */ jsxs(
@@ -7921,6 +8018,18 @@ const DepositModal = React.memo(
7921
8018
  )
7922
8019
  ]
7923
8020
  }
8021
+ ),
8022
+ (airdropMessage || airdropError) && /* @__PURE__ */ jsx(
8023
+ "div",
8024
+ {
8025
+ style: {
8026
+ marginTop: "6px",
8027
+ fontSize: "11px",
8028
+ color: airdropError ? "#b91c1c" : "#047857",
8029
+ fontFamily: styles?.fontFamily || theme.typography.fontFamily
8030
+ },
8031
+ children: airdropError || airdropMessage
8032
+ }
7924
8033
  )
7925
8034
  ]
7926
8035
  }
@@ -10010,105 +10119,8 @@ const formatCurrencyWithDecimals = (amount) => {
10010
10119
  maximumFractionDigits: 5
10011
10120
  }).format(rounded);
10012
10121
  };
10013
- const defaultBalanceData = {
10014
- totalBalance: 10333,
10015
- percentageChange: 2.15,
10016
- tradingAccounts: [
10017
- { id: "hyperliquid", name: "HYPERLIQUID", balance: 800 },
10018
- { id: "lighter", name: "LIGHTER", balance: 1200 }
10019
- ],
10020
- freeCollateral: 8e3,
10021
- freeCollateralItems: [
10022
- {
10023
- id: "usdc-eth",
10024
- name: "USDC",
10025
- balance: 3e3,
10026
- subtitle: "USD COIN",
10027
- iconColor: "#2775CA",
10028
- networks: [11155111]
10029
- },
10030
- // Ethereum Sepolia
10031
- {
10032
- id: "usdc-arb",
10033
- name: "USDC",
10034
- balance: 2e3,
10035
- subtitle: "USD COIN",
10036
- iconColor: "#2775CA",
10037
- networks: [42161]
10038
- },
10039
- // Arbitrum
10040
- {
10041
- id: "usdc-base",
10042
- name: "USDC",
10043
- balance: 1500,
10044
- subtitle: "USD COIN",
10045
- iconColor: "#2775CA",
10046
- networks: [84532]
10047
- },
10048
- // Base Sepolia
10049
- {
10050
- id: "weth",
10051
- name: "WETH",
10052
- balance: 500,
10053
- subtitle: "WRAPPED ETH",
10054
- iconColor: "#627EEA",
10055
- networks: [11155111]
10056
- },
10057
- {
10058
- id: "uniswap-pt",
10059
- name: "UNISWAP PT",
10060
- balance: 500,
10061
- iconColor: "#FF007A",
10062
- networks: [11155111]
10063
- },
10064
- {
10065
- id: "pendle-pt",
10066
- name: "PENDLE PT",
10067
- balance: 500,
10068
- iconColor: "#6366F1",
10069
- networks: [11155111]
10070
- }
10071
- ],
10072
- defiPositions: 2333,
10073
- defiPositionsItems: [
10074
- {
10075
- id: "uniswap-v4",
10076
- name: "UNISWAP V4",
10077
- balance: 1166.5,
10078
- iconColor: "#FF007A"
10079
- },
10080
- {
10081
- id: "pendle-pt-defi",
10082
- name: "PENDLE PT",
10083
- balance: 1166.5,
10084
- iconColor: "#6366F1"
10085
- }
10086
- ],
10087
- credit: 2333,
10088
- creditItems: [
10089
- {
10090
- id: "usdc-credit",
10091
- name: "USDC",
10092
- balance: 1e3,
10093
- subtitle: "USD COIN",
10094
- iconColor: "#2775CA"
10095
- },
10096
- {
10097
- id: "uniswap-lp",
10098
- name: "UNISWAP LP",
10099
- balance: 666.5,
10100
- iconColor: "#FF007A"
10101
- },
10102
- {
10103
- id: "pendle-pt-credit",
10104
- name: "PENDLE PT",
10105
- balance: 666.5,
10106
- iconColor: "#6366F1"
10107
- }
10108
- ]
10109
- };
10110
10122
  const SpiceBalance = ({
10111
- balanceData = defaultBalanceData,
10123
+ balanceData,
10112
10124
  isLoading = false,
10113
10125
  styles,
10114
10126
  className = "",
@@ -10204,24 +10216,6 @@ const SpiceBalance = ({
10204
10216
  balanceData.freeCollateralItems,
10205
10217
  balanceData.freeCollateral
10206
10218
  ]);
10207
- useMemo(() => {
10208
- if (balanceData.defiPositionsItems) {
10209
- return balanceData.defiPositionsItems.reduce(
10210
- (sum, item) => sum + item.balance,
10211
- 0
10212
- );
10213
- }
10214
- return balanceData.defiPositions;
10215
- }, [balanceData.defiPositionsItems, balanceData.defiPositions]);
10216
- useMemo(() => {
10217
- if (balanceData.creditItems) {
10218
- return balanceData.creditItems.reduce(
10219
- (sum, item) => sum + item.balance,
10220
- 0
10221
- );
10222
- }
10223
- return balanceData.credit;
10224
- }, [balanceData.creditItems, balanceData.credit]);
10225
10219
  const maskBalance = (value) => {
10226
10220
  return isBalanceVisible ? value : "******";
10227
10221
  };
@@ -11956,7 +11950,7 @@ const LpModal = ({
11956
11950
  };
11957
11951
 
11958
11952
  const useFromInput = () => {
11959
- const [fromAmount, setFromAmount] = useState("");
11953
+ const [fromAmount, setFromAmount] = useState("0");
11960
11954
  return {
11961
11955
  fromAmount,
11962
11956
  setFromAmount
@@ -11964,7 +11958,7 @@ const useFromInput = () => {
11964
11958
  };
11965
11959
 
11966
11960
  const useToInputUpdate = () => {
11967
- const [toAmount, setToAmount] = useState("");
11961
+ const [toAmount, setToAmount] = useState("0");
11968
11962
  const updateToAmount = useCallback((amount) => {
11969
11963
  setToAmount(amount);
11970
11964
  }, []);
@@ -11976,7 +11970,7 @@ const useToInputUpdate = () => {
11976
11970
  };
11977
11971
 
11978
11972
  const useDepositInput = () => {
11979
- const [depositAmount, setDepositAmount] = useState("");
11973
+ const [depositAmount, setDepositAmount] = useState("0");
11980
11974
  return {
11981
11975
  depositAmount,
11982
11976
  setDepositAmount
@@ -34,7 +34,7 @@ export interface BalanceData {
34
34
  creditItems?: AccountItem[];
35
35
  }
36
36
  export interface SpiceBalanceProps {
37
- balanceData?: BalanceData;
37
+ balanceData: BalanceData;
38
38
  isLoading?: boolean;
39
39
  onRefresh?: () => void;
40
40
  styles?: any;
@@ -19,7 +19,8 @@ export interface SpiceDepositResponse {
19
19
  }
20
20
  export interface DepositWidgetProps {
21
21
  depositBatches: ChainBatch[];
22
- tokenAddress?: Address;
22
+ tokenAddress: Address;
23
+ tokenDecimals: number;
23
24
  supportedChains: number[];
24
25
  theme?: ThemeMode;
25
26
  styles?: CustomStyles;
@@ -54,6 +54,15 @@ export declare class RelayerService {
54
54
  status: "pending" | "processing" | "success" | "failed";
55
55
  };
56
56
  }>;
57
+ requestSpiceUsdAirdrop(params: {
58
+ chainId: number;
59
+ address: string;
60
+ }): Promise<{
61
+ success: boolean;
62
+ txHash?: string;
63
+ amount?: string;
64
+ errorMessage?: string;
65
+ }>;
57
66
  }
58
67
  export declare const relayerService: RelayerService;
59
68
  export declare const createInitialSteps: (chainBatches: ChainBatch[], customGetChainName?: (chainId: number) => string) => SwapStep[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spicenet-io/spiceflow-ui",
3
- "version": "1.7.2",
3
+ "version": "1.7.3",
4
4
  "description": "Spiceflow UI SDK",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs.js",