From 837ba93c2a6470780f925a987bc9bb7248754cfd Mon Sep 17 00:00:00 2001 From: Discostu Date: Wed, 20 May 2026 06:56:55 +0200 Subject: [PATCH 1/3] feat: integrate Citrea (4114) as second-class EVM chain Adds Citrea Bitcoin L2 mainnet (chainId 4114) as a second-class EVM chain behind the VITE_FEATURE_CITREA flag. Native gas token cBTC (18 decimals, BTC-pegged via Clementine BitVM bridge). Standard contract Phase 1-2 items implemented (CAIP, KnownChainIds, ChainAdapter, EvmBaseAdapter, Plugin, FeatureFlag, 10x HDWallet, viem/ethers, baseAsset, utils, CSP, asset generation, coingecko adapter, migration 335). cBTC pricing falls back to WBTC mainnet via manualRelatedAssetIndex (cBTC has no direct CoinGecko price as of mainnet launch). Incidental fix: market-service-manager treats price=0 as not-found in findByAssetId, so providers returning partial data with zero price don't block the related-asset fallback. Symmetric with the existing findPriceHistoryByAssetId behavior. Discovered during cBTC smoke testing. --- .env | 2 + .env.development | 2 + chains/citrea.json | 30 ++++ headers/csps/chains/citrea.ts | 11 ++ headers/csps/index.ts | 2 + .../generated/eip155_4114/adapter.json | 1 + .../src/adapters/coingecko/generated/index.ts | 2 + packages/caip/src/adapters/coingecko/index.ts | 6 + .../caip/src/adapters/coingecko/utils.test.ts | 3 + packages/caip/src/adapters/coingecko/utils.ts | 17 ++ packages/caip/src/constants.ts | 6 + .../chain-adapters/src/evm/EvmBaseAdapter.ts | 9 + .../src/evm/SecondClassEvmAdapter.ts | 2 + .../src/evm/citrea/CitreaChainAdapter.ts | 57 +++++++ .../chain-adapters/src/evm/citrea/index.ts | 1 + packages/chain-adapters/src/evm/index.ts | 1 + packages/chain-adapters/src/types.ts | 11 ++ .../contracts/src/ethersProviderSingleton.ts | 2 + packages/contracts/src/publicRpcUrls.ts | 1 + packages/contracts/src/viemClient.ts | 21 +++ packages/hdwallet-coinbase/src/coinbase.ts | 1 + packages/hdwallet-core/src/ethereum.ts | 1 + packages/hdwallet-core/src/wallet.ts | 4 + packages/hdwallet-gridplus/src/gridplus.ts | 1 + packages/hdwallet-keepkey/src/keepkey.ts | 1 + packages/hdwallet-ledger/src/ledger.ts | 1 + .../src/native-multichain.ts | 1 + .../src/shapeshift-multichain.ts | 1 + packages/hdwallet-native/src/ethereum.ts | 1 + packages/hdwallet-phantom/src/phantom.ts | 1 + packages/hdwallet-trezor/src/trezor.ts | 1 + packages/hdwallet-vultisig/src/vultisig.ts | 1 + .../src/walletconnectV2.ts | 3 +- packages/types/src/base.ts | 2 + packages/utils/src/assetData/baseAssets.ts | 17 ++ packages/utils/src/assetData/getBaseAsset.ts | 3 + packages/utils/src/chainIdToFeeAssetId.ts | 3 + .../utils/src/getAssetNamespaceFromChainId.ts | 1 + packages/utils/src/getChainShortName.ts | 2 + .../utils/src/getNativeFeeAssetReference.ts | 2 + public/generated/asset-manifest.json | 4 +- public/generated/asset-manifest.json.br | Bin 66 -> 68 bytes public/generated/asset-manifest.json.gz | Bin 78 -> 78 bytes public/generated/generatedAssetData.json | 159 +++++++++++++++++- public/generated/generatedAssetData.json.br | Bin 1896674 -> 1897575 bytes public/generated/generatedAssetData.json.gz | Bin 2740292 -> 2741373 bytes public/generated/relatedAssetIndex.json | 11 +- public/generated/relatedAssetIndex.json.br | Bin 179598 -> 179679 bytes public/generated/relatedAssetIndex.json.gz | Bin 211304 -> 211432 bytes scripts/generateAssetData/citrea/index.ts | 11 ++ scripts/generateAssetData/coingecko.ts | 10 ++ .../generateAssetData/generateAssetData.ts | 3 + .../generateChainRelatedAssetIndex.ts | 3 + .../generateRelatedAssetIndex.ts | 3 + .../hooks/useGetPopularAssetsQuery.tsx | 2 + src/config.ts | 2 + src/constants/chains.ts | 2 + src/context/PluginProvider/PluginProvider.tsx | 1 + .../WalletProvider/WalletConnectV2/config.ts | 6 +- .../useWalletSupportsChain.ts | 5 + src/lib/account/evm.ts | 3 + src/lib/asset-service/service/AssetService.ts | 2 + src/lib/coingecko/utils.ts | 2 + .../market-service/market-service-manager.ts | 5 +- src/pages/Markets/components/MarketsRow.tsx | 3 + src/plugins/activePlugins.ts | 2 + src/plugins/citrea/index.tsx | 49 ++++++ src/state/migrations/index.ts | 2 + .../slices/opportunitiesSlice/mappings.ts | 1 + .../slices/portfolioSlice/utils/index.ts | 4 + .../preferencesSlice/preferencesSlice.ts | 2 + src/test/mocks/store.ts | 1 + src/vite-env.d.ts | 2 + 73 files changed, 527 insertions(+), 8 deletions(-) create mode 100644 chains/citrea.json create mode 100644 headers/csps/chains/citrea.ts create mode 100644 packages/caip/src/adapters/coingecko/generated/eip155_4114/adapter.json create mode 100644 packages/chain-adapters/src/evm/citrea/CitreaChainAdapter.ts create mode 100644 packages/chain-adapters/src/evm/citrea/index.ts create mode 100644 scripts/generateAssetData/citrea/index.ts create mode 100644 src/plugins/citrea/index.tsx diff --git a/.env b/.env index 5f424cb4679..55c3e3014f1 100644 --- a/.env +++ b/.env @@ -108,6 +108,7 @@ VITE_FEATURE_BOB=false VITE_FEATURE_MODE=false VITE_FEATURE_SONEIUM=false VITE_FEATURE_SEI=false +VITE_FEATURE_CITREA=false VITE_FEATURE_YIELD_MULTI_ACCOUNT=true VITE_FEATURE_YIELD_XYZ=true VITE_FEATURE_YIELDS_PAGE=true @@ -235,6 +236,7 @@ VITE_TRON_NODE_URL=https://api.trongrid.io VITE_UNICHAIN_NODE_URL=https://mainnet.unichain.org VITE_WORLDCHAIN_NODE_URL=https://worldchain-mainnet.g.alchemy.com/public VITE_ZKSYNC_ERA_NODE_URL=https://mainnet.era.zksync.io +VITE_CITREA_NODE_URL=https://rpc.mainnet.citrea.xyz # midgard VITE_THORCHAIN_MIDGARD_URL=https://api.thorchain.shapeshift.com/midgard/v2 diff --git a/.env.development b/.env.development index 48d2f40d91b..bae66759c83 100644 --- a/.env.development +++ b/.env.development @@ -39,6 +39,7 @@ VITE_FEATURE_YIELD_MULTI_ACCOUNT=true VITE_FEATURE_AGENTIC_CHAT=true VITE_FEATURE_MM_NATIVE_MULTICHAIN=true VITE_FEATURE_NOTIFICATIONS_WEBSERVICES=true +VITE_FEATURE_CITREA=true # mixpanel VITE_MIXPANEL_TOKEN=a867ce40912a6b7d01d088cf62b0e1ff @@ -92,6 +93,7 @@ VITE_BASE_NODE_URL=https://dev-api.base.shapeshift.com/api/v1/jsonrpc VITE_THORCHAIN_NODE_URL=https://dev-api.thorchain.shapeshift.com/lcd VITE_MAYACHAIN_NODE_URL=https://dev-api.mayachain.shapeshift.com/lcd VITE_SOLANA_NODE_URL=https://dev-api.solana.shapeshift.com/api/v1/jsonrpc +VITE_CITREA_NODE_URL=https://rpc.mainnet.citrea.xyz # midgard VITE_THORCHAIN_MIDGARD_URL=https://dev-api.thorchain.shapeshift.com/midgard/v2 diff --git a/chains/citrea.json b/chains/citrea.json new file mode 100644 index 00000000000..b3a96ad91f4 --- /dev/null +++ b/chains/citrea.json @@ -0,0 +1,30 @@ +{ + "camelName": "citrea", + "pascalName": "Citrea", + "upperName": "CITREA", + "chainId": 4114, + "viemChainName": "citrea", + "nativeSymbol": "cBTC", + "nativeName": "Citrea Bitcoin", + "nativePrecision": 18, + "isNativeEth": false, + "color": "#F7931A", + "networkIconUrl": "https://assets.coingecko.com/asset_platforms/images/102132293/small/citrea.jpg", + "nativeIconUrl": "https://assets.coingecko.com/coins/images/102172844/large/cBTC.png", + "explorerUrl": "https://explorer.mainnet.citrea.xyz", + "explorerAddressLink": "https://explorer.mainnet.citrea.xyz/address/", + "explorerTxLink": "https://explorer.mainnet.citrea.xyz/tx/", + "rpcUrl": "https://rpc.mainnet.citrea.xyz", + "publicRpcUrls": ["https://rpc.mainnet.citrea.xyz"], + "coingeckoPlatform": "citrea", + "wrappedNativeAddress": "0x3100000000000000000000000000000000000006", + "relatedAssetKey": "eip155:4114/slip44:60", + "shortName": "citrea", + "swappers": { + "relay": { "supported": false }, + "across": { "supported": false }, + "portals": { "supported": false }, + "zerion": { "supported": false }, + "yieldxyz": { "supported": false } + } +} diff --git a/headers/csps/chains/citrea.ts b/headers/csps/chains/citrea.ts new file mode 100644 index 00000000000..2ab4c67581b --- /dev/null +++ b/headers/csps/chains/citrea.ts @@ -0,0 +1,11 @@ +import { loadEnv } from 'vite' + +import { PUBLIC_RPC_URLS } from '../../../packages/contracts/src/publicRpcUrls' +import type { Csp } from '../../types' + +const mode = process.env.MODE ?? process.env.NODE_ENV ?? 'development' +const env = loadEnv(mode, process.cwd(), '') + +export const csp: Csp = { + 'connect-src': [env.VITE_CITREA_NODE_URL, ...PUBLIC_RPC_URLS.citrea], +} diff --git a/headers/csps/index.ts b/headers/csps/index.ts index 93352adb685..0e84d132c34 100644 --- a/headers/csps/index.ts +++ b/headers/csps/index.ts @@ -14,6 +14,7 @@ import { csp as blast } from './chains/blast' import { csp as bnbsmartchain } from './chains/bnbsmartchain' import { csp as bob } from './chains/bob' import { csp as celo } from './chains/celo' +import { csp as citrea } from './chains/citrea' import { csp as cosmos } from './chains/cosmos' import { csp as cronos } from './chains/cronos' import { csp as dogecoin } from './chains/dogecoin' @@ -206,4 +207,5 @@ export const csps = [ railway, discord, yieldxyz, + citrea, ] diff --git a/packages/caip/src/adapters/coingecko/generated/eip155_4114/adapter.json b/packages/caip/src/adapters/coingecko/generated/eip155_4114/adapter.json new file mode 100644 index 00000000000..5c28a5a2519 --- /dev/null +++ b/packages/caip/src/adapters/coingecko/generated/eip155_4114/adapter.json @@ -0,0 +1 @@ +{"eip155:4114/slip44:60":"citrea","eip155:4114/erc20:0x547afd93b9c47d552059feb556909e017f8a9b25":"citrea","eip155:4114/erc20:0xe045e6c36cf77faa2cfb54466d71a3aef7bbe839":"citrea-bridged-usdc","eip155:4114/erc20:0x9f3096bac87e7f03dc09b0b416eb0df837304dc4":"citrea-bridged-usdt","eip155:4114/erc20:0xdf240dc08b0fdad1d93b74d5048871232f6bea3d":"citrea-bridged-wbtc-citrea","eip155:4114/erc20:0x8d82c4e3c936c7b5724a382a9c5a4e6eb7ab6d5d":"citrea-usd","eip155:4114/erc20:0xac8c1aeb584765db16ac3e08d4736cfce198589b":"generic-usd","eip155:4114/erc20:0x2a36f2b204b46fd82653cd06d00c7ff757c99ae4":"juice-protocol","eip155:4114/erc20:0x1b70ae756b1089cc5948e4f8a2ad498df30e897d":"savings-vault-jusd-citrea","eip155:4114/erc20:0x384157027b1cdeac4e26e3709667bb28735379bb":"symbiosis-btc-citrea","eip155:4114/erc20:0x3100000000000000000000000000000000000006":"wrapped-citrea-bitcoin"} \ No newline at end of file diff --git a/packages/caip/src/adapters/coingecko/generated/index.ts b/packages/caip/src/adapters/coingecko/generated/index.ts index e8e5bb68b88..923daa376c3 100644 --- a/packages/caip/src/adapters/coingecko/generated/index.ts +++ b/packages/caip/src/adapters/coingecko/generated/index.ts @@ -36,6 +36,7 @@ import flowevm from "./eip155_747/adapter.json"; import celo from "./eip155_42220/adapter.json"; import sei from "./eip155_1329/adapter.json"; import abstract from "./eip155_2741/adapter.json"; +import citrea from "./eip155_4114/adapter.json"; import cosmos from "./cosmos_cosmoshub-4/adapter.json"; import thorchain from "./cosmos_thorchain-1/adapter.json"; import mayachain from "./cosmos_mayachain-mainnet-v1/adapter.json"; @@ -86,6 +87,7 @@ export { celo, sei, abstract, + citrea, cosmos, thorchain, mayachain, diff --git a/packages/caip/src/adapters/coingecko/index.ts b/packages/caip/src/adapters/coingecko/index.ts index 59983dcca4e..3644a2afe4f 100644 --- a/packages/caip/src/adapters/coingecko/index.ts +++ b/packages/caip/src/adapters/coingecko/index.ts @@ -16,6 +16,7 @@ import { celoChainId, CHAIN_NAMESPACE, CHAIN_REFERENCE, + citreaChainId, cosmosChainId, cronosChainId, ethChainId, @@ -100,6 +101,7 @@ export enum CoingeckoAssetPlatform { Ton = 'the-open-network', Near = 'near-protocol', Abstract = 'abstract', + Citrea = 'citrea', } type CoinGeckoId = string @@ -198,6 +200,8 @@ export const chainIdToCoingeckoAssetPlatform = (chainId: ChainId): string => { return CoingeckoAssetPlatform.Soneium case CHAIN_REFERENCE.SeiMainnet: return CoingeckoAssetPlatform.Sei + case CHAIN_REFERENCE.CitreaMainnet: + return CoingeckoAssetPlatform.Citrea default: throw new Error( `chainNamespace ${chainNamespace}, chainReference ${chainReference} not supported.`, @@ -367,6 +371,8 @@ export const coingeckoAssetPlatformToChainId = ( return tonChainId case CoingeckoAssetPlatform.Near: return nearChainId + case CoingeckoAssetPlatform.Citrea: + return citreaChainId default: return undefined } diff --git a/packages/caip/src/adapters/coingecko/utils.test.ts b/packages/caip/src/adapters/coingecko/utils.test.ts index 2a2d92b2dec..8f467b5f367 100644 --- a/packages/caip/src/adapters/coingecko/utils.test.ts +++ b/packages/caip/src/adapters/coingecko/utils.test.ts @@ -242,6 +242,9 @@ describe('adapters:coingecko:utils', () => { 'eip155:2741': { 'eip155:2741/slip44:60': 'ethereum', }, + 'eip155:4114': { + 'eip155:4114/slip44:60': 'citrea-bridged-bitcoin', + }, 'near:mainnet': { 'near:mainnet/slip44:397': 'near', }, diff --git a/packages/caip/src/adapters/coingecko/utils.ts b/packages/caip/src/adapters/coingecko/utils.ts index 66a2846f900..d9b3185d75e 100644 --- a/packages/caip/src/adapters/coingecko/utils.ts +++ b/packages/caip/src/adapters/coingecko/utils.ts @@ -28,6 +28,8 @@ import { celoChainId, CHAIN_NAMESPACE, CHAIN_REFERENCE, + citreaAssetId, + citreaChainId, cosmosChainId, cronosAssetId, cronosChainId, @@ -665,6 +667,20 @@ export const parseData = (coins: CoingeckoCoin[]): AssetMap => { } } + if (Object.keys(platforms).includes(CoingeckoAssetPlatform.Citrea)) { + try { + const assetId = toAssetId({ + chainNamespace: CHAIN_NAMESPACE.Evm, + chainReference: CHAIN_REFERENCE.CitreaMainnet, + assetNamespace: 'erc20', + assetReference: platforms[CoingeckoAssetPlatform.Citrea], + }) + prev[citreaChainId][assetId] = id + } catch { + // unable to create assetId, skip token + } + } + return prev }, { @@ -707,6 +723,7 @@ export const parseData = (coins: CoingeckoCoin[]): AssetMap => { [suiChainId]: { [suiAssetId]: 'sui' }, [nearChainId]: { [nearAssetId]: 'near' }, [tonChainId]: { [tonAssetId]: 'the-open-network' }, + [citreaChainId]: { [citreaAssetId]: 'citrea-bridged-bitcoin' }, }, ) diff --git a/packages/caip/src/constants.ts b/packages/caip/src/constants.ts index 7bed0cf1c18..962c67b0035 100644 --- a/packages/caip/src/constants.ts +++ b/packages/caip/src/constants.ts @@ -50,6 +50,7 @@ export const suiAssetId: AssetId = 'sui:35834a8a/slip44:784' export const nearAssetId: AssetId = 'near:mainnet/slip44:397' export const starknetAssetId: AssetId = 'starknet:SN_MAIN/slip44:9004' export const tonAssetId: AssetId = 'ton:mainnet/slip44:607' +export const citreaAssetId: AssetId = 'eip155:4114/slip44:60' export const uniV2EthFoxArbitrumAssetId: AssetId = 'eip155:42161/erc20:0x5f6ce0ca13b87bd738519545d3e018e70e339c24' @@ -142,6 +143,7 @@ export const suiChainId: ChainId = 'sui:35834a8a' export const nearChainId: ChainId = 'near:mainnet' export const starknetChainId: ChainId = 'starknet:SN_MAIN' export const tonChainId: ChainId = 'ton:mainnet' +export const citreaChainId: ChainId = 'eip155:4114' export const CHAIN_NAMESPACE = { Evm: 'eip155', @@ -210,6 +212,7 @@ export const CHAIN_REFERENCE = { StarknetMainnet: 'SN_MAIN', // https://namespaces.chainagnostic.org/starknet/caip2 TonMainnet: 'mainnet', // TON Mainnet AbstractMainnet: '2741', // https://abscan.org + CitreaMainnet: '4114', // https://explorer.mainnet.citrea.xyz } as const export const ASSET_NAMESPACE = { @@ -277,6 +280,7 @@ export const ASSET_REFERENCE = { Starknet: '9004', Ton: '607', Abstract: '60', // evm chain which uses ethereum derivation path as common practice + Citrea: '60', // evm chain which uses ethereum derivation path as common practice } as const export const VALID_CHAIN_IDS: ValidChainMap = Object.freeze({ @@ -323,6 +327,7 @@ export const VALID_CHAIN_IDS: ValidChainMap = Object.freeze({ CHAIN_REFERENCE.SeiMainnet, CHAIN_REFERENCE.CeloMainnet, CHAIN_REFERENCE.AbstractMainnet, + CHAIN_REFERENCE.CitreaMainnet, ], [CHAIN_NAMESPACE.CosmosSdk]: [ CHAIN_REFERENCE.CosmosHubMainnet, @@ -407,4 +412,5 @@ export const FEE_ASSET_IDS = [ katanaAssetId, etherealAssetId, flowEvmAssetId, + citreaAssetId, ] diff --git a/packages/chain-adapters/src/evm/EvmBaseAdapter.ts b/packages/chain-adapters/src/evm/EvmBaseAdapter.ts index 9d4cde8bfb8..45f505a8722 100644 --- a/packages/chain-adapters/src/evm/EvmBaseAdapter.ts +++ b/packages/chain-adapters/src/evm/EvmBaseAdapter.ts @@ -18,6 +18,7 @@ import { supportsBob, supportsBSC, supportsCelo, + supportsCitrea, supportsCronos, supportsETH, supportsEthereal, @@ -135,6 +136,7 @@ export const evmChainIds = [ KnownChainIds.SoneiumMainnet, KnownChainIds.SeiMainnet, KnownChainIds.AbstractMainnet, + KnownChainIds.CitreaMainnet, ] as const export type EvmChainAdapter = EvmBaseAdapter @@ -283,6 +285,8 @@ export abstract class EvmBaseAdapter implements IChainAdap return supportsSoneium(wallet) case Number(fromChainId(KnownChainIds.SeiMainnet).chainReference): return supportsSei(wallet) + case Number(fromChainId(KnownChainIds.CitreaMainnet).chainReference): + return supportsCitrea(wallet) default: return false } @@ -490,6 +494,11 @@ export abstract class EvmBaseAdapter implements IChainAdap symbol: 'ETH', explorer: 'https://abscan.org', }, + [KnownChainIds.CitreaMainnet]: { + name: 'Citrea Bitcoin', + symbol: 'cBTC', + explorer: 'https://explorer.mainnet.citrea.xyz', + }, }[this.chainId] try { diff --git a/packages/chain-adapters/src/evm/SecondClassEvmAdapter.ts b/packages/chain-adapters/src/evm/SecondClassEvmAdapter.ts index 8e77bf917f5..6593e689de9 100644 --- a/packages/chain-adapters/src/evm/SecondClassEvmAdapter.ts +++ b/packages/chain-adapters/src/evm/SecondClassEvmAdapter.ts @@ -5,6 +5,7 @@ import { blastChainId, bobChainId, celoChainId, + citreaChainId, cronosChainId, flowEvmChainId, hemiChainId, @@ -75,6 +76,7 @@ const WRAPPED_NATIVE_CONTRACT_BY_CHAIN_ID: Partial> = { [storyChainId]: '0x1514000000000000000000000000000000000000', [plumeChainId]: '0xea237441c92cae6fc17caaf9a7acb3f953be4bd1', [seiChainId]: '0xE30feDd158A2e3b13e9badaeABaFc5516e95e8C7', + [citreaChainId]: '0x3100000000000000000000000000000000000006', } const BATCH_SIZE = 500 diff --git a/packages/chain-adapters/src/evm/citrea/CitreaChainAdapter.ts b/packages/chain-adapters/src/evm/citrea/CitreaChainAdapter.ts new file mode 100644 index 00000000000..5effab35c14 --- /dev/null +++ b/packages/chain-adapters/src/evm/citrea/CitreaChainAdapter.ts @@ -0,0 +1,57 @@ +import type { AssetId } from '@shapeshiftoss/caip' +import { ASSET_REFERENCE, citreaAssetId } from '@shapeshiftoss/caip' +import type { RootBip44Params } from '@shapeshiftoss/types' +import { KnownChainIds } from '@shapeshiftoss/types' + +import { ChainAdapterDisplayName } from '../../types' +import type { TokenInfo } from '../SecondClassEvmAdapter' +import { SecondClassEvmAdapter } from '../SecondClassEvmAdapter' + +const SUPPORTED_CHAIN_IDS = [KnownChainIds.CitreaMainnet] +const DEFAULT_CHAIN_ID = KnownChainIds.CitreaMainnet + +export type ChainAdapterArgs = { + rpcUrl: string + getKnownTokens: () => TokenInfo[] +} + +export const isCitreaChainAdapter = (adapter: unknown): adapter is ChainAdapter => { + return (adapter as ChainAdapter).getType() === KnownChainIds.CitreaMainnet +} + +export class ChainAdapter extends SecondClassEvmAdapter { + public static readonly rootBip44Params: RootBip44Params = { + purpose: 44, + coinType: Number(ASSET_REFERENCE.Citrea), + accountNumber: 0, + } + + constructor(args: ChainAdapterArgs) { + super({ + assetId: citreaAssetId, + chainId: DEFAULT_CHAIN_ID, + rootBip44Params: ChainAdapter.rootBip44Params, + supportedChainIds: SUPPORTED_CHAIN_IDS, + rpcUrl: args.rpcUrl, + getKnownTokens: args.getKnownTokens, + }) + } + + getDisplayName() { + return ChainAdapterDisplayName.Citrea + } + + getName() { + return 'Citrea' + } + + getType(): KnownChainIds.CitreaMainnet { + return KnownChainIds.CitreaMainnet + } + + getFeeAssetId(): AssetId { + return this.assetId + } +} + +export type { TokenInfo } diff --git a/packages/chain-adapters/src/evm/citrea/index.ts b/packages/chain-adapters/src/evm/citrea/index.ts new file mode 100644 index 00000000000..e1562615315 --- /dev/null +++ b/packages/chain-adapters/src/evm/citrea/index.ts @@ -0,0 +1 @@ +export * from './CitreaChainAdapter' diff --git a/packages/chain-adapters/src/evm/index.ts b/packages/chain-adapters/src/evm/index.ts index defef25e97d..111a9f8f492 100644 --- a/packages/chain-adapters/src/evm/index.ts +++ b/packages/chain-adapters/src/evm/index.ts @@ -4,6 +4,7 @@ export { isSecondClassEvmAdapter, SecondClassEvmAdapter } from './SecondClassEvm export type { SecondClassEvmAdapterArgs, TokenInfo } from './SecondClassEvmAdapter' export * as evm from './evm' +export * as citrea from './citrea' export * as abstract from './abstract' export * as ethereum from './ethereum' diff --git a/packages/chain-adapters/src/types.ts b/packages/chain-adapters/src/types.ts index fbdd05171fb..a21e1f6c5d1 100644 --- a/packages/chain-adapters/src/types.ts +++ b/packages/chain-adapters/src/types.ts @@ -71,6 +71,8 @@ type ChainSpecificAccount = ChainSpecific< [KnownChainIds.SoneiumMainnet]: evm.Account [KnownChainIds.SeiMainnet]: evm.Account [KnownChainIds.AbstractMainnet]: evm.Account + [KnownChainIds.CitreaMainnet]: evm.Account + [KnownChainIds.BitcoinMainnet]: utxo.Account [KnownChainIds.BitcoinCashMainnet]: utxo.Account [KnownChainIds.DogecoinMainnet]: utxo.Account @@ -145,6 +147,8 @@ type ChainSpecificFeeData = ChainSpecific< [KnownChainIds.SoneiumMainnet]: evm.FeeData [KnownChainIds.SeiMainnet]: evm.FeeData [KnownChainIds.AbstractMainnet]: evm.FeeData + [KnownChainIds.CitreaMainnet]: evm.FeeData + [KnownChainIds.BitcoinMainnet]: utxo.FeeData [KnownChainIds.BitcoinCashMainnet]: utxo.FeeData [KnownChainIds.DogecoinMainnet]: utxo.FeeData @@ -252,6 +256,8 @@ export type ChainSignTx = { [KnownChainIds.SoneiumMainnet]: ETHSignTx [KnownChainIds.SeiMainnet]: ETHSignTx [KnownChainIds.AbstractMainnet]: ETHSignTx + [KnownChainIds.CitreaMainnet]: ETHSignTx + [KnownChainIds.BitcoinMainnet]: BTCSignTx [KnownChainIds.BitcoinCashMainnet]: BTCSignTx [KnownChainIds.DogecoinMainnet]: BTCSignTx @@ -331,6 +337,8 @@ export type ChainSpecificBuildTxData = ChainSpecific< [KnownChainIds.SoneiumMainnet]: evm.BuildTxInput [KnownChainIds.SeiMainnet]: evm.BuildTxInput [KnownChainIds.AbstractMainnet]: evm.BuildTxInput + [KnownChainIds.CitreaMainnet]: evm.BuildTxInput + [KnownChainIds.BitcoinMainnet]: utxo.BuildTxInput [KnownChainIds.BitcoinCashMainnet]: utxo.BuildTxInput [KnownChainIds.DogecoinMainnet]: utxo.BuildTxInput @@ -460,6 +468,8 @@ type ChainSpecificGetFeeDataInput = ChainSpecific< [KnownChainIds.SoneiumMainnet]: evm.GetFeeDataInput [KnownChainIds.SeiMainnet]: evm.GetFeeDataInput [KnownChainIds.AbstractMainnet]: evm.GetFeeDataInput + [KnownChainIds.CitreaMainnet]: evm.GetFeeDataInput + [KnownChainIds.BitcoinMainnet]: utxo.GetFeeDataInput [KnownChainIds.BitcoinCashMainnet]: utxo.GetFeeDataInput [KnownChainIds.DogecoinMainnet]: utxo.GetFeeDataInput @@ -566,6 +576,7 @@ export enum ChainAdapterDisplayName { Starknet = 'Starknet', Ton = 'TON', Abstract = 'Abstract', + Citrea = 'Citrea', } export type BroadcastTransactionInput = { diff --git a/packages/contracts/src/ethersProviderSingleton.ts b/packages/contracts/src/ethersProviderSingleton.ts index 1d512384c78..67d41f5e892 100644 --- a/packages/contracts/src/ethersProviderSingleton.ts +++ b/packages/contracts/src/ethersProviderSingleton.ts @@ -82,6 +82,8 @@ export const rpcUrlByChainId = (chainId: EvmChainId): string => { return PUBLIC_RPC_URLS.sei[0] case KnownChainIds.AbstractMainnet: return PUBLIC_RPC_URLS.abstract[0] + case KnownChainIds.CitreaMainnet: + return process.env.VITE_CITREA_NODE_URL default: return assertUnreachable(chainId) } diff --git a/packages/contracts/src/publicRpcUrls.ts b/packages/contracts/src/publicRpcUrls.ts index 12d5a518b2e..8a066ba40f3 100644 --- a/packages/contracts/src/publicRpcUrls.ts +++ b/packages/contracts/src/publicRpcUrls.ts @@ -95,4 +95,5 @@ export const PUBLIC_RPC_URLS = { 'https://zksync.drpc.org', 'https://zksync.api.onfinality.io/public', ], + citrea: ['https://rpc.mainnet.citrea.xyz'], } as const diff --git a/packages/contracts/src/viemClient.ts b/packages/contracts/src/viemClient.ts index 076dbc2c0dd..85e6a1a6921 100644 --- a/packages/contracts/src/viemClient.ts +++ b/packages/contracts/src/viemClient.ts @@ -187,6 +187,19 @@ export const ethereal = defineChain({ }, }) +export const citrea = defineChain({ + id: 4114, + name: 'Citrea Mainnet', + nativeCurrency: { name: 'Citrea Bitcoin', symbol: 'cBTC', decimals: 18 }, + rpcUrls: { default: { http: ['https://rpc.mainnet.citrea.xyz'] } }, + blockExplorers: { + default: { + name: 'Citrea Explorer', + url: 'https://explorer.mainnet.citrea.xyz', + }, + }, +}) + export const viemEtherealClient = createPublicClient({ chain: ethereal, transport: createRpcTransport(undefined, PUBLIC_RPC_URLS.ethereal), @@ -257,6 +270,11 @@ export const viemSoneiumClient = createPublicClient({ transport: createRpcTransport(undefined, PUBLIC_RPC_URLS.soneium), }) as PublicClient +export const viemCitreaClient = createPublicClient({ + chain: citrea, + transport: createRpcTransport(undefined, PUBLIC_RPC_URLS.citrea), +}) as PublicClient + export const viemClientByChainId: Record = { [KnownChainIds.EthereumMainnet]: viemEthMainnetClient, [KnownChainIds.BnbSmartChainMainnet]: viemBscClient, @@ -293,6 +311,7 @@ export const viemClientByChainId: Record = { [KnownChainIds.SoneiumMainnet]: viemSoneiumClient, [KnownChainIds.SeiMainnet]: viemSeiClient, [KnownChainIds.AbstractMainnet]: viemAbstractClient, + [KnownChainIds.CitreaMainnet]: viemCitreaClient, } export const viemNetworkIdByChainId: Record = { @@ -331,6 +350,7 @@ export const viemNetworkIdByChainId: Record = { [KnownChainIds.SoneiumMainnet]: soneium.id, [KnownChainIds.SeiMainnet]: sei.id, [KnownChainIds.AbstractMainnet]: abstract.id, + [KnownChainIds.CitreaMainnet]: citrea.id, } export const viemClientByNetworkId: Record = { @@ -369,6 +389,7 @@ export const viemClientByNetworkId: Record = { [soneium.id]: viemSoneiumClient, [sei.id]: viemSeiClient, [abstract.id]: viemAbstractClient, + [citrea.id]: viemCitreaClient, } export const assertGetViemClient = (chainId: ChainId): PublicClient => { diff --git a/packages/hdwallet-coinbase/src/coinbase.ts b/packages/hdwallet-coinbase/src/coinbase.ts index 3c783737f6f..b752997658d 100644 --- a/packages/hdwallet-coinbase/src/coinbase.ts +++ b/packages/hdwallet-coinbase/src/coinbase.ts @@ -154,6 +154,7 @@ export class CoinbaseHDWallet implements core.HDWallet, core.ETHWallet { readonly _supportsKavaInfo = false readonly _supportsTerra = false readonly _supportsTerraInfo = false + readonly _supportsCitrea = false info: CoinbaseHDWalletInfo & core.HDWalletInfo ethAddress?: Address | null diff --git a/packages/hdwallet-core/src/ethereum.ts b/packages/hdwallet-core/src/ethereum.ts index 74cd9211e48..4a892a26adb 100644 --- a/packages/hdwallet-core/src/ethereum.ts +++ b/packages/hdwallet-core/src/ethereum.ts @@ -232,6 +232,7 @@ export interface ETHWallet extends ETHWalletInfo, HDWallet { readonly _supportsCronos: boolean readonly _supportsUnichain: boolean readonly _supportsSoneium: boolean + readonly _supportsCitrea: boolean ethGetAddress(msg: ETHGetAddress): Promise
ethGetAddresses?(msgs: ETHGetAddress[]): Promise diff --git a/packages/hdwallet-core/src/wallet.ts b/packages/hdwallet-core/src/wallet.ts index 97ec2596115..c384243b9db 100644 --- a/packages/hdwallet-core/src/wallet.ts +++ b/packages/hdwallet-core/src/wallet.ts @@ -277,6 +277,10 @@ export function supportsSoneium(wallet: HDWallet): wallet is ETHWallet { return isObject(wallet) && (wallet as any)._supportsSoneium } +export function supportsCitrea(wallet: HDWallet): wallet is ETHWallet { + return isObject(wallet) && (wallet as any)._supportsCitrea +} + export function infoCosmos(info: HDWalletInfo): info is CosmosWalletInfo { return isObject(info) && (info as any)._supportsCosmosInfo } diff --git a/packages/hdwallet-gridplus/src/gridplus.ts b/packages/hdwallet-gridplus/src/gridplus.ts index 054bf4b4b08..2c0cc1a129e 100644 --- a/packages/hdwallet-gridplus/src/gridplus.ts +++ b/packages/hdwallet-gridplus/src/gridplus.ts @@ -390,6 +390,7 @@ export class GridPlusHDWallet readonly _supportsCosmos = true readonly _supportsETH = true readonly _supportsEthSwitchChain = false + readonly _supportsCitrea = false readonly _supportsGnosis = true readonly _supportsMayachain = true readonly _supportsOptimism = true diff --git a/packages/hdwallet-keepkey/src/keepkey.ts b/packages/hdwallet-keepkey/src/keepkey.ts index 4afe565a53a..215eff17eb5 100644 --- a/packages/hdwallet-keepkey/src/keepkey.ts +++ b/packages/hdwallet-keepkey/src/keepkey.ts @@ -576,6 +576,7 @@ export class KeepKeyHDWallet readonly _supportsCronos = false readonly _supportsUnichain = false readonly _supportsSoneium = false + readonly _supportsCitrea = false readonly _supportsBTC = true _supportsCosmos = true _supportsOsmosis = true diff --git a/packages/hdwallet-ledger/src/ledger.ts b/packages/hdwallet-ledger/src/ledger.ts index a9d4e1b9343..620b5865ee9 100644 --- a/packages/hdwallet-ledger/src/ledger.ts +++ b/packages/hdwallet-ledger/src/ledger.ts @@ -460,6 +460,7 @@ export class LedgerHDWallet readonly _supportsSui = true readonly _supportsTron = true readonly _supportsNear = true + readonly _supportsCitrea = true _isLedger = true diff --git a/packages/hdwallet-metamask-multichain/src/native-multichain.ts b/packages/hdwallet-metamask-multichain/src/native-multichain.ts index b970148202f..d012074c9c1 100644 --- a/packages/hdwallet-metamask-multichain/src/native-multichain.ts +++ b/packages/hdwallet-metamask-multichain/src/native-multichain.ts @@ -304,6 +304,7 @@ export class MetaMaskNativeMultiChainHDWallet readonly _supportsCronos = true readonly _supportsUnichain = true readonly _supportsSoneium = true + readonly _supportsCitrea = true readonly _supportsOsmosisInfo = false readonly _supportsOsmosis = false readonly _supportsBinanceInfo = false diff --git a/packages/hdwallet-metamask-multichain/src/shapeshift-multichain.ts b/packages/hdwallet-metamask-multichain/src/shapeshift-multichain.ts index 472fcee7638..5172aeacf66 100644 --- a/packages/hdwallet-metamask-multichain/src/shapeshift-multichain.ts +++ b/packages/hdwallet-metamask-multichain/src/shapeshift-multichain.ts @@ -316,6 +316,7 @@ export class MetaMaskMultiChainHDWallet readonly _supportsEos = false readonly _supportsThorchainInfo = true readonly _supportsThorchain = true + readonly _supportsCitrea = true info: MetaMaskMultiChainHDWalletInfo & core.HDWalletInfo bitcoinAddress?: string | null diff --git a/packages/hdwallet-native/src/ethereum.ts b/packages/hdwallet-native/src/ethereum.ts index f01d48ac42e..8fcbd59e5ce 100644 --- a/packages/hdwallet-native/src/ethereum.ts +++ b/packages/hdwallet-native/src/ethereum.ts @@ -92,6 +92,7 @@ export function MixinNativeETHWallet { - return [1, 10, 56, 100, 137, 43114, 2741].includes(chainId) + return [1, 10, 56, 100, 137, 43114, 2741, 4114].includes(chainId) } public async ethSupportsSecureTransfer(): Promise { @@ -234,6 +234,7 @@ export class WalletConnectV2HDWallet implements HDWallet, ETHWallet, BTCWallet { readonly _supportsCronos = true readonly _supportsUnichain = true readonly _supportsSoneium = true + readonly _supportsCitrea = true info: WalletConnectV2WalletInfo & HDWalletInfo provider: EthereumProvider diff --git a/packages/types/src/base.ts b/packages/types/src/base.ts index eeeb6313fb3..8125b4009d4 100644 --- a/packages/types/src/base.ts +++ b/packages/types/src/base.ts @@ -63,6 +63,7 @@ export enum KnownChainIds { StarknetMainnet = 'starknet:SN_MAIN', TonMainnet = 'ton:mainnet', AbstractMainnet = 'eip155:2741', + CitreaMainnet = 'eip155:4114', } export type EvmChainId = @@ -101,6 +102,7 @@ export type EvmChainId = | KnownChainIds.ModeMainnet | KnownChainIds.SoneiumMainnet | KnownChainIds.AbstractMainnet + | KnownChainIds.CitreaMainnet export type CosmosSdkChainId = | KnownChainIds.CosmosMainnet diff --git a/packages/utils/src/assetData/baseAssets.ts b/packages/utils/src/assetData/baseAssets.ts index 2274323a451..d88fd639b4c 100644 --- a/packages/utils/src/assetData/baseAssets.ts +++ b/packages/utils/src/assetData/baseAssets.ts @@ -857,3 +857,20 @@ export const ton: Readonly = Object.freeze({ explorerTxLink: 'https://tonscan.org/tx/', relatedAssetKey: null, }) + +export const citrea: Readonly = Object.freeze({ + assetId: caip.citreaAssetId, + chainId: caip.citreaChainId, + name: 'Citrea Bitcoin', + networkName: 'Citrea', + symbol: 'cBTC', + precision: 18, + color: '#F7931A', + networkColor: '#F7931A', + icon: 'https://assets.coingecko.com/coins/images/102172844/large/cBTC.png', + networkIcon: 'https://assets.coingecko.com/asset_platforms/images/102132293/small/citrea.jpg', + explorer: 'https://explorer.mainnet.citrea.xyz', + explorerAddressLink: 'https://explorer.mainnet.citrea.xyz/address/', + explorerTxLink: 'https://explorer.mainnet.citrea.xyz/tx/', + relatedAssetKey: null, +}) diff --git a/packages/utils/src/assetData/getBaseAsset.ts b/packages/utils/src/assetData/getBaseAsset.ts index 33e613002c7..fe0ea391c48 100644 --- a/packages/utils/src/assetData/getBaseAsset.ts +++ b/packages/utils/src/assetData/getBaseAsset.ts @@ -16,6 +16,7 @@ import { bnbsmartchain, bobChain, celo, + citrea, cronos, dogecoin, ethereal, @@ -156,6 +157,8 @@ export const getBaseAsset = (chainId: ChainId): Readonly => { return ton case KnownChainIds.AbstractMainnet: return abstract + case KnownChainIds.CitreaMainnet: + return citrea default: return assertUnreachable(knownChainId) } diff --git a/packages/utils/src/chainIdToFeeAssetId.ts b/packages/utils/src/chainIdToFeeAssetId.ts index 01a9bfab4bb..3ac7ef1ac2e 100644 --- a/packages/utils/src/chainIdToFeeAssetId.ts +++ b/packages/utils/src/chainIdToFeeAssetId.ts @@ -11,6 +11,7 @@ import { bscAssetId, btcAssetId, celoAssetId, + citreaAssetId, cosmosAssetId, cronosAssetId, dogeAssetId, @@ -155,6 +156,8 @@ export const chainIdToFeeAssetId = (_chainId: ChainId): AssetId => { return tonAssetId case KnownChainIds.AbstractMainnet: return abstractAssetId + case KnownChainIds.CitreaMainnet: + return citreaAssetId default: return assertUnreachable(chainId) } diff --git a/packages/utils/src/getAssetNamespaceFromChainId.ts b/packages/utils/src/getAssetNamespaceFromChainId.ts index 107b891cb36..db1a413817d 100644 --- a/packages/utils/src/getAssetNamespaceFromChainId.ts +++ b/packages/utils/src/getAssetNamespaceFromChainId.ts @@ -49,6 +49,7 @@ export const getAssetNamespaceFromChainId = (chainId: KnownChainIds): AssetNames case KnownChainIds.FlowEvmMainnet: case KnownChainIds.CeloMainnet: case KnownChainIds.AbstractMainnet: + case KnownChainIds.CitreaMainnet: return ASSET_NAMESPACE.erc20 case KnownChainIds.StarknetMainnet: return ASSET_NAMESPACE.starknetToken diff --git a/packages/utils/src/getChainShortName.ts b/packages/utils/src/getChainShortName.ts index a5012b04e34..7e1b7f3b8e1 100644 --- a/packages/utils/src/getChainShortName.ts +++ b/packages/utils/src/getChainShortName.ts @@ -102,6 +102,8 @@ export const getChainShortName = (chainId: KnownChainIds) => { return 'TON' case KnownChainIds.AbstractMainnet: return 'ABS' + case KnownChainIds.CitreaMainnet: + return 'citrea' default: { assertUnreachable(chainId) } diff --git a/packages/utils/src/getNativeFeeAssetReference.ts b/packages/utils/src/getNativeFeeAssetReference.ts index 53862e88e3d..f4ec5789097 100644 --- a/packages/utils/src/getNativeFeeAssetReference.ts +++ b/packages/utils/src/getNativeFeeAssetReference.ts @@ -94,6 +94,8 @@ export const getNativeFeeAssetReference = ( return ASSET_REFERENCE.Mode case CHAIN_REFERENCE.SoneiumMainnet: return ASSET_REFERENCE.Soneium + case CHAIN_REFERENCE.CitreaMainnet: + return ASSET_REFERENCE.Citrea default: throw new Error(`Chain namespace ${chainNamespace} on ${chainReference} not supported.`) } diff --git a/public/generated/asset-manifest.json b/public/generated/asset-manifest.json index 3cc2743eebb..66b9195dfca 100644 --- a/public/generated/asset-manifest.json +++ b/public/generated/asset-manifest.json @@ -1,4 +1,4 @@ { - "assetData": "d38a9fe9", - "relatedAssetIndex": "b8be8a11" + "assetData": "e1aff009", + "relatedAssetIndex": "2ec10a73" } \ No newline at end of file diff --git a/public/generated/asset-manifest.json.br b/public/generated/asset-manifest.json.br index 37b0ed113fadc65ce90fe7910cd277e777a766ec..3bd5f35cbdcad8920953d70b394dbaea68a28cf3 100644 GIT binary patch literal 68 zcmeB{Z>Z){P*6%NE>10RNi0cJvQkh=HB3xPGcd4J(g8^orRF4-q^3B6RCwm4q*j2G R7^Nl~8YG$i{$b0OR5tUH||9 diff --git a/public/generated/generatedAssetData.json b/public/generated/generatedAssetData.json index 1bcf05249aa..92bd1666f47 100644 --- a/public/generated/generatedAssetData.json +++ b/public/generated/generatedAssetData.json @@ -341388,6 +341388,152 @@ "explorerAddressLink": "https://tronscan.org/#/address/", "explorerTxLink": "https://tronscan.org/#/transaction/", "relatedAssetKey": null + }, + "eip155:4114/erc20:0x1b70ae756b1089cc5948e4f8a2ad498df30e897d": { + "assetId": "eip155:4114/erc20:0x1b70ae756b1089cc5948e4f8a2ad498df30e897d", + "chainId": "eip155:4114", + "name": "Savings Vault JUSD (Citrea)", + "precision": 18, + "color": "#FFFFFF", + "icon": "https://assets.coingecko.com/coins/images/102172892/large/JuiceDollar_Coinlogo.png?1776439475", + "symbol": "SVJUSD", + "explorer": "https://explorer.mainnet.citrea.xyz", + "explorerAddressLink": "https://explorer.mainnet.citrea.xyz/address/", + "explorerTxLink": "https://explorer.mainnet.citrea.xyz/tx/", + "relatedAssetKey": null + }, + "eip155:4114/erc20:0x2a36f2b204b46fd82653cd06d00c7ff757c99ae4": { + "assetId": "eip155:4114/erc20:0x2a36f2b204b46fd82653cd06d00c7ff757c99ae4", + "chainId": "eip155:4114", + "name": "Juice Protocol", + "precision": 18, + "color": "#FFFFFF", + "icon": "https://assets.coingecko.com/coins/images/102172950/large/juice.png?1776783178", + "symbol": "JUICE", + "explorer": "https://explorer.mainnet.citrea.xyz", + "explorerAddressLink": "https://explorer.mainnet.citrea.xyz/address/", + "explorerTxLink": "https://explorer.mainnet.citrea.xyz/tx/", + "relatedAssetKey": null + }, + "eip155:4114/erc20:0x3100000000000000000000000000000000000006": { + "assetId": "eip155:4114/erc20:0x3100000000000000000000000000000000000006", + "chainId": "eip155:4114", + "name": "Wrapped Citrea Bitcoin", + "precision": 18, + "color": "#FFFFFF", + "icon": "https://assets.coingecko.com/coins/images/102172843/large/cBTC.png?1776227743", + "symbol": "WCBTC", + "explorer": "https://explorer.mainnet.citrea.xyz", + "explorerAddressLink": "https://explorer.mainnet.citrea.xyz/address/", + "explorerTxLink": "https://explorer.mainnet.citrea.xyz/tx/", + "relatedAssetKey": null + }, + "eip155:4114/erc20:0x384157027b1cdeac4e26e3709667bb28735379bb": { + "assetId": "eip155:4114/erc20:0x384157027b1cdeac4e26e3709667bb28735379bb", + "chainId": "eip155:4114", + "name": "Symbiosis BTC (Citrea)", + "precision": 8, + "color": "#FFFFFF", + "icon": "https://assets.coingecko.com/coins/images/102172893/large/syBTC.png?1776440292", + "symbol": "SYBTC", + "explorer": "https://explorer.mainnet.citrea.xyz", + "explorerAddressLink": "https://explorer.mainnet.citrea.xyz/address/", + "explorerTxLink": "https://explorer.mainnet.citrea.xyz/tx/", + "relatedAssetKey": null + }, + "eip155:4114/erc20:0x547afd93b9c47d552059feb556909e017f8a9b25": { + "assetId": "eip155:4114/erc20:0x547afd93b9c47d552059feb556909e017f8a9b25", + "chainId": "eip155:4114", + "name": "Citrea", + "precision": 18, + "color": "#FFFFFF", + "icon": "https://assets.coingecko.com/coins/images/102173169/large/CTR.png?1778226916", + "symbol": "CTR", + "explorer": "https://explorer.mainnet.citrea.xyz", + "explorerAddressLink": "https://explorer.mainnet.citrea.xyz/address/", + "explorerTxLink": "https://explorer.mainnet.citrea.xyz/tx/", + "relatedAssetKey": null + }, + "eip155:4114/erc20:0x8d82c4e3c936c7b5724a382a9c5a4e6eb7ab6d5d": { + "assetId": "eip155:4114/erc20:0x8d82c4e3c936c7b5724a382a9c5a4e6eb7ab6d5d", + "chainId": "eip155:4114", + "name": "Citrea USD", + "precision": 6, + "color": "#FFFFFF", + "icon": "https://assets.coingecko.com/coins/images/71615/large/ctUSD.png?1776133927", + "symbol": "CTUSD", + "explorer": "https://explorer.mainnet.citrea.xyz", + "explorerAddressLink": "https://explorer.mainnet.citrea.xyz/address/", + "explorerTxLink": "https://explorer.mainnet.citrea.xyz/tx/", + "relatedAssetKey": null + }, + "eip155:4114/erc20:0x9f3096bac87e7f03dc09b0b416eb0df837304dc4": { + "assetId": "eip155:4114/erc20:0x9f3096bac87e7f03dc09b0b416eb0df837304dc4", + "chainId": "eip155:4114", + "name": "Citrea Bridged USDT (Citrea)", + "precision": 6, + "color": "#FFFFFF", + "icon": "https://assets.coingecko.com/coins/images/102172831/large/usdt.png?1776134144", + "symbol": "USDT.E", + "explorer": "https://explorer.mainnet.citrea.xyz", + "explorerAddressLink": "https://explorer.mainnet.citrea.xyz/address/", + "explorerTxLink": "https://explorer.mainnet.citrea.xyz/tx/", + "relatedAssetKey": "eip155:1/erc20:0xdac17f958d2ee523a2206206994597c13d831ec7" + }, + "eip155:4114/erc20:0xac8c1aeb584765db16ac3e08d4736cfce198589b": { + "assetId": "eip155:4114/erc20:0xac8c1aeb584765db16ac3e08d4736cfce198589b", + "chainId": "eip155:4114", + "name": "Generic USD", + "precision": 18, + "color": "#FFFFFF", + "icon": "https://assets.coingecko.com/coins/images/71672/large/GUSD.png?1769242841", + "symbol": "GUSD", + "explorer": "https://explorer.mainnet.citrea.xyz", + "explorerAddressLink": "https://explorer.mainnet.citrea.xyz/address/", + "explorerTxLink": "https://explorer.mainnet.citrea.xyz/tx/", + "relatedAssetKey": null + }, + "eip155:4114/erc20:0xdf240dc08b0fdad1d93b74d5048871232f6bea3d": { + "assetId": "eip155:4114/erc20:0xdf240dc08b0fdad1d93b74d5048871232f6bea3d", + "chainId": "eip155:4114", + "name": "Citrea Bridged WBTC (Citrea)", + "precision": 8, + "color": "#FFFFFF", + "icon": "https://assets.coingecko.com/coins/images/102172832/large/wbtc.png?1776134474", + "symbol": "WBTC.E", + "explorer": "https://explorer.mainnet.citrea.xyz", + "explorerAddressLink": "https://explorer.mainnet.citrea.xyz/address/", + "explorerTxLink": "https://explorer.mainnet.citrea.xyz/tx/", + "relatedAssetKey": "eip155:1/erc20:0xdac17f958d2ee523a2206206994597c13d831ec7" + }, + "eip155:4114/erc20:0xe045e6c36cf77faa2cfb54466d71a3aef7bbe839": { + "assetId": "eip155:4114/erc20:0xe045e6c36cf77faa2cfb54466d71a3aef7bbe839", + "chainId": "eip155:4114", + "name": "Citrea Bridged USDC (Citrea)", + "precision": 6, + "color": "#FFFFFF", + "icon": "https://assets.coingecko.com/coins/images/102172830/large/usdc.png?1776133757", + "symbol": "USDC.E", + "explorer": "https://explorer.mainnet.citrea.xyz", + "explorerAddressLink": "https://explorer.mainnet.citrea.xyz/address/", + "explorerTxLink": "https://explorer.mainnet.citrea.xyz/tx/", + "relatedAssetKey": "eip155:1/erc20:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48" + }, + "eip155:4114/slip44:60": { + "assetId": "eip155:4114/slip44:60", + "chainId": "eip155:4114", + "name": "Citrea Bitcoin", + "networkName": "Citrea", + "symbol": "cBTC", + "precision": 18, + "color": "#F7931A", + "networkColor": "#F7931A", + "icon": "https://assets.coingecko.com/coins/images/102172844/large/cBTC.png", + "networkIcon": "https://assets.coingecko.com/asset_platforms/images/102132293/small/citrea.jpg", + "explorer": "https://explorer.mainnet.citrea.xyz", + "explorerAddressLink": "https://explorer.mainnet.citrea.xyz/address/", + "explorerTxLink": "https://explorer.mainnet.citrea.xyz/tx/", + "relatedAssetKey": "eip155:4114/slip44:60" } }, "ids": [ @@ -366473,6 +366619,17 @@ "eip155:1/erc20:0x750c3a0a0ce9984eeb8c5d146dff024b584e5e33", "eip155:324/erc20:0x3355df6d4c9c3035724fd0e3914de96a5a83aaf4", "eip155:324/erc20:0xbbeb516fb02a01611cbbe0453fe3c580d7281011", - "eip155:8453/erc20:0x3054e8f8fba3055a42e5f5228a2a4e2ab1326933" + "eip155:8453/erc20:0x3054e8f8fba3055a42e5f5228a2a4e2ab1326933", + "eip155:4114/erc20:0x1b70ae756b1089cc5948e4f8a2ad498df30e897d", + "eip155:4114/erc20:0x2a36f2b204b46fd82653cd06d00c7ff757c99ae4", + "eip155:4114/erc20:0x3100000000000000000000000000000000000006", + "eip155:4114/erc20:0x384157027b1cdeac4e26e3709667bb28735379bb", + "eip155:4114/erc20:0x547afd93b9c47d552059feb556909e017f8a9b25", + "eip155:4114/erc20:0x8d82c4e3c936c7b5724a382a9c5a4e6eb7ab6d5d", + "eip155:4114/erc20:0x9f3096bac87e7f03dc09b0b416eb0df837304dc4", + "eip155:4114/erc20:0xac8c1aeb584765db16ac3e08d4736cfce198589b", + "eip155:4114/erc20:0xdf240dc08b0fdad1d93b74d5048871232f6bea3d", + "eip155:4114/erc20:0xe045e6c36cf77faa2cfb54466d71a3aef7bbe839", + "eip155:4114/slip44:60" ] } \ No newline at end of file diff --git a/public/generated/generatedAssetData.json.br b/public/generated/generatedAssetData.json.br index 337a2bb3a9a42b56ebb6473371d3bf084a2604fe..e4496a396bef3b3ab8f26bdf8a4b2e537e8f3c4b 100644 GIT binary patch delta 1165746 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 m6av20wOZ1V Lz-Y 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