|
const TESTNET_BASE_URL = process.env.NEXT_PUBLIC_TESTNET_URL || "http://localhost:8000" |
|
|
|
export interface TestnetUser { |
|
id: number |
|
wallet_address: string |
|
role: string |
|
name: string |
|
location: string |
|
verified: boolean |
|
flb_balance: number |
|
created_at: string |
|
} |
|
|
|
export interface TestnetValidator { |
|
id: number |
|
wallet_address: string |
|
name: string |
|
stake_amount: number |
|
active: boolean |
|
last_heartbeat: string |
|
blocks_validated: number |
|
uptime_percentage: number |
|
} |
|
|
|
export interface NetworkStats { |
|
total_users: number |
|
total_validators: number |
|
total_transactions: number |
|
total_flb_supply: number |
|
active_validators: number |
|
network_uptime: number |
|
} |
|
|
|
export interface HealthAction { |
|
user_id: number |
|
action_type: string |
|
description: string |
|
impact_score: number |
|
} |
|
|
|
export class TestnetClient { |
|
private baseUrl: string |
|
|
|
constructor(baseUrl: string = TESTNET_BASE_URL) { |
|
this.baseUrl = baseUrl |
|
} |
|
|
|
async ping() { |
|
const response = await fetch(`${this.baseUrl}/ping`) |
|
if (!response.ok) { |
|
throw new Error(`HTTP error! status: ${response.status}`) |
|
} |
|
return response.json() |
|
} |
|
|
|
async getManifest() { |
|
const response = await fetch(`${this.baseUrl}/.well-known/manifest.json`) |
|
if (!response.ok) { |
|
throw new Error(`HTTP error! status: ${response.status}`) |
|
} |
|
return response.json() |
|
} |
|
|
|
async getUsers(): Promise<TestnetUser[]> { |
|
const response = await fetch(`${this.baseUrl}/users`) |
|
if (!response.ok) { |
|
throw new Error(`HTTP error! status: ${response.status}`) |
|
} |
|
return response.json() |
|
} |
|
|
|
async createUser(userData: { |
|
wallet_address: string |
|
role: string |
|
name: string |
|
location: string |
|
}): Promise<TestnetUser> { |
|
const response = await fetch(`${this.baseUrl}/users`, { |
|
method: "POST", |
|
headers: { |
|
"Content-Type": "application/json", |
|
}, |
|
body: JSON.stringify(userData), |
|
}) |
|
if (!response.ok) { |
|
throw new Error(`HTTP error! status: ${response.status}`) |
|
} |
|
return response.json() |
|
} |
|
|
|
async getUser(walletAddress: string): Promise<TestnetUser> { |
|
const response = await fetch(`${this.baseUrl}/users/${walletAddress}`) |
|
if (!response.ok) { |
|
throw new Error(`HTTP error! status: ${response.status}`) |
|
} |
|
return response.json() |
|
} |
|
|
|
async getValidators(): Promise<TestnetValidator[]> { |
|
const response = await fetch(`${this.baseUrl}/validators`) |
|
if (!response.ok) { |
|
throw new Error(`HTTP error! status: ${response.status}`) |
|
} |
|
return response.json() |
|
} |
|
|
|
async createValidator(validatorData: { |
|
wallet_address: string |
|
name: string |
|
stake_amount: number |
|
}): Promise<TestnetValidator> { |
|
const response = await fetch(`${this.baseUrl}/validators`, { |
|
method: "POST", |
|
headers: { |
|
"Content-Type": "application/json", |
|
}, |
|
body: JSON.stringify(validatorData), |
|
}) |
|
if (!response.ok) { |
|
throw new Error(`HTTP error! status: ${response.status}`) |
|
} |
|
return response.json() |
|
} |
|
|
|
async sendValidatorHeartbeat(walletAddress: string) { |
|
const response = await fetch(`${this.baseUrl}/validators/${walletAddress}/heartbeat`, { |
|
method: "POST", |
|
}) |
|
if (!response.ok) { |
|
throw new Error(`HTTP error! status: ${response.status}`) |
|
} |
|
return response.json() |
|
} |
|
|
|
async getNetworkStats(): Promise<NetworkStats> { |
|
const response = await fetch(`${this.baseUrl}/stats`) |
|
if (!response.ok) { |
|
throw new Error(`HTTP error! status: ${response.status}`) |
|
} |
|
return response.json() |
|
} |
|
|
|
async getFLBPrice() { |
|
const response = await fetch(`${this.baseUrl}/oracle/price`) |
|
if (!response.ok) { |
|
throw new Error(`HTTP error! status: ${response.status}`) |
|
} |
|
return response.json() |
|
} |
|
|
|
async getConsensusStatus() { |
|
const response = await fetch(`${this.baseUrl}/consensus/status`) |
|
if (!response.ok) { |
|
throw new Error(`HTTP error! status: ${response.status}`) |
|
} |
|
return response.json() |
|
} |
|
|
|
async recordHealthAction(actionData: HealthAction) { |
|
const response = await fetch(`${this.baseUrl}/health-actions`, { |
|
method: "POST", |
|
headers: { |
|
"Content-Type": "application/json", |
|
}, |
|
body: JSON.stringify(actionData), |
|
}) |
|
if (!response.ok) { |
|
throw new Error(`HTTP error! status: ${response.status}`) |
|
} |
|
return response.json() |
|
} |
|
|
|
|
|
connectWebSocket(onMessage: (data: any) => void) { |
|
const wsUrl = this.baseUrl.replace("http", "ws") + "/ws" |
|
const ws = new WebSocket(wsUrl) |
|
|
|
ws.onmessage = (event) => { |
|
try { |
|
const data = JSON.parse(event.data) |
|
onMessage(data) |
|
} catch (error) { |
|
console.error("Failed to parse WebSocket message:", error) |
|
} |
|
} |
|
|
|
ws.onerror = (error) => { |
|
console.error("WebSocket error:", error) |
|
} |
|
|
|
ws.onclose = () => { |
|
console.log("WebSocket connection closed") |
|
} |
|
|
|
return ws |
|
} |
|
} |
|
|
|
|
|
export const testnetClient = new TestnetClient() |
|
|