diff --git a/package-lock.json b/package-lock.json
index 5fca2da4..556aae5f 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -14,7 +14,7 @@
"@etherspot/data-utils": "1.1.1",
"@etherspot/intent-sdk": "1.0.0-alpha.12",
"@etherspot/modular-sdk": "6.1.1",
- "@etherspot/transaction-kit": "2.1.3",
+ "@etherspot/transaction-kit": "2.1.4",
"@hypelab/sdk-react": "1.0.4",
"@lifi/sdk": "3.6.8",
"@mui/icons-material": "5.16.6",
@@ -5302,9 +5302,9 @@
}
},
"node_modules/@etherspot/transaction-kit": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/@etherspot/transaction-kit/-/transaction-kit-2.1.3.tgz",
- "integrity": "sha512-PccY2N8Ifri3DGiR91MA3pQHEL4dXRQZYaJIXRRqpU+Y7AvgjdPHN95CFc9uyWhsFthe12EEX0/+JBk6Z29Y+g==",
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/@etherspot/transaction-kit/-/transaction-kit-2.1.4.tgz",
+ "integrity": "sha512-a17dM3U1HGJtYHltxx9SRBlBClK5JaSUmqZ+Ki37vg5r+eIcEcEyRyXZVgmCsORFd1pxXU/eqfgkU6agFJmrWw==",
"license": "MIT",
"dependencies": {
"@etherspot/eip1271-verification-util": "0.1.2",
@@ -25138,6 +25138,7 @@
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0"
@@ -37040,6 +37041,7 @@
"version": "9.0.5",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
"integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
+ "dev": true,
"license": "ISC",
"dependencies": {
"brace-expansion": "^2.0.1"
@@ -37064,6 +37066,7 @@
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
"integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
+ "dev": true,
"license": "ISC",
"engines": {
"node": ">=16 || 14 >=14.17"
diff --git a/package.json b/package.json
index 78b272e2..b022c866 100644
--- a/package.json
+++ b/package.json
@@ -23,7 +23,7 @@
"@etherspot/data-utils": "1.1.1",
"@etherspot/intent-sdk": "1.0.0-alpha.12",
"@etherspot/modular-sdk": "6.1.1",
- "@etherspot/transaction-kit": "2.1.3",
+ "@etherspot/transaction-kit": "2.1.4",
"@hypelab/sdk-react": "1.0.4",
"@lifi/sdk": "3.6.8",
"@mui/icons-material": "5.16.6",
diff --git a/src/apps/pulse/components/Buy/PayingToken.tsx b/src/apps/pulse/components/Buy/PayingToken.tsx
index adf56004..6f804695 100644
--- a/src/apps/pulse/components/Buy/PayingToken.tsx
+++ b/src/apps/pulse/components/Buy/PayingToken.tsx
@@ -4,6 +4,7 @@ import { MdCheck } from 'react-icons/md';
// utils
import { getLogoForChainId } from '../../../../utils/blockchain';
+import { truncateDecimals } from '../../utils/number';
// types
import { PayingToken as PayingTokenType } from '../../types/tokens';
@@ -85,7 +86,7 @@ export default function PayingToken(props: PayingTokenProps) {
- {payingToken.totalRaw}
+ {truncateDecimals(payingToken.totalRaw, 6)}
${payingToken.totalUsd.toFixed(2)}
diff --git a/src/apps/pulse/components/Buy/tests/Buy.test.tsx b/src/apps/pulse/components/Buy/tests/Buy.test.tsx
index 5eb6e516..f5a19cc7 100644
--- a/src/apps/pulse/components/Buy/tests/Buy.test.tsx
+++ b/src/apps/pulse/components/Buy/tests/Buy.test.tsx
@@ -94,6 +94,11 @@ vi.mock('../../../../../services/pillarXApiTransactionsHistory', () => ({
vi.mock('../../hooks/useRelayBuy', () => ({
default: vi.fn(() => ({
+ getUSDCToken: vi.fn(() => ({
+ chainId: 1,
+ address: '0xUSDC1234567890',
+ decimals: 6,
+ })),
getBestOffer: vi.fn(),
isInitialized: false,
error: null,
diff --git a/src/apps/pulse/components/Sell/PreviewSell.tsx b/src/apps/pulse/components/Sell/PreviewSell.tsx
index 41a9b0c8..b163f579 100644
--- a/src/apps/pulse/components/Sell/PreviewSell.tsx
+++ b/src/apps/pulse/components/Sell/PreviewSell.tsx
@@ -69,7 +69,7 @@ const PreviewSell = (props: PreviewSellProps) => {
const [isTransactionSuccess, setIsTransactionSuccess] = useState(false);
const previewModalRef = useRef
(null);
const {
- getUSDCAddress,
+ getUSDCToken,
executeSell,
error,
clearError,
@@ -232,7 +232,8 @@ const PreviewSell = (props: PreviewSellProps) => {
// }
// };
- const usdcAddress = getUSDCAddress(selectedChainIdForSettlement || 0);
+ const usdcToken = getUSDCToken(selectedChainIdForSettlement || 0);
+ const usdcAddress = usdcToken ? usdcToken.address : '';
// Clean up pulse-sell batch when component unmounts or preview closes
useEffect(() => {
diff --git a/src/apps/pulse/components/Sell/tests/PreviewSell.test.tsx b/src/apps/pulse/components/Sell/tests/PreviewSell.test.tsx
index ea1b5d4b..7f0c3b0c 100644
--- a/src/apps/pulse/components/Sell/tests/PreviewSell.test.tsx
+++ b/src/apps/pulse/components/Sell/tests/PreviewSell.test.tsx
@@ -162,7 +162,11 @@ describe('', () => {
vi.clearAllMocks();
(useRelaySell as any).mockReturnValue({
- getUSDCAddress: vi.fn(() => '0xUSDC1234567890'),
+ getUSDCToken: vi.fn(() => ({
+ chainId: 1,
+ address: '0xUSDC1234567890',
+ decimals: 6,
+ })),
executeSell: vi.fn(),
error: null,
clearError: vi.fn(),
@@ -259,7 +263,11 @@ describe('', () => {
})
);
(useRelaySell as any).mockReturnValue({
- getUSDCAddress: vi.fn(() => '0xUSDC1234567890'),
+ getUSDCToken: vi.fn(() => ({
+ chainId: 1,
+ address: '0xUSDC1234567890',
+ decimals: 6,
+ })),
executeSell: mockExecuteSell,
error: null,
clearError: vi.fn(),
@@ -299,7 +307,11 @@ describe('', () => {
describe('handles error states', () => {
it('displays relay error', () => {
(useRelaySell as any).mockReturnValue({
- getUSDCAddress: vi.fn(() => '0xUSDC1234567890'),
+ getUSDCToken: vi.fn(() => ({
+ chainId: 1,
+ address: '0xUSDC1234567890',
+ decimals: 6,
+ })),
executeSell: vi.fn(),
error: 'Relay error occurred',
clearError: vi.fn(),
@@ -334,7 +346,7 @@ describe('', () => {
describe('handles edge cases', () => {
it('handles missing USDC address', () => {
(useRelaySell as any).mockReturnValue({
- getUSDCAddress: vi.fn(() => null),
+ getUSDCToken: vi.fn(() => null),
executeSell: vi.fn(),
error: null,
clearError: vi.fn(),
diff --git a/src/apps/pulse/constants/tokens.ts b/src/apps/pulse/constants/tokens.ts
index 2dedd40f..b9afcb33 100644
--- a/src/apps/pulse/constants/tokens.ts
+++ b/src/apps/pulse/constants/tokens.ts
@@ -1,13 +1,41 @@
import { isGnosisEnabled } from '../../../utils/blockchain';
export const allStableCurrencies = [
- { chainId: 1, address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48' },
- { chainId: 10, address: '0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85' }, // USDC on Optimism
- { chainId: 137, address: '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359' }, // USDC on Polygon
- { chainId: 8453, address: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913' }, // USDC on Base
- { chainId: 42161, address: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831' }, // USDC on Arbitrum
- { chainId: 56, address: '0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d' }, // USDC on BNB Smart Chain
- { chainId: 100, address: '0x2a22f9c3b484c3629090FeED35F17Ff8F88f76F0' }, // USDC on Gnosis
+ {
+ chainId: 1,
+ address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
+ decimals: 6,
+ },
+ {
+ chainId: 10,
+ address: '0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85',
+ decimals: 6,
+ }, // USDC on Optimism
+ {
+ chainId: 137,
+ address: '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359',
+ decimals: 6,
+ }, // USDC on Polygon
+ {
+ chainId: 8453,
+ address: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
+ decimals: 6,
+ }, // USDC on Base
+ {
+ chainId: 42161,
+ address: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831',
+ decimals: 6,
+ }, // USDC on Arbitrum
+ {
+ chainId: 56,
+ address: '0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d',
+ decimals: 18,
+ }, // USDC on BNB Smart Chain
+ {
+ chainId: 100,
+ address: '0x2a22f9c3b484c3629090FeED35F17Ff8F88f76F0',
+ decimals: 6,
+ }, // USDC on Gnosis
];
export const STABLE_CURRENCIES = allStableCurrencies.filter(
diff --git a/src/apps/pulse/hooks/tests/useRelaySell.test.tsx b/src/apps/pulse/hooks/tests/useRelaySell.test.tsx
index 97736dc6..7d3eadb7 100644
--- a/src/apps/pulse/hooks/tests/useRelaySell.test.tsx
+++ b/src/apps/pulse/hooks/tests/useRelaySell.test.tsx
@@ -53,7 +53,7 @@ vi.mock('../../constants/tokens', () => ({
{
chainId: 1,
address: '0xA0b86a33E6441b8C4C8C0C8C0C8C0C8C0C8C0C8C',
- symbol: 'USDC',
+ decimals: 6,
},
],
}));
@@ -182,7 +182,7 @@ describe('useRelaySell', () => {
expect(result.current.isLoading).toBe(false);
expect(result.current.error).toBe(null);
expect(result.current.isInitialized).toBe(false);
- expect(typeof result.current.getUSDCAddress).toBe('function');
+ expect(typeof result.current.getUSDCToken).toBe('function');
expect(typeof result.current.getBestSellOffer).toBe('function');
expect(typeof result.current.executeSell).toBe('function');
expect(typeof result.current.buildSellTransactions).toBe('function');
@@ -249,7 +249,7 @@ describe('useRelaySell', () => {
expect(result.current.isInitialized).toBe(true);
});
- it('getUSDCAddress returns correct address for supported chain', async () => {
+ it('getUSDCToken returns correct token for supported chain', async () => {
const useRelaySdk = await import('../useRelaySdk');
const useTransactionKit = await import(
'../../../../hooks/useTransactionKit'
@@ -289,11 +289,15 @@ describe('useRelaySell', () => {
const { result } = renderHook(() => useRelaySell());
- const usdcAddress = result.current.getUSDCAddress(1);
- expect(usdcAddress).toBe('0xA0b86a33E6441b8C4C8C0C8C0C8C0C8C0C8C0C8C');
+ const usdcToken = result.current.getUSDCToken(1);
+ expect(usdcToken?.address).toBe(
+ '0xA0b86a33E6441b8C4C8C0C8C0C8C0C8C0C8C0C8C'
+ );
+ expect(usdcToken?.decimals).toBe(6);
+ expect(usdcToken?.chainId).toBe(1);
});
- it('getUSDCAddress returns null for unsupported chain', async () => {
+ it('getUSDCToken returns null for unsupported chain', async () => {
const useRelaySdk = await import('../useRelaySdk');
const useTransactionKit = await import(
'../../../../hooks/useTransactionKit'
@@ -333,8 +337,8 @@ describe('useRelaySell', () => {
const { result } = renderHook(() => useRelaySell());
- const usdcAddress = result.current.getUSDCAddress(999);
- expect(usdcAddress).toBe(null);
+ const usdcToken = result.current.getUSDCToken(999);
+ expect(usdcToken).toBe(null);
});
it('getBestSellOffer returns null when not initialized', async () => {
@@ -633,7 +637,11 @@ describe('useRelaySell', () => {
const { result } = renderHook(() => useRelaySell());
- const success = await result.current.executeSell(mockSelectedToken, '1.0');
+ const success = await result.current.executeSell(
+ mockSelectedToken,
+ '1.0',
+ 1
+ );
expect(success).toBe(false);
diff --git a/src/apps/pulse/hooks/useRelayBuy.ts b/src/apps/pulse/hooks/useRelayBuy.ts
index cd9d1ab3..ed5d6c99 100644
--- a/src/apps/pulse/hooks/useRelayBuy.ts
+++ b/src/apps/pulse/hooks/useRelayBuy.ts
@@ -108,13 +108,15 @@ export default function useRelayBuy() {
}, [isInitialized]);
/**
- * Get the USDC address for a specific chain
+ * Get the USDC token details for a specific chain
*/
- const getUSDCAddress = (chainId: number): string | null => {
+ const getUSDCToken = (
+ chainId: number
+ ): { chainId: number; address: string; decimals: number } | null => {
const stableCurrency = STABLE_CURRENCIES.find(
(currency) => currency.chainId === chainId
);
- return stableCurrency?.address || null;
+ return stableCurrency ?? null;
};
/**
@@ -135,12 +137,15 @@ export default function useRelayBuy() {
return null;
}
- const usdcAddress = getUSDCAddress(fromChainId);
- if (!usdcAddress) {
+ const USDCtoken = getUSDCToken(fromChainId);
+ if (!USDCtoken) {
setError('Unable to get quote. Please try again.');
return null;
}
+ const usdcAddress = USDCtoken.address;
+ const usdcDecimals = USDCtoken.decimals;
+
setIsLoading(true);
setError(null);
@@ -172,8 +177,11 @@ export default function useRelayBuy() {
// If USDC price is $0.9998, then $10 USD = 10 / 0.9998 = 10.002 USDC
const usdcAmount = usdAmount / usdcPrice;
- // Convert to wei using 6 decimals (USDC precision)
- fromAmountInWei = parseUnits(usdcAmount.toFixed(6), 6);
+ // Convert to wei using USDC decimals (e.g., 6 on Ethereum, 18 on BSC)
+ fromAmountInWei = parseUnits(
+ usdcAmount.toFixed(usdcDecimals),
+ usdcDecimals
+ );
} catch (parseError) {
console.error('Failed to parse fromAmount:', parseError);
setError('Invalid amount. Please try again.');
@@ -308,11 +316,14 @@ export default function useRelayBuy() {
}
// Get USDC address for the chain
- const usdcAddress = getUSDCAddress(fromChainId);
- if (!usdcAddress) {
+ const USDCtoken = getUSDCToken(fromChainId);
+ if (!USDCtoken) {
throw new Error('USDC address not found for chain');
}
+ const usdcAddress = USDCtoken.address;
+ const usdcDecimals = USDCtoken.decimals;
+
// Calculate fee distribution: 1% fee, 99% for swap
// Get the USDC amount needed for the swap from the quote
const usdcNeededForSwap = BigInt(
@@ -357,7 +368,7 @@ export default function useRelayBuy() {
t.blockchain === `chain-${fromChainId}`
);
if (usdcToken && usdcToken.balance) {
- userUsdcBalance = toWei(usdcToken.balance.toString(), 6); // USDC has 6 decimals
+ userUsdcBalance = toWei(usdcToken.balance.toString(), usdcDecimals);
}
// Debug: Log balance validation only if there's an issue
@@ -788,7 +799,7 @@ export default function useRelayBuy() {
);
return {
- getUSDCAddress,
+ getUSDCToken,
getBestOffer,
executeBuy,
buildTransactions,
diff --git a/src/apps/pulse/hooks/useRelaySell.ts b/src/apps/pulse/hooks/useRelaySell.ts
index f1b1aabe..8d664ed6 100644
--- a/src/apps/pulse/hooks/useRelaySell.ts
+++ b/src/apps/pulse/hooks/useRelaySell.ts
@@ -112,14 +112,19 @@ export default function useRelaySell() {
}, [isInitialized]);
/**
- * Get the USDC address for a specific chain
+ * Get the USDC token details for a specific chain
*/
- const getUSDCAddress = useCallback((chainId: number): string | null => {
- const stableCurrency = STABLE_CURRENCIES.find(
- (currency) => currency.chainId === chainId
- );
- return stableCurrency?.address || null;
- }, []);
+ const getUSDCToken = useCallback(
+ (
+ chainId: number
+ ): { chainId: number; address: string; decimals: number } | null => {
+ const stableCurrency = STABLE_CURRENCIES.find(
+ (currency) => currency.chainId === chainId
+ );
+ return stableCurrency ?? null;
+ },
+ []
+ );
/**
* Get the best sell offer for swapping a token to USDC
@@ -140,12 +145,15 @@ export default function useRelaySell() {
return null;
}
- const usdcAddress = getUSDCAddress(toChainId);
- if (!usdcAddress) {
+ const usdcToken = getUSDCToken(toChainId);
+ if (!usdcToken) {
setError('Unable to get quote. Please try again.');
return null;
}
+ const usdcAddress = usdcToken.address;
+ const usdcDecimals = usdcToken.decimals;
+
setIsLoading(true);
setError(null);
@@ -205,14 +213,15 @@ export default function useRelaySell() {
if (currencyOut.amountFormatted) {
usdcAmount = parseFloat(currencyOut.amountFormatted);
} else if (currencyOut.amount) {
- // Convert from raw units to readable format
- usdcAmount = parseFloat(currencyOut.amount) / 10 ** 6; // USDC has 6 decimals
+ // Convert from raw units to readable format using USDC decimals
+ usdcAmount = parseFloat(currencyOut.amount) / 10 ** usdcDecimals;
}
// Get the minimum amount (prefer formatted, fallback to raw amount)
if (currencyOut.minimumAmount) {
- // minimumAmount is in raw units, convert to readable format
- minimumAmount = parseFloat(currencyOut.minimumAmount) / 10 ** 6; // USDC has 6 decimals
+ // minimumAmount is in raw units, convert to readable format using USDC decimals
+ minimumAmount =
+ parseFloat(currencyOut.minimumAmount) / 10 ** usdcDecimals;
} else {
// Fallback: calculate minimum receive using slippage tolerance
// Formula: Minimum to receive = Est. to amount × (1 - max.slippage)
@@ -329,12 +338,14 @@ export default function useRelaySell() {
throw new Error('Fee receiver address is not configured');
}
- // Get USDC address for the chain
- const usdcAddress = getUSDCAddress(token.chainId);
- if (!usdcAddress) {
+ // Get USDC address and decimals for the chain
+ const usdcToken = getUSDCToken(token.chainId);
+ if (!usdcToken) {
throw new Error('USDC address not found for chain');
}
+ const usdcAddress = usdcToken.address;
+
// Calculate fee distribution: 99% to user, 1% to fee receiver
// We swap 100% of the token, then take 1% of the received USDC as fee
// Use the guaranteed minimum USDC received from the swap (slippage-protected)
@@ -1005,17 +1016,20 @@ export default function useRelaySell() {
const usdcAfterFee = usdcAfterFirstSwap * 0.99; // 1% fee taken
// Step 3: Get quote for bridging USDC to target chain
- const usdcAddress = getUSDCAddress(fromChainId);
- if (!usdcAddress) {
+ const usdcToken = getUSDCToken(fromChainId);
+ if (!usdcToken) {
setError('Unable to get USDC address for source chain');
return null;
}
+ const usdcAddress = usdcToken.address;
+ const usdcDecimals = usdcToken.decimals;
+
const bridgeOffer = await getBestSellOffer({
fromAmount: usdcAfterFee.toString(),
fromTokenAddress: usdcAddress,
fromChainId,
- fromTokenDecimals: 6,
+ fromTokenDecimals: usdcDecimals,
toChainId, // Target chain
slippage,
});
@@ -1065,7 +1079,7 @@ export default function useRelaySell() {
setIsLoading(false);
}
},
- [isInitialized, getBestSellOffer, getUSDCAddress]
+ [isInitialized, getBestSellOffer, getUSDCToken]
);
/**
@@ -1133,12 +1147,15 @@ export default function useRelaySell() {
const fromAmountBigInt = parseUnits(inputAmount, fromToken.decimals);
- // Step 3: Get USDC address
- const usdcAddress = getUSDCAddress(fromChainId);
- if (!usdcAddress) {
+ // Step 3: Get USDC address and decimals
+ const usdcToken = getUSDCToken(fromChainId);
+ if (!usdcToken) {
throw new Error('USDC address not found for source chain');
}
+ const usdcAddress = usdcToken.address;
+ const usdcDecimals = usdcToken.decimals;
+
// Step 4: Calculate fee for first swap (1% of USDC received)
const feeReceiver = import.meta.env.VITE_SWAP_FEE_RECEIVER;
if (!feeReceiver) {
@@ -1399,7 +1416,7 @@ export default function useRelaySell() {
// Step 10: Get quote for USDC bridge
const usdcToBridgeFormatted = (
Number(usdcAfterFirstSwapFee) /
- 10 ** 6
+ 10 ** usdcDecimals
).toString();
let bridgeOffer: SellOffer | null = null;
@@ -1408,7 +1425,7 @@ export default function useRelaySell() {
fromAmount: usdcToBridgeFormatted,
fromTokenAddress: usdcAddress,
fromChainId,
- fromTokenDecimals: 6,
+ fromTokenDecimals: usdcDecimals,
toChainId, // Target chain
});
} catch (err) {
@@ -1452,7 +1469,10 @@ export default function useRelaySell() {
}
if (bridgeSpenderAddress) {
- const usdcAmountBigInt = parseUnits(usdcToBridgeFormatted, 6);
+ const usdcAmountBigInt = parseUnits(
+ usdcToBridgeFormatted,
+ usdcDecimals
+ );
const isAllowance = await isAllowanceSet({
owner: walletAddress || '',
@@ -1583,7 +1603,7 @@ export default function useRelaySell() {
},
[
getBestSellOffer,
- getUSDCAddress,
+ getUSDCToken,
isAllowanceSet,
walletAddress,
transactionDebugLog,
@@ -1596,7 +1616,7 @@ export default function useRelaySell() {
}, []);
return {
- getUSDCAddress,
+ getUSDCToken,
getBestSellOffer,
getBestSellOfferWithBridge,
executeSell,
diff --git a/src/apps/pulse/hooks/useTopUp.ts b/src/apps/pulse/hooks/useTopUp.ts
index 05b49152..22dbcfa3 100644
--- a/src/apps/pulse/hooks/useTopUp.ts
+++ b/src/apps/pulse/hooks/useTopUp.ts
@@ -32,11 +32,8 @@ export default function useTopUp() {
const [error, setError] = useState(null);
const { kit, walletAddress } = useTransactionKit();
- const {
- buildSellTransactions,
- getUSDCAddress,
- isInitialized: isRelayInitialized,
- } = useRelaySell();
+ const { buildSellTransactions, isInitialized: isRelayInitialized } =
+ useRelaySell();
const { transactionDebugLog } = useTransactionDebugLogger();
const clearError = useCallback(() => {
@@ -60,12 +57,6 @@ export default function useTopUp() {
const transactions = [];
const { chainId } = selectedToken;
- // Get USDC address for the chain
- const usdcAddress = getUSDCAddress(chainId);
- if (!usdcAddress) {
- throw new Error(`USDC not supported on chain ${chainId}`);
- }
-
// Step 1: If non-USDC token, add sell transactions
if (sellOffer) {
const tokenPrice = parseFloat(selectedToken.usdValue) || 0;
@@ -154,7 +145,7 @@ export default function useTopUp() {
return transactions;
},
- [walletAddress, getUSDCAddress, buildSellTransactions]
+ [walletAddress, buildSellTransactions]
);
/**
diff --git a/src/apps/pulse/utils/number.ts b/src/apps/pulse/utils/number.ts
index fcaa39fb..6546860a 100644
--- a/src/apps/pulse/utils/number.ts
+++ b/src/apps/pulse/utils/number.ts
@@ -51,3 +51,18 @@ export function bigIntPow(base: bigint, exponent: bigint): bigint {
}
return result;
}
+
+export function truncateDecimals(
+ value: string | number,
+ decimals: number
+): string {
+ const strValue = typeof value === 'number' ? value.toString() : value;
+ const [integerPart, decimalPart] = strValue.split('.');
+
+ if (!decimalPart) {
+ return integerPart;
+ }
+
+ const truncatedDecimal = decimalPart.slice(0, decimals);
+ return `${integerPart}.${truncatedDecimal}`;
+}
diff --git a/src/services/pillarXApiWalletTransactions.ts b/src/services/pillarXApiWalletTransactions.ts
index d3cf796f..efcb2798 100644
--- a/src/services/pillarXApiWalletTransactions.ts
+++ b/src/services/pillarXApiWalletTransactions.ts
@@ -36,7 +36,7 @@ export const pillarXApiWalletTransactions = createApi({
wallet,
limit,
page,
- filterSpam: true,
+ filterSpam: false,
},
},
};
diff --git a/src/utils/pnl.ts b/src/utils/pnl.ts
index 5fb4533e..a3f55c7f 100644
--- a/src/utils/pnl.ts
+++ b/src/utils/pnl.ts
@@ -18,6 +18,17 @@ const USDC_ADDRESSES = allStableCurrencies.map(
currency.address.toLowerCase()
);
+/**
+ * Get the USDC decimals for a specific chain
+ */
+const getUSDCDecimalsByChainId = (chainId: number): number => {
+ const usdcToken = allStableCurrencies.find(
+ (currency: { chainId: number; address: string; decimals: number }) =>
+ currency.chainId === chainId
+ ) as { chainId: number; address: string; decimals: number } | undefined;
+ return usdcToken?.decimals ?? 6; // Default to 6 if not found
+};
+
export const reconstructTrades = (
transactions: MobulaTransactionRow[],
walletAddress: string
@@ -332,10 +343,12 @@ export const getRelayValidatedTrades = async (
// For BUY, we expect negative USDC (spending)
// For SELL, we expect positive USDC (receiving)
+ const usdcDecimals = getUSDCDecimalsByChainId(token.chainId);
+ const usdcDivisor = 10 ** usdcDecimals;
if (side === 'BUY' && balanceDiff < 0) {
- usdcAmount += Math.abs(balanceDiff) / 1e6; // USDC has 6 decimals
+ usdcAmount += Math.abs(balanceDiff) / usdcDivisor;
} else if (side === 'SELL' && balanceDiff > 0) {
- usdcAmount += balanceDiff / 1e6;
+ usdcAmount += balanceDiff / usdcDivisor;
}
}
});
@@ -438,7 +451,8 @@ export const calculatePnLFromRelay = (
// If state changes show token movement, use that
if (tokenChange !== 0) {
const tokenDivisor = 10 ** token.decimals;
- const usdcDivisor = 1e6;
+ const usdcDecimals = getUSDCDecimalsByChainId(token.chainId);
+ const usdcDivisor = 10 ** usdcDecimals;
const tokenAmountRaw = Math.abs(tokenChange) / tokenDivisor;
const usdcAmountRaw = Math.abs(usdcChange) / usdcDivisor;