feat: add chain API wrapper with idempotency-key
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
72
src/api/chain.js
Normal file
72
src/api/chain.js
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
import { apiFetch } from './client';
|
||||||
|
|
||||||
|
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');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 키 내보내기는 비밀번호 오류 시 서버가 401을 반환하므로,
|
||||||
|
// apiFetch의 401 자동 refresh/로그아웃을 우회하기 위해 직접 fetch한다.
|
||||||
|
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 {}
|
||||||
|
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');
|
||||||
|
}
|
||||||
|
|
||||||
|
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', { asset_id: assetId, price });
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function buyFromMarket(listingId) {
|
||||||
|
return idempotentPost('/api/chain/market/buy', { listing_id: listingId });
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function cancelListing(listingId) {
|
||||||
|
return idempotentPost('/api/chain/market/cancel', { listing_id: listingId });
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user