From a6055bf9e55beeb1ecf9ee7a790b26ee050c48b9 Mon Sep 17 00:00:00 2001 From: Max Date: Wed, 4 Mar 2026 09:07:11 +0100 Subject: [PATCH 1/2] feat: load PDF blockchains dynamically from API (#980) Co-authored-by: max-tech-bot --- src/screens/account.screen.tsx | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/screens/account.screen.tsx b/src/screens/account.screen.tsx index 4d5b9cea..a7383ac1 100644 --- a/src/screens/account.screen.tsx +++ b/src/screens/account.screen.tsx @@ -59,17 +59,6 @@ function formatAddress(address: UserProfile['address']): string { .join(', '); } -// Supported EVM blockchains for balance PDF (must match API's SUPPORTED_BLOCKCHAINS) -const SUPPORTED_PDF_BLOCKCHAINS: Blockchain[] = [ - Blockchain.ETHEREUM, - Blockchain.BINANCE_SMART_CHAIN, - Blockchain.POLYGON, - Blockchain.ARBITRUM, - Blockchain.OPTIMISM, - Blockchain.BASE, - Blockchain.GNOSIS, -]; - enum FiatCurrency { CHF = 'CHF', EUR = 'EUR', @@ -107,6 +96,7 @@ export default function AccountScreen(): JSX.Element { const [pdfError, setPdfError] = useState(); const [showRecommendationModal, setShowRecommendationModal] = useState(false); const [isDataLoading, setIsDataLoading] = useState(true); + const [pdfBlockchains, setPdfBlockchains] = useState([]); const isKycLevel50 = user && user.kyc.level >= 50; @@ -131,7 +121,7 @@ export default function AccountScreen(): JSX.Element { const selectedPdfCurrency = useWatch({ control: pdfControl, name: 'currency' }); const selectedPdfDate = useWatch({ control: pdfControl, name: 'date' }); - const supportedBlockchains = selectedAddress?.blockchains.filter((b) => SUPPORTED_PDF_BLOCKCHAINS.includes(b)) ?? []; + const supportedBlockchains = selectedAddress?.blockchains.filter((b) => pdfBlockchains.includes(b)) ?? []; const canDownloadPdf = supportedBlockchains.length > 0; useEffect(() => { @@ -147,6 +137,10 @@ export default function AccountScreen(): JSX.Element { if (isLoggedIn) loadTransactions(); }, [isLoggedIn]); + useEffect(() => { + loadPdfBlockchains(); + }, []); + useEffect(() => { if (selectedAddress?.address && user?.activeAddress?.address !== selectedAddress?.address && !isUserLoading) { changeAddress(selectedAddress.address) @@ -157,6 +151,14 @@ export default function AccountScreen(): JSX.Element { } }, [selectedAddress, user?.activeAddress, !isUserLoading]); + async function loadPdfBlockchains(): Promise { + return call({ url: 'balance/pdf/blockchains', method: 'GET' }) + .then(setPdfBlockchains) + .catch(() => { + // ignore errors + }); + } + async function loadInitialData(): Promise { setIsDataLoading(true); From 25c580f2a42213fb999e88ea242696b4d3c1395b Mon Sep 17 00:00:00 2001 From: TaprootFreak <142087526+TaprootFreak@users.noreply.github.com> Date: Wed, 4 Mar 2026 09:08:41 +0100 Subject: [PATCH 2/2] feat: add Citrea blockchain support (#972) * feat: add Citrea blockchain support with cBTC, JUSD, and ctUSD assets Add Citrea as a new EVM blockchain to the services toolbox including buy and sell flows for cBTC, JUSD, and ctUSD. Register Citrea in EVM chain detection, balance PDF support, and transaction signing. * feat: add missing Citrea assets (WBTC.e, USDT.e, USDC.e, JUICE) Add WBTC.e, USDT.e, USDC.e, and JUICE tiles to buy-citrea and sell-citrea pages. Use existing wbtc, usdt, usdc images for bridged token variants. * fix: remove Citrea from SUPPORTED_PDF_BLOCKCHAINS Citrea is not yet in the API's SUPPORTED_BLOCKCHAINS, so remove it from the balance PDF list to keep both in sync. --- src/__tests__/evm.test.ts | 4 + src/config/feature-tree.ts | 194 +++++++++++++++++++++++++++ src/screens/blockchain-tx.screen.tsx | 1 + src/util/evm.ts | 2 + 4 files changed, 201 insertions(+) diff --git a/src/__tests__/evm.test.ts b/src/__tests__/evm.test.ts index f601b828..065b8d78 100644 --- a/src/__tests__/evm.test.ts +++ b/src/__tests__/evm.test.ts @@ -9,6 +9,8 @@ jest.mock('@dfx.swiss/react', () => ({ GNOSIS: 'Gnosis', BINANCE_SMART_CHAIN: 'BinanceSmartChain', HAQQ: 'Haqq', + CITREA: 'Citrea', + CITREA_TESTNET: 'CitreaTestnet', BITCOIN: 'Bitcoin', LIGHTNING: 'Lightning', SOLANA: 'Solana', @@ -83,6 +85,8 @@ describe('Evm', () => { Blockchain.GNOSIS, Blockchain.BINANCE_SMART_CHAIN, Blockchain.HAQQ, + Blockchain.CITREA, + Blockchain.CITREA_TESTNET, ]; evmChains.forEach(chain => { diff --git a/src/config/feature-tree.ts b/src/config/feature-tree.ts index 6931399d..29394be9 100644 --- a/src/config/feature-tree.ts +++ b/src/config/feature-tree.ts @@ -151,6 +151,13 @@ export const FeatureTree: Page[] = [ page: 'buy-gnosis', }, }, + { + id: 'citrea', + img: 'citrea', + next: { + page: 'buy-citrea', + }, + }, ], }, { @@ -744,6 +751,96 @@ export const FeatureTree: Page[] = [ }, ], }, + { + id: 'buy-citrea', + dfxStyle: true, + tiles: [ + { + id: 'cbtc', + img: 'cbtc', + next: { + page: 'wallets', + tiles: ['hw-wallet', 'metamask', 'walletconnect', 'cli'], + options: { + service: 'buy', + query: { blockchain: Blockchain.CITREA, assetOut: 'cBTC' }, + }, + }, + }, + { + id: 'jusd', + img: 'jusd', + next: { + page: 'wallets', + tiles: ['hw-wallet', 'metamask', 'walletconnect', 'cli'], + options: { + service: 'buy', + query: { blockchain: Blockchain.CITREA, assetOut: 'JUSD' }, + }, + }, + }, + { + id: 'ctusd', + img: 'ctusd', + next: { + page: 'wallets', + tiles: ['hw-wallet', 'metamask', 'walletconnect', 'cli'], + options: { + service: 'buy', + query: { blockchain: Blockchain.CITREA, assetOut: 'ctUSD' }, + }, + }, + }, + { + id: 'wbtce', + img: 'wbtc', + next: { + page: 'wallets', + tiles: ['hw-wallet', 'metamask', 'walletconnect', 'cli'], + options: { + service: 'buy', + query: { blockchain: Blockchain.CITREA, assetOut: 'WBTC.e' }, + }, + }, + }, + { + id: 'usdte', + img: 'usdt', + next: { + page: 'wallets', + tiles: ['hw-wallet', 'metamask', 'walletconnect', 'cli'], + options: { + service: 'buy', + query: { blockchain: Blockchain.CITREA, assetOut: 'USDT.e' }, + }, + }, + }, + { + id: 'usdce', + img: 'usdc', + next: { + page: 'wallets', + tiles: ['hw-wallet', 'metamask', 'walletconnect', 'cli'], + options: { + service: 'buy', + query: { blockchain: Blockchain.CITREA, assetOut: 'USDC.e' }, + }, + }, + }, + { + id: 'juice', + img: 'juice', + next: { + page: 'wallets', + tiles: ['hw-wallet', 'metamask', 'walletconnect', 'cli'], + options: { + service: 'buy', + query: { blockchain: Blockchain.CITREA, assetOut: 'JUICE' }, + }, + }, + }, + ], + }, { id: 'sell', dfxStyle: true, @@ -860,6 +957,13 @@ export const FeatureTree: Page[] = [ page: 'sell-gnosis', }, }, + { + id: 'citrea', + img: 'citrea', + next: { + page: 'sell-citrea', + }, + }, ], }, { @@ -1410,6 +1514,96 @@ export const FeatureTree: Page[] = [ }, ], }, + { + id: 'sell-citrea', + dfxStyle: true, + tiles: [ + { + id: 'cbtc', + img: 'cbtc', + next: { + page: 'wallets', + tiles: ['hw-wallet', 'metamask', 'walletconnect', 'cli'], + options: { + service: 'sell', + query: { blockchain: Blockchain.CITREA, assetIn: 'cBTC' }, + }, + }, + }, + { + id: 'jusd', + img: 'jusd', + next: { + page: 'wallets', + tiles: ['hw-wallet', 'metamask', 'walletconnect', 'cli'], + options: { + service: 'sell', + query: { blockchain: Blockchain.CITREA, assetIn: 'JUSD' }, + }, + }, + }, + { + id: 'ctusd', + img: 'ctusd', + next: { + page: 'wallets', + tiles: ['hw-wallet', 'metamask', 'walletconnect', 'cli'], + options: { + service: 'sell', + query: { blockchain: Blockchain.CITREA, assetIn: 'ctUSD' }, + }, + }, + }, + { + id: 'wbtce', + img: 'wbtc', + next: { + page: 'wallets', + tiles: ['hw-wallet', 'metamask', 'walletconnect', 'cli'], + options: { + service: 'sell', + query: { blockchain: Blockchain.CITREA, assetIn: 'WBTC.e' }, + }, + }, + }, + { + id: 'usdte', + img: 'usdt', + next: { + page: 'wallets', + tiles: ['hw-wallet', 'metamask', 'walletconnect', 'cli'], + options: { + service: 'sell', + query: { blockchain: Blockchain.CITREA, assetIn: 'USDT.e' }, + }, + }, + }, + { + id: 'usdce', + img: 'usdc', + next: { + page: 'wallets', + tiles: ['hw-wallet', 'metamask', 'walletconnect', 'cli'], + options: { + service: 'sell', + query: { blockchain: Blockchain.CITREA, assetIn: 'USDC.e' }, + }, + }, + }, + { + id: 'juice', + img: 'juice', + next: { + page: 'wallets', + tiles: ['hw-wallet', 'metamask', 'walletconnect', 'cli'], + options: { + service: 'sell', + query: { blockchain: Blockchain.CITREA, assetIn: 'JUICE' }, + }, + }, + }, + ], + }, // --- LOGIN --- // { diff --git a/src/screens/blockchain-tx.screen.tsx b/src/screens/blockchain-tx.screen.tsx index 68ac5dfa..275ea2fc 100644 --- a/src/screens/blockchain-tx.screen.tsx +++ b/src/screens/blockchain-tx.screen.tsx @@ -31,6 +31,7 @@ const availableBlockchains = [ Blockchain.ARBITRUM, Blockchain.OPTIMISM, Blockchain.BASE, + Blockchain.CITREA, ]; const availableSigners = ['0x9229e0179a436CD0b77F731992307AC765Bc4b17']; diff --git a/src/util/evm.ts b/src/util/evm.ts index 9d2ba985..b6f02738 100644 --- a/src/util/evm.ts +++ b/src/util/evm.ts @@ -43,6 +43,8 @@ export class Evm { Blockchain.GNOSIS, Blockchain.BINANCE_SMART_CHAIN, Blockchain.HAQQ, + Blockchain.CITREA, + Blockchain.CITREA_TESTNET, ].includes(blockchain); } }