Files
koin_ping_0.2.0/frontend/src/api/addresses.jsx
KS Jannette 37ff644aa7 audit: fix issues #1-#9 (mock data, notifier interface, retry/timeout, digest scheduling, real status, RPC retry, dedup, address edit UI)
- #1: remove mock alert events that poisoned production responses
- #2: add Notifier interface + Send implementations for all channels
- #3/#4: notification goroutines now carry a 30s context timeout and retry up to 3x with exponential backoff
- #5: schedule email digest in poller via DIGEST_INTERVAL_HOURS (default 24h)
- #6: SystemStatus queries real checkpoint data; returns starting/active/idle with latestBlock and lag
- #7: Ethereum RPC client retries on network errors, 429, and 5xx with 1s/2s backoff
- #8: alert_events dedup index + ON CONFLICT DO NOTHING to prevent duplicate events on poller restart
- #9: PATCH /v1/addresses/{id} for label editing; frontend address list gains inline edit and remove buttons
2026-03-01 07:49:08 -05:00

153 lines
4.9 KiB
JavaScript

// API client for address management
import { getAuthHeaders, getAuthHeadersSimple } from "./authHeaders";
import { API_BASE } from "./config";
/**
* Create a new blockchain address to monitor
* @param {Object} data - Address data
* @param {string} data.address - Blockchain address (0x...)
* @param {string} [data.label] - Optional label for the address
* @returns {Promise<Object>} Created address with id and metadata
*/
export async function createAddress(data) {
try {
const headers = await getAuthHeaders();
const response = await fetch(`${API_BASE}/addresses`, {
method: "POST",
headers: headers,
body: JSON.stringify(data),
});
if (!response.ok) {
// Try to parse error response, but handle if it's not JSON
let errorMessage = "Failed to create address";
try {
const error = await response.json();
errorMessage = error.message || errorMessage;
} catch {
// If JSON parse fails, use status text
errorMessage = `Server error: ${response.status} ${response.statusText}`;
}
throw new Error(errorMessage);
}
return response.json();
} catch (error) {
// Handle network errors
if (error.message.includes("fetch")) {
throw new Error(
"Cannot connect to server. Is the backend running?",
);
}
throw error;
}
}
/**
* Get all tracked addresses
* @returns {Promise<Array>} List of all addresses
*/
export async function getAddresses() {
try {
const headers = await getAuthHeadersSimple();
const response = await fetch(`${API_BASE}/addresses`, {
headers: headers,
});
if (!response.ok) {
// Try to parse error response, but handle if it's not JSON
let errorMessage = "Failed to fetch addresses";
try {
const error = await response.json();
errorMessage = error.message || errorMessage;
} catch {
// If JSON parse fails, use status text
errorMessage = `Server error: ${response.status} ${response.statusText}`;
}
throw new Error(errorMessage);
}
return response.json();
} catch (error) {
// Handle network errors or JSON parse errors
if (error.message.includes("fetch")) {
throw new Error(
"Cannot connect to server. Is the backend running?",
);
}
throw error;
}
}
/**
* Update an address (e.g. change its label)
* @param {number} addressId - Address ID to update
* @param {Object} data - Fields to update (e.g. { label: "New Label" })
* @returns {Promise<Object>} Updated address
*/
export async function updateAddress(addressId, data) {
try {
const headers = await getAuthHeaders();
const response = await fetch(`${API_BASE}/addresses/${addressId}`, {
method: "PATCH",
headers: headers,
body: JSON.stringify(data),
});
if (!response.ok) {
let errorMessage = "Failed to update address";
try {
const error = await response.json();
errorMessage = error.message || errorMessage;
} catch {
errorMessage = `Server error: ${response.status} ${response.statusText}`;
}
throw new Error(errorMessage);
}
return response.json();
} catch (error) {
if (error.message.includes("fetch")) {
throw new Error("Cannot connect to server. Is the backend running?");
}
throw error;
}
}
/**
* Delete a tracked address
* @param {number} addressId - Address ID to delete
* @returns {Promise<void>}
*/
export async function deleteAddress(addressId) {
try {
const headers = await getAuthHeadersSimple();
const response = await fetch(`${API_BASE}/addresses/${addressId}`, {
method: "DELETE",
headers: headers,
});
if (!response.ok && response.status !== 204) {
// Try to parse error response, but handle if it's not JSON
let errorMessage = "Failed to delete address";
try {
const error = await response.json();
errorMessage = error.message || errorMessage;
} catch {
// If JSON parse fails, use status text
errorMessage = `Server error: ${response.status} ${response.statusText}`;
}
throw new Error(errorMessage);
}
} catch (error) {
// Handle network errors
if (error.message.includes("fetch")) {
throw new Error(
"Cannot connect to server. Is the backend running?",
);
}
throw error;
}
}