@spicenet-io/spiceflow-ui 1.8.1 → 1.8.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/hooks/index.d.ts +2 -0
- package/dist/hooks/useSpiceAssets/index.d.ts +27 -0
- package/dist/index.cjs.js +161 -29
- package/dist/index.d.ts +1 -0
- package/dist/index.js +161 -30
- package/dist/utils/relayer/index.d.ts +1 -0
- package/package.json +1 -1
package/dist/hooks/index.d.ts
CHANGED
|
@@ -13,3 +13,5 @@ export type { UseWalletReturn, WalletState, WalletActions } from "./useWallet";
|
|
|
13
13
|
export { useEmbeddedWalletAddress } from "./useEmbeddedWalletAddress";
|
|
14
14
|
export { useSpiceBalance } from "./useSpiceBalance";
|
|
15
15
|
export type { UseSpiceBalanceConfig, UseSpiceBalanceReturn, SpiceBalanceApiResponse, } from "./useSpiceBalance";
|
|
16
|
+
export { useSpiceAssets } from "./useSpiceAssets";
|
|
17
|
+
export type { UseSpiceAssetsConfig, UseSpiceAssetsReturn, } from "./useSpiceAssets";
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Address } from "viem";
|
|
2
|
+
import { Asset } from "../../types/assets";
|
|
3
|
+
export interface SpiceBalanceApiResponse {
|
|
4
|
+
success: boolean;
|
|
5
|
+
data?: {
|
|
6
|
+
tokens: {
|
|
7
|
+
[chainId: string]: {
|
|
8
|
+
[tokenAddress: string]: string;
|
|
9
|
+
};
|
|
10
|
+
};
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
export interface UseSpiceAssetsConfig {
|
|
14
|
+
address?: Address | string;
|
|
15
|
+
supportedChains?: number[];
|
|
16
|
+
enabled?: boolean;
|
|
17
|
+
refetchInterval?: number;
|
|
18
|
+
}
|
|
19
|
+
export interface UseSpiceAssetsReturn {
|
|
20
|
+
assets: Asset[];
|
|
21
|
+
loading: boolean;
|
|
22
|
+
error: string | null;
|
|
23
|
+
hasBalance: boolean;
|
|
24
|
+
refetch: () => Promise<void>;
|
|
25
|
+
getAssetsByChain: (chainId: number) => Asset[];
|
|
26
|
+
}
|
|
27
|
+
export declare const useSpiceAssets: ({ address, supportedChains, enabled, refetchInterval, }: UseSpiceAssetsConfig) => UseSpiceAssetsReturn;
|
package/dist/index.cjs.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
+
const viem = require('viem');
|
|
5
|
+
const chains = require('viem/chains');
|
|
4
6
|
const jsxRuntime = require('react/jsx-runtime');
|
|
5
7
|
const React = require('react');
|
|
6
|
-
const viem = require('viem');
|
|
7
8
|
const Button = require('./Button-D2yFTia-.js');
|
|
8
9
|
const actions = require('viem/actions');
|
|
9
|
-
const chains = require('viem/chains');
|
|
10
10
|
const reactDom = require('react-dom');
|
|
11
11
|
const reactAuth = require('@privy-io/react-auth');
|
|
12
12
|
const sdkReactCore = require('@dynamic-labs/sdk-react-core');
|
|
@@ -3074,6 +3074,7 @@ class RelayerService {
|
|
|
3074
3074
|
}
|
|
3075
3075
|
}
|
|
3076
3076
|
async submitSpiceDeposit(request) {
|
|
3077
|
+
const depositType = request.isDeposit ? "deposit" : "withdrawal";
|
|
3077
3078
|
try {
|
|
3078
3079
|
const response = await fetch(`${this.baseUrl}/spicedeposit`, {
|
|
3079
3080
|
method: "POST",
|
|
@@ -3084,13 +3085,16 @@ class RelayerService {
|
|
|
3084
3085
|
});
|
|
3085
3086
|
const data = await response.json();
|
|
3086
3087
|
if (!response.ok || !data.success) {
|
|
3087
|
-
console.error(
|
|
3088
|
+
console.error(
|
|
3089
|
+
`Failed to submit ${depositType} request to API:`,
|
|
3090
|
+
data.error?.message
|
|
3091
|
+
);
|
|
3088
3092
|
return { success: false, error: data.error };
|
|
3089
3093
|
}
|
|
3090
|
-
console.log(
|
|
3094
|
+
console.log(`${depositType} request successfully submitted to API`);
|
|
3091
3095
|
return data;
|
|
3092
3096
|
} catch (error) {
|
|
3093
|
-
console.error(
|
|
3097
|
+
console.error(`Error submitting ${depositType} request to API:`, error);
|
|
3094
3098
|
return {
|
|
3095
3099
|
success: false,
|
|
3096
3100
|
error: {
|
|
@@ -3952,6 +3956,133 @@ const SwapWidget = ({
|
|
|
3952
3956
|
] });
|
|
3953
3957
|
};
|
|
3954
3958
|
|
|
3959
|
+
const useSpiceAssets = ({
|
|
3960
|
+
address,
|
|
3961
|
+
supportedChains,
|
|
3962
|
+
enabled = true,
|
|
3963
|
+
refetchInterval
|
|
3964
|
+
}) => {
|
|
3965
|
+
const [assets, setAssets] = React.useState([]);
|
|
3966
|
+
const [loading, setLoading] = React.useState(false);
|
|
3967
|
+
const [error, setError] = React.useState(null);
|
|
3968
|
+
const [hasBalance, setHasBalance] = React.useState(false);
|
|
3969
|
+
const fetchAssets = React.useCallback(async () => {
|
|
3970
|
+
if (!address || !enabled) {
|
|
3971
|
+
setAssets([]);
|
|
3972
|
+
setHasBalance(false);
|
|
3973
|
+
return;
|
|
3974
|
+
}
|
|
3975
|
+
setLoading(true);
|
|
3976
|
+
setError(null);
|
|
3977
|
+
try {
|
|
3978
|
+
const response = await fetch(
|
|
3979
|
+
`${RELAYER_API_URL}/spicedeposit/${address}`
|
|
3980
|
+
);
|
|
3981
|
+
if (!response.ok) {
|
|
3982
|
+
throw new Error(`Failed to fetch balance: ${response.status}`);
|
|
3983
|
+
}
|
|
3984
|
+
const result = await response.json();
|
|
3985
|
+
if (result.success && result.data?.tokens) {
|
|
3986
|
+
const tokens = result.data.tokens;
|
|
3987
|
+
const parsedAssets = [];
|
|
3988
|
+
Object.keys(tokens).forEach((chainIdStr) => {
|
|
3989
|
+
const chainId = parseInt(chainIdStr);
|
|
3990
|
+
if (supportedChains && !supportedChains.includes(chainId)) {
|
|
3991
|
+
return;
|
|
3992
|
+
}
|
|
3993
|
+
const chainTokens = tokens[chainIdStr];
|
|
3994
|
+
const chainConfig = getChainConfig(chainId);
|
|
3995
|
+
if (chainTokens && typeof chainTokens === "object") {
|
|
3996
|
+
Object.keys(chainTokens).forEach((tokenAddress) => {
|
|
3997
|
+
const rawBalanceStr = chainTokens[tokenAddress];
|
|
3998
|
+
const rawBalance = BigInt(rawBalanceStr || "0");
|
|
3999
|
+
if (rawBalance > BigInt(0)) {
|
|
4000
|
+
const isNative = tokenAddress.toLowerCase() === "0x0" || tokenAddress.toLowerCase() === "0x0000000000000000000000000000000000000000" || tokenAddress.toLowerCase() === "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee";
|
|
4001
|
+
let decimals = 18;
|
|
4002
|
+
let symbol = "TOKEN";
|
|
4003
|
+
let name = tokenAddress.slice(0, 6) + "..." + tokenAddress.slice(-4);
|
|
4004
|
+
let logoURI;
|
|
4005
|
+
if (isNative) {
|
|
4006
|
+
decimals = chainConfig?.nativeCurrency?.decimals || 18;
|
|
4007
|
+
symbol = chainConfig?.nativeCurrency?.symbol || "ETH";
|
|
4008
|
+
name = chainConfig?.nativeCurrency?.name || "Native Token";
|
|
4009
|
+
} else {
|
|
4010
|
+
const tokenConfig = chainConfig?.supportedTokens?.find(
|
|
4011
|
+
(t) => t.address.toLowerCase() === tokenAddress.toLowerCase()
|
|
4012
|
+
);
|
|
4013
|
+
if (tokenConfig) {
|
|
4014
|
+
decimals = tokenConfig.decimals;
|
|
4015
|
+
symbol = tokenConfig.symbol;
|
|
4016
|
+
name = tokenConfig.name;
|
|
4017
|
+
logoURI = tokenConfig.logoURI;
|
|
4018
|
+
}
|
|
4019
|
+
}
|
|
4020
|
+
const balanceFormatted = parseFloat(
|
|
4021
|
+
(Number(rawBalance) / Math.pow(10, decimals)).toFixed(6)
|
|
4022
|
+
);
|
|
4023
|
+
if (balanceFormatted > 0) {
|
|
4024
|
+
parsedAssets.push({
|
|
4025
|
+
address: isNative ? "0x0000000000000000000000000000000000000000" : tokenAddress,
|
|
4026
|
+
symbol,
|
|
4027
|
+
name,
|
|
4028
|
+
decimals,
|
|
4029
|
+
chainId,
|
|
4030
|
+
balance: rawBalance,
|
|
4031
|
+
balanceFormatted,
|
|
4032
|
+
balanceUsd: 0,
|
|
4033
|
+
// API doesn't provide USD value
|
|
4034
|
+
isNative,
|
|
4035
|
+
logoURI
|
|
4036
|
+
});
|
|
4037
|
+
}
|
|
4038
|
+
}
|
|
4039
|
+
});
|
|
4040
|
+
}
|
|
4041
|
+
});
|
|
4042
|
+
setAssets(parsedAssets);
|
|
4043
|
+
setHasBalance(parsedAssets.length > 0);
|
|
4044
|
+
} else {
|
|
4045
|
+
setAssets([]);
|
|
4046
|
+
setHasBalance(false);
|
|
4047
|
+
}
|
|
4048
|
+
} catch (err) {
|
|
4049
|
+
const errorMessage = err instanceof Error ? err.message : "Failed to fetch balance";
|
|
4050
|
+
setError(errorMessage);
|
|
4051
|
+
console.error("Error fetching Spice assets:", err);
|
|
4052
|
+
setAssets([]);
|
|
4053
|
+
setHasBalance(false);
|
|
4054
|
+
} finally {
|
|
4055
|
+
setLoading(false);
|
|
4056
|
+
}
|
|
4057
|
+
}, [address, enabled, supportedChains]);
|
|
4058
|
+
React.useEffect(() => {
|
|
4059
|
+
if (enabled && address) {
|
|
4060
|
+
fetchAssets();
|
|
4061
|
+
}
|
|
4062
|
+
}, [address, enabled, fetchAssets]);
|
|
4063
|
+
React.useEffect(() => {
|
|
4064
|
+
if (!enabled || !address || !refetchInterval) return;
|
|
4065
|
+
const interval = setInterval(() => {
|
|
4066
|
+
fetchAssets();
|
|
4067
|
+
}, refetchInterval);
|
|
4068
|
+
return () => clearInterval(interval);
|
|
4069
|
+
}, [address, enabled, refetchInterval, fetchAssets]);
|
|
4070
|
+
const getAssetsByChain = React.useCallback(
|
|
4071
|
+
(chainId) => {
|
|
4072
|
+
return assets.filter((asset) => asset.chainId === chainId);
|
|
4073
|
+
},
|
|
4074
|
+
[assets]
|
|
4075
|
+
);
|
|
4076
|
+
return {
|
|
4077
|
+
assets,
|
|
4078
|
+
loading,
|
|
4079
|
+
error,
|
|
4080
|
+
hasBalance,
|
|
4081
|
+
refetch: fetchAssets,
|
|
4082
|
+
getAssetsByChain
|
|
4083
|
+
};
|
|
4084
|
+
};
|
|
4085
|
+
|
|
3955
4086
|
const DepositWidget = ({
|
|
3956
4087
|
depositBatches,
|
|
3957
4088
|
tokenAddress,
|
|
@@ -3991,14 +4122,15 @@ const DepositWidget = ({
|
|
|
3991
4122
|
const [selectedDepositAsset, setSelectedDepositAsset] = React.useState(null);
|
|
3992
4123
|
const [isPending, startTransition] = React.useTransition();
|
|
3993
4124
|
const {
|
|
3994
|
-
assets,
|
|
3995
|
-
loading:
|
|
3996
|
-
error:
|
|
3997
|
-
|
|
3998
|
-
} =
|
|
4125
|
+
assets: spiceAssets,
|
|
4126
|
+
loading: loadingSpiceAssets,
|
|
4127
|
+
error: spiceAssetsError,
|
|
4128
|
+
refetch: refreshSpiceAssets
|
|
4129
|
+
} = useSpiceAssets({
|
|
3999
4130
|
address,
|
|
4000
4131
|
supportedChains,
|
|
4001
|
-
|
|
4132
|
+
enabled: isConnected,
|
|
4133
|
+
refetchInterval: 3e4
|
|
4002
4134
|
});
|
|
4003
4135
|
const [isExecuting, setIsExecuting] = React.useState(false);
|
|
4004
4136
|
const [error, setError] = React.useState(null);
|
|
@@ -4162,7 +4294,7 @@ const DepositWidget = ({
|
|
|
4162
4294
|
const initialSteps = createInitialSteps(allChainBatches, getChainName);
|
|
4163
4295
|
startStatusPolling(result.intentId, initialSteps);
|
|
4164
4296
|
onDepositSuccess?.(result.intentId);
|
|
4165
|
-
|
|
4297
|
+
refreshSpiceAssets();
|
|
4166
4298
|
}
|
|
4167
4299
|
} catch (error2) {
|
|
4168
4300
|
const errorMessage = error2 instanceof Error ? error2.message : "Deposit failed";
|
|
@@ -4172,23 +4304,18 @@ const DepositWidget = ({
|
|
|
4172
4304
|
setIsExecuting(false);
|
|
4173
4305
|
}
|
|
4174
4306
|
};
|
|
4175
|
-
const
|
|
4176
|
-
const allAssets = supportedChains.flatMap(
|
|
4177
|
-
(chainId) => getAllAssetsForChain(chainId, assets)
|
|
4178
|
-
);
|
|
4179
|
-
console.log("allAssets", allAssets);
|
|
4180
|
-
console.log("supportedTokens", supportedTokens);
|
|
4307
|
+
const spiceDepositAssets = React.useMemo(() => {
|
|
4181
4308
|
if (supportedTokens && supportedTokens.length > 0) {
|
|
4182
|
-
return
|
|
4309
|
+
return spiceAssets.filter(
|
|
4183
4310
|
(asset) => supportedTokens.some(
|
|
4184
4311
|
(symbol) => symbol.toLowerCase() === asset.symbol.toLowerCase()
|
|
4185
4312
|
)
|
|
4186
4313
|
);
|
|
4187
4314
|
}
|
|
4188
|
-
return
|
|
4189
|
-
}, [
|
|
4315
|
+
return spiceAssets;
|
|
4316
|
+
}, [spiceAssets, supportedTokens]);
|
|
4190
4317
|
const canDeposit = selectedDepositAsset && selectedDepositAsset.amount && parseFloat(selectedDepositAsset.amount) > 0 && parseFloat(selectedDepositAsset.amount) <= selectedDepositAsset.asset.balanceFormatted && isConnected && !isExecuting && depositBatches.length > 0;
|
|
4191
|
-
const displayError =
|
|
4318
|
+
const displayError = spiceAssetsError || error;
|
|
4192
4319
|
const containerStyles = {
|
|
4193
4320
|
backgroundColor: styles?.container?.backgroundColor || styles?.primaryBackground || theme.colors.background,
|
|
4194
4321
|
border: `1px solid ${styles?.container?.borderColor || theme.colors.border}`,
|
|
@@ -4215,7 +4342,7 @@ const DepositWidget = ({
|
|
|
4215
4342
|
onNewTx: () => {
|
|
4216
4343
|
clearStatus();
|
|
4217
4344
|
setSelectedDepositAsset(null);
|
|
4218
|
-
|
|
4345
|
+
refreshSpiceAssets();
|
|
4219
4346
|
},
|
|
4220
4347
|
explorerUrlBuilder: (chainId, txHash) => getExplorerUrl(chainId, txHash),
|
|
4221
4348
|
theme
|
|
@@ -4344,11 +4471,11 @@ const DepositWidget = ({
|
|
|
4344
4471
|
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { marginBottom: theme.spacing.sm }, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4345
4472
|
AssetSelector,
|
|
4346
4473
|
{
|
|
4347
|
-
assets:
|
|
4474
|
+
assets: spiceDepositAssets,
|
|
4348
4475
|
selectedAsset: selectedDepositAsset || void 0,
|
|
4349
4476
|
onAssetSelect: handleDepositAssetSelect,
|
|
4350
4477
|
onAmountChange: handleDepositAmountChange,
|
|
4351
|
-
loading:
|
|
4478
|
+
loading: loadingSpiceAssets,
|
|
4352
4479
|
label: "Deposit",
|
|
4353
4480
|
showBalance: true,
|
|
4354
4481
|
showMaxButton: true,
|
|
@@ -7643,7 +7770,8 @@ const DepositModal = React.memo(
|
|
|
7643
7770
|
tokenAddress,
|
|
7644
7771
|
chainId,
|
|
7645
7772
|
amount: amount.toString(),
|
|
7646
|
-
user: address
|
|
7773
|
+
user: address,
|
|
7774
|
+
isDeposit: true
|
|
7647
7775
|
});
|
|
7648
7776
|
await relayerService.submitSpiceDeposit({
|
|
7649
7777
|
txHash: transferToEmbeddedTx,
|
|
@@ -7651,7 +7779,8 @@ const DepositModal = React.memo(
|
|
|
7651
7779
|
tokenAddress,
|
|
7652
7780
|
chainId,
|
|
7653
7781
|
amount: amount.toString(),
|
|
7654
|
-
user: address
|
|
7782
|
+
user: address,
|
|
7783
|
+
isDeposit: true
|
|
7655
7784
|
});
|
|
7656
7785
|
console.log(
|
|
7657
7786
|
`Successfully submitted deposit for txHash: ${transferToEmbeddedTx}`
|
|
@@ -9253,7 +9382,8 @@ const WithdrawModal = React.memo(
|
|
|
9253
9382
|
sender: externalWalletAddress,
|
|
9254
9383
|
tokenAddress: apiTokenAddress,
|
|
9255
9384
|
chainId: destinationChainId,
|
|
9256
|
-
amount: amount2.toString()
|
|
9385
|
+
amount: amount2.toString(),
|
|
9386
|
+
isDeposit: false
|
|
9257
9387
|
});
|
|
9258
9388
|
const depositResult = await relayerService.submitSpiceDeposit({
|
|
9259
9389
|
user: externalWalletAddress,
|
|
@@ -9261,7 +9391,8 @@ const WithdrawModal = React.memo(
|
|
|
9261
9391
|
sender: externalWalletAddress,
|
|
9262
9392
|
tokenAddress: apiTokenAddress,
|
|
9263
9393
|
chainId: destinationChainId,
|
|
9264
|
-
amount: amount2.toString()
|
|
9394
|
+
amount: amount2.toString(),
|
|
9395
|
+
isDeposit: false
|
|
9265
9396
|
});
|
|
9266
9397
|
if (!depositResult.success) {
|
|
9267
9398
|
console.error(
|
|
@@ -12153,6 +12284,7 @@ exports.SpiceWithdraw = SpiceWithdraw;
|
|
|
12153
12284
|
exports.SwapWidget = SwapWidget;
|
|
12154
12285
|
exports.WithdrawModal = WithdrawModal;
|
|
12155
12286
|
exports.fetchBalances = fetchBalances;
|
|
12287
|
+
exports.relayerService = relayerService;
|
|
12156
12288
|
exports.useAssets = useAssets;
|
|
12157
12289
|
exports.useDepositInput = useDepositInput;
|
|
12158
12290
|
exports.useFromInput = useFromInput;
|
package/dist/index.d.ts
CHANGED
|
@@ -21,3 +21,4 @@ export type { LpModalProps } from "./types/lp";
|
|
|
21
21
|
export { useAssets, fetchBalances, useStatus, useFromInput, useToInputUpdate, useDepositInput, useWallet, useSpiceBalance, } from "./hooks";
|
|
22
22
|
export type { UseAssetsConfig, UseAssetsReturn, UseStatusConfig, UseStatusReturn, UseFromInputReturn, UseToInputUpdateReturn, UseDepositInputReturn, UseWalletReturn, WalletState, WalletActions, UseSpiceBalanceConfig, UseSpiceBalanceReturn, SpiceBalanceApiResponse, } from "./hooks";
|
|
23
23
|
export type { WalletProvider, WalletLoginProps, ProviderConfig, } from "./types/wallet";
|
|
24
|
+
export { relayerService } from "./utils/relayer";
|
package/dist/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
"use client";
|
|
2
|
+
import { defineChain, createPublicClient, http, isAddress, getAddress, parseEther, encodeFunctionData, parseUnits, erc20Abi } from 'viem';
|
|
3
|
+
import { basecampTestnet, citreaTestnet, baseSepolia, arbitrumSepolia, sepolia } from 'viem/chains';
|
|
2
4
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
3
5
|
import React, { useState, useRef, useEffect, useCallback, createContext, useContext, useTransition, useMemo, forwardRef, createElement } from 'react';
|
|
4
|
-
import { defineChain, createPublicClient, http, isAddress, getAddress, parseEther, encodeFunctionData, parseUnits, erc20Abi } from 'viem';
|
|
5
6
|
import { c as createTheme, B as Button, d as defaultTheme } from './Button-aWXByNBC.js';
|
|
6
7
|
import { getBalance, readContract } from 'viem/actions';
|
|
7
|
-
import { basecampTestnet, citreaTestnet, baseSepolia, arbitrumSepolia, sepolia } from 'viem/chains';
|
|
8
8
|
import { createPortal } from 'react-dom';
|
|
9
9
|
import { useWallets, usePrivy, useSign7702Authorization, useSignMessage } from '@privy-io/react-auth';
|
|
10
10
|
import { useDynamicContext } from '@dynamic-labs/sdk-react-core';
|
|
@@ -3072,6 +3072,7 @@ class RelayerService {
|
|
|
3072
3072
|
}
|
|
3073
3073
|
}
|
|
3074
3074
|
async submitSpiceDeposit(request) {
|
|
3075
|
+
const depositType = request.isDeposit ? "deposit" : "withdrawal";
|
|
3075
3076
|
try {
|
|
3076
3077
|
const response = await fetch(`${this.baseUrl}/spicedeposit`, {
|
|
3077
3078
|
method: "POST",
|
|
@@ -3082,13 +3083,16 @@ class RelayerService {
|
|
|
3082
3083
|
});
|
|
3083
3084
|
const data = await response.json();
|
|
3084
3085
|
if (!response.ok || !data.success) {
|
|
3085
|
-
console.error(
|
|
3086
|
+
console.error(
|
|
3087
|
+
`Failed to submit ${depositType} request to API:`,
|
|
3088
|
+
data.error?.message
|
|
3089
|
+
);
|
|
3086
3090
|
return { success: false, error: data.error };
|
|
3087
3091
|
}
|
|
3088
|
-
console.log(
|
|
3092
|
+
console.log(`${depositType} request successfully submitted to API`);
|
|
3089
3093
|
return data;
|
|
3090
3094
|
} catch (error) {
|
|
3091
|
-
console.error(
|
|
3095
|
+
console.error(`Error submitting ${depositType} request to API:`, error);
|
|
3092
3096
|
return {
|
|
3093
3097
|
success: false,
|
|
3094
3098
|
error: {
|
|
@@ -3950,6 +3954,133 @@ const SwapWidget = ({
|
|
|
3950
3954
|
] });
|
|
3951
3955
|
};
|
|
3952
3956
|
|
|
3957
|
+
const useSpiceAssets = ({
|
|
3958
|
+
address,
|
|
3959
|
+
supportedChains,
|
|
3960
|
+
enabled = true,
|
|
3961
|
+
refetchInterval
|
|
3962
|
+
}) => {
|
|
3963
|
+
const [assets, setAssets] = useState([]);
|
|
3964
|
+
const [loading, setLoading] = useState(false);
|
|
3965
|
+
const [error, setError] = useState(null);
|
|
3966
|
+
const [hasBalance, setHasBalance] = useState(false);
|
|
3967
|
+
const fetchAssets = useCallback(async () => {
|
|
3968
|
+
if (!address || !enabled) {
|
|
3969
|
+
setAssets([]);
|
|
3970
|
+
setHasBalance(false);
|
|
3971
|
+
return;
|
|
3972
|
+
}
|
|
3973
|
+
setLoading(true);
|
|
3974
|
+
setError(null);
|
|
3975
|
+
try {
|
|
3976
|
+
const response = await fetch(
|
|
3977
|
+
`${RELAYER_API_URL}/spicedeposit/${address}`
|
|
3978
|
+
);
|
|
3979
|
+
if (!response.ok) {
|
|
3980
|
+
throw new Error(`Failed to fetch balance: ${response.status}`);
|
|
3981
|
+
}
|
|
3982
|
+
const result = await response.json();
|
|
3983
|
+
if (result.success && result.data?.tokens) {
|
|
3984
|
+
const tokens = result.data.tokens;
|
|
3985
|
+
const parsedAssets = [];
|
|
3986
|
+
Object.keys(tokens).forEach((chainIdStr) => {
|
|
3987
|
+
const chainId = parseInt(chainIdStr);
|
|
3988
|
+
if (supportedChains && !supportedChains.includes(chainId)) {
|
|
3989
|
+
return;
|
|
3990
|
+
}
|
|
3991
|
+
const chainTokens = tokens[chainIdStr];
|
|
3992
|
+
const chainConfig = getChainConfig(chainId);
|
|
3993
|
+
if (chainTokens && typeof chainTokens === "object") {
|
|
3994
|
+
Object.keys(chainTokens).forEach((tokenAddress) => {
|
|
3995
|
+
const rawBalanceStr = chainTokens[tokenAddress];
|
|
3996
|
+
const rawBalance = BigInt(rawBalanceStr || "0");
|
|
3997
|
+
if (rawBalance > BigInt(0)) {
|
|
3998
|
+
const isNative = tokenAddress.toLowerCase() === "0x0" || tokenAddress.toLowerCase() === "0x0000000000000000000000000000000000000000" || tokenAddress.toLowerCase() === "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee";
|
|
3999
|
+
let decimals = 18;
|
|
4000
|
+
let symbol = "TOKEN";
|
|
4001
|
+
let name = tokenAddress.slice(0, 6) + "..." + tokenAddress.slice(-4);
|
|
4002
|
+
let logoURI;
|
|
4003
|
+
if (isNative) {
|
|
4004
|
+
decimals = chainConfig?.nativeCurrency?.decimals || 18;
|
|
4005
|
+
symbol = chainConfig?.nativeCurrency?.symbol || "ETH";
|
|
4006
|
+
name = chainConfig?.nativeCurrency?.name || "Native Token";
|
|
4007
|
+
} else {
|
|
4008
|
+
const tokenConfig = chainConfig?.supportedTokens?.find(
|
|
4009
|
+
(t) => t.address.toLowerCase() === tokenAddress.toLowerCase()
|
|
4010
|
+
);
|
|
4011
|
+
if (tokenConfig) {
|
|
4012
|
+
decimals = tokenConfig.decimals;
|
|
4013
|
+
symbol = tokenConfig.symbol;
|
|
4014
|
+
name = tokenConfig.name;
|
|
4015
|
+
logoURI = tokenConfig.logoURI;
|
|
4016
|
+
}
|
|
4017
|
+
}
|
|
4018
|
+
const balanceFormatted = parseFloat(
|
|
4019
|
+
(Number(rawBalance) / Math.pow(10, decimals)).toFixed(6)
|
|
4020
|
+
);
|
|
4021
|
+
if (balanceFormatted > 0) {
|
|
4022
|
+
parsedAssets.push({
|
|
4023
|
+
address: isNative ? "0x0000000000000000000000000000000000000000" : tokenAddress,
|
|
4024
|
+
symbol,
|
|
4025
|
+
name,
|
|
4026
|
+
decimals,
|
|
4027
|
+
chainId,
|
|
4028
|
+
balance: rawBalance,
|
|
4029
|
+
balanceFormatted,
|
|
4030
|
+
balanceUsd: 0,
|
|
4031
|
+
// API doesn't provide USD value
|
|
4032
|
+
isNative,
|
|
4033
|
+
logoURI
|
|
4034
|
+
});
|
|
4035
|
+
}
|
|
4036
|
+
}
|
|
4037
|
+
});
|
|
4038
|
+
}
|
|
4039
|
+
});
|
|
4040
|
+
setAssets(parsedAssets);
|
|
4041
|
+
setHasBalance(parsedAssets.length > 0);
|
|
4042
|
+
} else {
|
|
4043
|
+
setAssets([]);
|
|
4044
|
+
setHasBalance(false);
|
|
4045
|
+
}
|
|
4046
|
+
} catch (err) {
|
|
4047
|
+
const errorMessage = err instanceof Error ? err.message : "Failed to fetch balance";
|
|
4048
|
+
setError(errorMessage);
|
|
4049
|
+
console.error("Error fetching Spice assets:", err);
|
|
4050
|
+
setAssets([]);
|
|
4051
|
+
setHasBalance(false);
|
|
4052
|
+
} finally {
|
|
4053
|
+
setLoading(false);
|
|
4054
|
+
}
|
|
4055
|
+
}, [address, enabled, supportedChains]);
|
|
4056
|
+
useEffect(() => {
|
|
4057
|
+
if (enabled && address) {
|
|
4058
|
+
fetchAssets();
|
|
4059
|
+
}
|
|
4060
|
+
}, [address, enabled, fetchAssets]);
|
|
4061
|
+
useEffect(() => {
|
|
4062
|
+
if (!enabled || !address || !refetchInterval) return;
|
|
4063
|
+
const interval = setInterval(() => {
|
|
4064
|
+
fetchAssets();
|
|
4065
|
+
}, refetchInterval);
|
|
4066
|
+
return () => clearInterval(interval);
|
|
4067
|
+
}, [address, enabled, refetchInterval, fetchAssets]);
|
|
4068
|
+
const getAssetsByChain = useCallback(
|
|
4069
|
+
(chainId) => {
|
|
4070
|
+
return assets.filter((asset) => asset.chainId === chainId);
|
|
4071
|
+
},
|
|
4072
|
+
[assets]
|
|
4073
|
+
);
|
|
4074
|
+
return {
|
|
4075
|
+
assets,
|
|
4076
|
+
loading,
|
|
4077
|
+
error,
|
|
4078
|
+
hasBalance,
|
|
4079
|
+
refetch: fetchAssets,
|
|
4080
|
+
getAssetsByChain
|
|
4081
|
+
};
|
|
4082
|
+
};
|
|
4083
|
+
|
|
3953
4084
|
const DepositWidget = ({
|
|
3954
4085
|
depositBatches,
|
|
3955
4086
|
tokenAddress,
|
|
@@ -3989,14 +4120,15 @@ const DepositWidget = ({
|
|
|
3989
4120
|
const [selectedDepositAsset, setSelectedDepositAsset] = useState(null);
|
|
3990
4121
|
const [isPending, startTransition] = useTransition();
|
|
3991
4122
|
const {
|
|
3992
|
-
assets,
|
|
3993
|
-
loading:
|
|
3994
|
-
error:
|
|
3995
|
-
|
|
3996
|
-
} =
|
|
4123
|
+
assets: spiceAssets,
|
|
4124
|
+
loading: loadingSpiceAssets,
|
|
4125
|
+
error: spiceAssetsError,
|
|
4126
|
+
refetch: refreshSpiceAssets
|
|
4127
|
+
} = useSpiceAssets({
|
|
3997
4128
|
address,
|
|
3998
4129
|
supportedChains,
|
|
3999
|
-
|
|
4130
|
+
enabled: isConnected,
|
|
4131
|
+
refetchInterval: 3e4
|
|
4000
4132
|
});
|
|
4001
4133
|
const [isExecuting, setIsExecuting] = useState(false);
|
|
4002
4134
|
const [error, setError] = useState(null);
|
|
@@ -4160,7 +4292,7 @@ const DepositWidget = ({
|
|
|
4160
4292
|
const initialSteps = createInitialSteps(allChainBatches, getChainName);
|
|
4161
4293
|
startStatusPolling(result.intentId, initialSteps);
|
|
4162
4294
|
onDepositSuccess?.(result.intentId);
|
|
4163
|
-
|
|
4295
|
+
refreshSpiceAssets();
|
|
4164
4296
|
}
|
|
4165
4297
|
} catch (error2) {
|
|
4166
4298
|
const errorMessage = error2 instanceof Error ? error2.message : "Deposit failed";
|
|
@@ -4170,23 +4302,18 @@ const DepositWidget = ({
|
|
|
4170
4302
|
setIsExecuting(false);
|
|
4171
4303
|
}
|
|
4172
4304
|
};
|
|
4173
|
-
const
|
|
4174
|
-
const allAssets = supportedChains.flatMap(
|
|
4175
|
-
(chainId) => getAllAssetsForChain(chainId, assets)
|
|
4176
|
-
);
|
|
4177
|
-
console.log("allAssets", allAssets);
|
|
4178
|
-
console.log("supportedTokens", supportedTokens);
|
|
4305
|
+
const spiceDepositAssets = useMemo(() => {
|
|
4179
4306
|
if (supportedTokens && supportedTokens.length > 0) {
|
|
4180
|
-
return
|
|
4307
|
+
return spiceAssets.filter(
|
|
4181
4308
|
(asset) => supportedTokens.some(
|
|
4182
4309
|
(symbol) => symbol.toLowerCase() === asset.symbol.toLowerCase()
|
|
4183
4310
|
)
|
|
4184
4311
|
);
|
|
4185
4312
|
}
|
|
4186
|
-
return
|
|
4187
|
-
}, [
|
|
4313
|
+
return spiceAssets;
|
|
4314
|
+
}, [spiceAssets, supportedTokens]);
|
|
4188
4315
|
const canDeposit = selectedDepositAsset && selectedDepositAsset.amount && parseFloat(selectedDepositAsset.amount) > 0 && parseFloat(selectedDepositAsset.amount) <= selectedDepositAsset.asset.balanceFormatted && isConnected && !isExecuting && depositBatches.length > 0;
|
|
4189
|
-
const displayError =
|
|
4316
|
+
const displayError = spiceAssetsError || error;
|
|
4190
4317
|
const containerStyles = {
|
|
4191
4318
|
backgroundColor: styles?.container?.backgroundColor || styles?.primaryBackground || theme.colors.background,
|
|
4192
4319
|
border: `1px solid ${styles?.container?.borderColor || theme.colors.border}`,
|
|
@@ -4213,7 +4340,7 @@ const DepositWidget = ({
|
|
|
4213
4340
|
onNewTx: () => {
|
|
4214
4341
|
clearStatus();
|
|
4215
4342
|
setSelectedDepositAsset(null);
|
|
4216
|
-
|
|
4343
|
+
refreshSpiceAssets();
|
|
4217
4344
|
},
|
|
4218
4345
|
explorerUrlBuilder: (chainId, txHash) => getExplorerUrl(chainId, txHash),
|
|
4219
4346
|
theme
|
|
@@ -4342,11 +4469,11 @@ const DepositWidget = ({
|
|
|
4342
4469
|
/* @__PURE__ */ jsx("div", { style: { marginBottom: theme.spacing.sm }, children: /* @__PURE__ */ jsx(
|
|
4343
4470
|
AssetSelector,
|
|
4344
4471
|
{
|
|
4345
|
-
assets:
|
|
4472
|
+
assets: spiceDepositAssets,
|
|
4346
4473
|
selectedAsset: selectedDepositAsset || void 0,
|
|
4347
4474
|
onAssetSelect: handleDepositAssetSelect,
|
|
4348
4475
|
onAmountChange: handleDepositAmountChange,
|
|
4349
|
-
loading:
|
|
4476
|
+
loading: loadingSpiceAssets,
|
|
4350
4477
|
label: "Deposit",
|
|
4351
4478
|
showBalance: true,
|
|
4352
4479
|
showMaxButton: true,
|
|
@@ -7641,7 +7768,8 @@ const DepositModal = React.memo(
|
|
|
7641
7768
|
tokenAddress,
|
|
7642
7769
|
chainId,
|
|
7643
7770
|
amount: amount.toString(),
|
|
7644
|
-
user: address
|
|
7771
|
+
user: address,
|
|
7772
|
+
isDeposit: true
|
|
7645
7773
|
});
|
|
7646
7774
|
await relayerService.submitSpiceDeposit({
|
|
7647
7775
|
txHash: transferToEmbeddedTx,
|
|
@@ -7649,7 +7777,8 @@ const DepositModal = React.memo(
|
|
|
7649
7777
|
tokenAddress,
|
|
7650
7778
|
chainId,
|
|
7651
7779
|
amount: amount.toString(),
|
|
7652
|
-
user: address
|
|
7780
|
+
user: address,
|
|
7781
|
+
isDeposit: true
|
|
7653
7782
|
});
|
|
7654
7783
|
console.log(
|
|
7655
7784
|
`Successfully submitted deposit for txHash: ${transferToEmbeddedTx}`
|
|
@@ -9251,7 +9380,8 @@ const WithdrawModal = React.memo(
|
|
|
9251
9380
|
sender: externalWalletAddress,
|
|
9252
9381
|
tokenAddress: apiTokenAddress,
|
|
9253
9382
|
chainId: destinationChainId,
|
|
9254
|
-
amount: amount2.toString()
|
|
9383
|
+
amount: amount2.toString(),
|
|
9384
|
+
isDeposit: false
|
|
9255
9385
|
});
|
|
9256
9386
|
const depositResult = await relayerService.submitSpiceDeposit({
|
|
9257
9387
|
user: externalWalletAddress,
|
|
@@ -9259,7 +9389,8 @@ const WithdrawModal = React.memo(
|
|
|
9259
9389
|
sender: externalWalletAddress,
|
|
9260
9390
|
tokenAddress: apiTokenAddress,
|
|
9261
9391
|
chainId: destinationChainId,
|
|
9262
|
-
amount: amount2.toString()
|
|
9392
|
+
amount: amount2.toString(),
|
|
9393
|
+
isDeposit: false
|
|
9263
9394
|
});
|
|
9264
9395
|
if (!depositResult.success) {
|
|
9265
9396
|
console.error(
|
|
@@ -12136,4 +12267,4 @@ const useDepositInput = () => {
|
|
|
12136
12267
|
};
|
|
12137
12268
|
};
|
|
12138
12269
|
|
|
12139
|
-
export { ConnectWalletModal, DepositModal, DepositWidget, DepositWidgetModal, LpModal, ProviderLogin, SelectChainModal, SpiceBalance, SpiceDeposit, SpiceFlowProvider, SpiceFlowProviderContext, SpiceWithdraw, SwapWidget, WithdrawModal, fetchBalances, useAssets, useDepositInput, useFromInput, useSpiceBalance, useStatus, useToInputUpdate, useWallet };
|
|
12270
|
+
export { ConnectWalletModal, DepositModal, DepositWidget, DepositWidgetModal, LpModal, ProviderLogin, SelectChainModal, SpiceBalance, SpiceDeposit, SpiceFlowProvider, SpiceFlowProviderContext, SpiceWithdraw, SwapWidget, WithdrawModal, fetchBalances, relayerService, useAssets, useDepositInput, useFromInput, useSpiceBalance, useStatus, useToInputUpdate, useWallet };
|