import { getCsrfToken } from '@shared/api/csrf' import { tokenStore, refreshAccessToken } from '@shared/api/tokenStore' const WALLET_API_URL = 'https://app.cryptowallet.elcsa.ru' export type Chain = 'ETH' | 'BSC' | 'BTC' | 'TRX' | 'SOL' export interface FormattedAmount { raw: string formatted: string decimals: number usdPrice: number usdValue: number } export interface WalletBalanceData { chain: Chain address: string native: FormattedAmount tokens: Record } export interface PriceEntry { usd: number } export interface SendWalletPayload { to: string amount: string token?: string feeTier?: 'slow' | 'normal' | 'fast' } export interface SendWalletResponse { data: { txid: string; chain: Chain } } export interface WalletAddress { chain: Chain address: string derivationPath: string } export interface PortfolioToken { symbol: string amountFormatted: string usd: number } export interface PortfolioNative { amount: string amountFormatted: string usd: number } export interface PortfolioChain { address: string stale: boolean native: PortfolioNative tokens: PortfolioToken[] totalUsd: number } export interface PortfolioData { totalUsd: number asOfMs: number chains: Record } export const CHAINS: Chain[] = ['ETH', 'BSC', 'BTC', 'TRX', 'SOL'] async function walletGet(path: string, allowRetry: boolean = true): Promise { const csrf = await getCsrfToken() const bearer = tokenStore.get() const res = await fetch(`${WALLET_API_URL}${path}`, { credentials: 'include', headers: { 'X-CSRF-Token': csrf, ...(bearer ? { Authorization: `Bearer ${bearer}` } : {}), }, }) if (res.status === 401 && allowRetry) { try { await refreshAccessToken() return walletGet(path, false) } catch { tokenStore.clear() throw new Error('Unauthorized') } } const data = await res.json() if (!res.ok) throw data return data as T } async function walletPost(path: string, body: unknown, allowRetry: boolean = true): Promise { const csrf = await getCsrfToken() const bearer = tokenStore.get() const res = await fetch(`${WALLET_API_URL}${path}`, { method: 'POST', credentials: 'include', headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': csrf, ...(bearer ? { Authorization: `Bearer ${bearer}` } : {}), }, body: JSON.stringify(body), }) if (res.status === 401 && allowRetry) { try { await refreshAccessToken() return walletPost(path, body, false) } catch { tokenStore.clear() throw new Error('Unauthorized') } } const data = await res.json() if (!res.ok) throw data return data as T } export async function getWalletAddresses(): Promise { const res = await walletGet<{ success: boolean; data: WalletAddress[] }>('/api/wallets') return res.data } export async function getWalletBalance(chain: Chain): Promise { const res = await walletGet<{ success: boolean; data: WalletBalanceData }>(`/api/wallets/${chain}/balance`) return res.data } export async function getPrices(symbols: string[]): Promise> { const res = await walletGet<{ success: boolean; data: Record }>( `/api/prices?symbols=${symbols.join(',')}` ) return res.data } export async function sendWallet(chain: Chain, payload: SendWalletPayload): Promise { return walletPost(`/api/wallets/${chain}/send`, payload) } export async function getPortfolio(): Promise { const res = await walletGet<{ success: boolean; data: PortfolioData }>('/api/wallets/portfolio') return res.data } export interface TokenInfo { chain: string symbol: string name: string contract: string | null } export interface RelayQuotePayload { user: string recipient: string originChainId: number destinationChainId: number originCurrency: string destinationCurrency: string amount: string tradeType: 'EXACT_INPUT' } export interface RelayQuoteResponse { details: { currencyOut: { amountFormatted: string amountUsd: string } } fees: { gas: { amountUsd: string } } } export async function getTokensList(): Promise { const res = await walletGet<{ success: boolean; data: TokenInfo[] }>('/api/tokens') return res.data } export async function getRelayQuote(payload: RelayQuotePayload): Promise { return walletPost('/api/relay/quote', payload) } export async function createWallet(): Promise { await walletPost('/api/wallets/create', {}) } export async function revealMnemonic(): Promise { const res = await walletPost<{ success: boolean; data: { mnemonic: string } }>('/api/wallets/mnemonic/reveal', { confirm: 'I_UNDERSTAND_SEED_IS_SECRET' }) return res.data.mnemonic }