File size: 5,097 Bytes
78d0e31
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
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()
  }

  // WebSocket connection for real-time updates
  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 a singleton instance
export const testnetClient = new TestnetClient()