// // SDLApi.swift // sdlan // // Created by 安礼成 on 2024/6/5. // import Foundation struct JSONRPCResponse: Decodable { let result: T? let error: JSONRPCError? } struct JSONRPCError: Error, Decodable { let code: Int let message: String let data: String? } struct SDLAPI { enum Mode { case debug case prod } static let mode: Mode = .debug static var baseUrl: String { switch mode { case .debug: return "http://127.0.0.1:18082/test" case .prod: return "https://punchnet.s5s8.com/api" } } struct Upgrade: Decodable { let upgrade_type: Int let upgrade_prompt: String let upgrade_address: String } struct NetworkProfile: Decodable { struct NetworkItem: Decodable { let name: String let code: String } let network: [NetworkItem] } static func checkVersion(clientId: String, version: Int, channel: String) async throws -> JSONRPCResponse { let params: [String:Any] = [ "client_id": clientId, "version": version, "channel": channel ] let postData = try! JSONSerialization.data(withJSONObject: params) var request = URLRequest(url: URL(string: baseUrl + "/upgrade")!) request.httpMethod = "POST" request.addValue("application/json", forHTTPHeaderField: "Content-Type") request.httpBody = postData let (data, _) = try await URLSession.shared.data(for: request) return try JSONDecoder().decode(JSONRPCResponse.self, from: data) } static func getUserNetworks(clientId: String) async throws -> JSONRPCResponse { let params: [String:Any] = [ "client_id": clientId ] let postData = try! JSONSerialization.data(withJSONObject: params) var request = URLRequest(url: URL(string: baseUrl + "/get_user_network")!) request.httpMethod = "POST" request.addValue("application/json", forHTTPHeaderField: "Content-Type") request.httpBody = postData let (data, _) = try await URLSession.shared.data(for: request) return try JSONDecoder().decode(JSONRPCResponse.self, from: data) } static func loginWithAccountAndPassword(clientId: String, username: String, password: String, as: T.Type) async throws -> T { let params: [String:Any] = [ "client_id": clientId, "username": username, "password": password ] return try await doPost(path: "/login_with_account", params: params, as: T.self) } private static func doPost(path: String, params: [String: Any], as: T.Type) async throws -> T { let postData = try! JSONSerialization.data(withJSONObject: params) var request = URLRequest(url: URL(string: baseUrl + path)!) request.httpMethod = "POST" request.addValue("application/json", forHTTPHeaderField: "Content-Type") request.httpBody = postData let (data, _) = try await URLSession.shared.data(for: request) let rpcResponse = try JSONDecoder().decode(JSONRPCResponse.self, from: data) if let result = rpcResponse.result { return result } else if let error = rpcResponse.error { throw error } else { throw DecodingError.dataCorrupted( .init( codingPath: [], debugDescription: "Invalid JSON-RPC response: \(String(data: data, encoding: .utf8) ?? "")" ) ) } } }