import { apiFetch } from './client'; // exportWalletKey는 비밀번호 오류 시 서버가 401을 반환하므로 // apiFetch의 401 자동 refresh/로그아웃을 우회하기 위해 BASE를 직접 참조 const BASE = import.meta.env.VITE_API_BASE_URL || ''; // --- 지갑 --- export async function getBalance() { return apiFetch('/api/chain/balance'); } export async function getWallet() { return apiFetch('/api/chain/wallet'); } /** * 개인키 내보내기 * apiFetch를 우회해 직접 fetch 사용 — 비밀번호 오류(401)를 로그아웃 없이 처리하기 위함 * @param {string} password * @returns {Promise<{privateKey: string}>} * @throws {Error} 비밀번호 오류 시 status 401 */ export async function exportWalletKey(password) { const token = localStorage.getItem('token'); const headers = { 'Content-Type': 'application/json' }; if (token) headers['Authorization'] = `Bearer ${token}`; const res = await fetch(BASE + '/api/chain/wallet/export', { method: 'POST', headers, credentials: 'include', body: JSON.stringify({ password }), }); if (!res.ok) { const err = new Error(res.status === 401 ? '비밀번호가 올바르지 않습니다' : '키 내보내기에 실패했습니다'); err.status = res.status; try { const body = await res.json(); err.message = body.message || err.message; } catch { /* ignore parse failure */ } throw err; } return res.json(); } // --- 자산 --- export async function getAssets() { return apiFetch('/api/chain/assets'); } export async function getAsset(id) { return apiFetch(`/api/chain/asset/${id}`); } // --- 인벤토리 --- export async function getInventory() { return apiFetch('/api/chain/inventory'); } // --- 마켓 --- export async function getMarketListings() { return apiFetch('/api/chain/market'); } export async function getListing(id) { return apiFetch(`/api/chain/market/${id}`); } /** * Idempotency-Key 헤더를 붙인 POST 요청 * 중복 제출(네트워크 재시도 등)로 인한 이중 처리를 서버에서 방지 * @param {string} path * @param {object} body */ function idempotentPost(path, body) { return apiFetch(path, { method: 'POST', headers: { 'Idempotency-Key': crypto.randomUUID() }, body: JSON.stringify(body), }); } export async function listOnMarket(assetId, price) { return idempotentPost('/api/chain/market/list', { assetId, price }); } export async function buyFromMarket(listingId) { return idempotentPost('/api/chain/market/buy', { listingId }); } export async function cancelListing(listingId) { return idempotentPost('/api/chain/market/cancel', { listingId }); }