Skip to content

Commit

Permalink
RPC setup
Browse files Browse the repository at this point in the history
  • Loading branch information
RomeroYang committed Jul 29, 2024
1 parent b69a407 commit 34b9c16
Show file tree
Hide file tree
Showing 5 changed files with 444 additions and 0 deletions.
222 changes: 222 additions & 0 deletions RPC/Package.resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
{
"originHash" : "fcf25dc9b4931a1d81f53cd6efcf7914dd698adfbfd85aebcc2589b96787a187",
"pins" : [
{
"identity" : "async-http-client",
"kind" : "remoteSourceControl",
"location" : "https://github.com/swift-server/async-http-client.git",
"state" : {
"revision" : "0ae99db85b2b9d1e79b362bd31fd1ffe492f7c47",
"version" : "1.21.2"
}
},
{
"identity" : "async-kit",
"kind" : "remoteSourceControl",
"location" : "https://github.com/vapor/async-kit.git",
"state" : {
"revision" : "7ece208cd401687641c88367a00e3ea2b04311f1",
"version" : "1.19.0"
}
},
{
"identity" : "blake2.swift",
"kind" : "remoteSourceControl",
"location" : "https://github.com/tesseract-one/Blake2.swift.git",
"state" : {
"revision" : "29c55c8fe42d6661e5a32cc5bbbad1fff64fd01e",
"version" : "0.2.0"
}
},
{
"identity" : "console-kit",
"kind" : "remoteSourceControl",
"location" : "https://github.com/vapor/console-kit.git",
"state" : {
"revision" : "9f7932f22ab6f64aafadc14491e694179b7d0f6f",
"version" : "4.14.3"
}
},
{
"identity" : "multipart-kit",
"kind" : "remoteSourceControl",
"location" : "https://github.com/vapor/multipart-kit.git",
"state" : {
"revision" : "a31236f24bfd2ea2f520a74575881f6731d7ae68",
"version" : "4.7.0"
}
},
{
"identity" : "routing-kit",
"kind" : "remoteSourceControl",
"location" : "https://github.com/vapor/routing-kit.git",
"state" : {
"revision" : "8c9a227476555c55837e569be71944e02a056b72",
"version" : "4.9.1"
}
},
{
"identity" : "scalecodec.swift",
"kind" : "remoteSourceControl",
"location" : "https://github.com/AcalaNetwork/ScaleCodec.swift.git",
"state" : {
"branch" : "main",
"revision" : "dac3e7161de34c60c82794d031de0231b5a5746e"
}
},
{
"identity" : "swift-algorithms",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-algorithms.git",
"state" : {
"revision" : "f6919dfc309e7f1b56224378b11e28bab5bccc42",
"version" : "1.2.0"
}
},
{
"identity" : "swift-atomics",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-atomics.git",
"state" : {
"revision" : "cd142fd2f64be2100422d658e7411e39489da985",
"version" : "1.2.0"
}
},
{
"identity" : "swift-collections",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-collections.git",
"state" : {
"revision" : "3d2dc41a01f9e49d84f0a3925fb858bed64f702d",
"version" : "1.1.2"
}
},
{
"identity" : "swift-crypto",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-crypto.git",
"state" : {
"revision" : "46072478ca365fe48370993833cb22de9b41567f",
"version" : "3.5.2"
}
},
{
"identity" : "swift-http-types",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-http-types",
"state" : {
"revision" : "ae67c8178eb46944fd85e4dc6dd970e1f3ed6ccd",
"version" : "1.3.0"
}
},
{
"identity" : "swift-log",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-log.git",
"state" : {
"revision" : "9cb486020ebf03bfa5b5df985387a14a98744537",
"version" : "1.6.1"
}
},
{
"identity" : "swift-metrics",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-metrics.git",
"state" : {
"revision" : "e0165b53d49b413dd987526b641e05e246782685",
"version" : "2.5.0"
}
},
{
"identity" : "swift-nio",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-nio.git",
"state" : {
"revision" : "fc79798d5a150d61361a27ce0c51169b889e23de",
"version" : "2.68.0"
}
},
{
"identity" : "swift-nio-extras",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-nio-extras.git",
"state" : {
"revision" : "05c36b57453d23ea63785d58a7dbc7b70ba1745e",
"version" : "1.23.0"
}
},
{
"identity" : "swift-nio-http2",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-nio-http2.git",
"state" : {
"revision" : "a0224f3d20438635dd59c9fcc593520d80d131d0",
"version" : "1.33.0"
}
},
{
"identity" : "swift-nio-ssl",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-nio-ssl.git",
"state" : {
"revision" : "2b09805797f21c380f7dc9bedaab3157c5508efb",
"version" : "2.27.0"
}
},
{
"identity" : "swift-nio-transport-services",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-nio-transport-services.git",
"state" : {
"revision" : "38ac8221dd20674682148d6451367f89c2652980",
"version" : "1.21.0"
}
},
{
"identity" : "swift-numerics",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-numerics.git",
"state" : {
"revision" : "0a5bc04095a675662cf24757cc0640aa2204253b",
"version" : "1.0.2"
}
},
{
"identity" : "swift-system",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-system.git",
"state" : {
"revision" : "6a9e38e7bd22a3b8ba80bddf395623cf68f57807",
"version" : "1.3.1"
}
},
{
"identity" : "tuples.swift",
"kind" : "remoteSourceControl",
"location" : "https://github.com/tesseract-one/Tuples.swift.git",
"state" : {
"revision" : "4d2cf7c64443cdf4df833d0bedd767bf9dbc49d9",
"version" : "0.1.3"
}
},
{
"identity" : "vapor",
"kind" : "remoteSourceControl",
"location" : "https://github.com/vapor/vapor.git",
"state" : {
"revision" : "a823735db57b46100b0c61cdfc5a08525b1e7cad",
"version" : "4.102.1"
}
},
{
"identity" : "websocket-kit",
"kind" : "remoteSourceControl",
"location" : "https://github.com/vapor/websocket-kit.git",
"state" : {
"revision" : "4232d34efa49f633ba61afde365d3896fc7f8740",
"version" : "2.15.0"
}
}
],
"version" : 3
}
37 changes: 37 additions & 0 deletions RPC/Package.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// swift-tools-version: 6.0
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
name: "RPC",
platforms: [
.macOS(.v14),
],
products: [
// Products define the executables and libraries a package produces, making them visible to other packages.
.library(
name: "RPC",
targets: ["RPC"]
),
],
dependencies: [
.package(path: "../Blockchain"),
.package(url: "https://github.com/vapor/vapor.git", from: "4.102.1"),
],
targets: [
// Targets are the basic building blocks of a package, defining a module or a test suite.
// Targets can depend on other targets in this package and products from dependencies.
.target(
name: "RPC",
dependencies: [
"Blockchain",
.product(name: "Vapor", package: "vapor"),
]
),
.testTarget(
name: "RPCTests",
dependencies: ["RPC"]
),
]
)
17 changes: 17 additions & 0 deletions RPC/Sources/RPC/RPC.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// The Swift Programming Language
// https://docs.swift.org/swift-book
import Vapor

public func startServer() throws {
let env = try Environment.detect()
let app = Application(env)
defer { app.shutdown() }
try configure(app)
try app.run()
}

public func configure(_ app: Application) throws {
// Register routes
let rpcController = RPCController()
try app.register(collection: rpcController)
}
76 changes: 76 additions & 0 deletions RPC/Sources/RPC/RPCController.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import Blockchain
import Vapor

final class RPCController: RouteCollection {
func boot(routes: RoutesBuilder) throws {
// HTTP JSON-RPC route
routes.post("rpc", use: handleRPCRequest)

// WebSocket JSON-RPC route
routes.webSocket("ws", onUpgrade: handleWebSocket)
}

func handleRPCRequest(_ req: Request) -> EventLoopFuture<Response> {
do {
let rpcRequest = try req.content.decode(RPCRequest<AnyContent>.self)
// Handle the JSON-RPC request
let result = try RPCController.handleMethod(rpcRequest.method, params: rpcRequest.params)
let rpcResponse = RPCResponse(jsonrpc: "2.0", result: AnyContent(result ?? ""), error: nil, id: rpcRequest.id)
return try req.eventLoop.makeSucceededFuture(Response(status: .ok, body: .init(data: JSONEncoder().encode(rpcResponse))))
} catch {
let rpcError = RPCError(code: -32600, message: "Invalid Request")
let rpcResponse = RPCResponse<RPCError>(jsonrpc: "2.0", result: nil, error: rpcError, id: nil)
return req.eventLoop.makeSucceededFuture(Response(status: .badRequest, body: .init(data: try! JSONEncoder().encode(rpcResponse))))

Check failure on line 23 in RPC/Sources/RPC/RPCController.swift

View workflow job for this annotation

GitHub Actions / Swift Lint

Force Try Violation: Force tries should be avoided (force_try)

Check failure on line 23 in RPC/Sources/RPC/RPCController.swift

View workflow job for this annotation

GitHub Actions / Swift Lint

Line Length Violation: Line should be 140 characters or less; currently it has 142 characters (line_length)
}
}

func handleWebSocket(req _: Request, ws: WebSocket) {
ws.onText { ws, text in
Task {
await RPCController.processWebSocketRequest(ws, text: text)
}
}
}

private static func processWebSocketRequest(_ ws: WebSocket, text: String) async {
do {
let rpcRequest = try JSONDecoder().decode(RPCRequest<AnyContent>.self, from: Data(text.utf8))
let result = try handleMethod(rpcRequest.method, params: rpcRequest.params?.value)
let rpcResponse = RPCResponse(jsonrpc: "2.0", result: AnyContent(result ?? ""), error: nil, id: rpcRequest.id)
let responseData = try JSONEncoder().encode(rpcResponse)
try await ws.send(String(data: responseData, encoding: .utf8)!)

Check failure on line 41 in RPC/Sources/RPC/RPCController.swift

View workflow job for this annotation

GitHub Actions / Swift Lint

Non-Optional String <-> Data Conversion Violation: Prefer using UTF-8 encoded strings when converting between `String` and `Data` (non_optional_string_data_conversion)
} catch {
let rpcError = RPCError(code: -32600, message: "Invalid Request")
let rpcResponse = RPCResponse<RPCError>(jsonrpc: "2.0", result: nil, error: rpcError, id: nil)

do {
let responseData = try JSONEncoder().encode(rpcResponse)
try await ws.send(String(data: responseData, encoding: .utf8)!)

Check failure on line 48 in RPC/Sources/RPC/RPCController.swift

View workflow job for this annotation

GitHub Actions / Swift Lint

Non-Optional String <-> Data Conversion Violation: Prefer using UTF-8 encoded strings when converting between `String` and `Data` (non_optional_string_data_conversion)
} catch {
// Handle the error appropriately, e.g., log it
print("Failed to send WebSocket error response: \(error)")
}
}
}

static func handleChainGetBlock(params _: BlockParams?) -> CodableBlock? {
// Fetch the block by hash or number
nil
}

static func handleChainGetHeader(params _: HeaderParams?) -> CodableHeader? {
// Fetch the header by hash or number
nil
}

static func handleMethod(_ method: String, params: Any?) throws -> Any? {
switch method {
case "chain_getBlock":
return handleChainGetBlock(params: params as? BlockParams)
case "chain_getHeader":
return handleChainGetHeader(params: params as? HeaderParams)
default:
throw RPCError(code: -32601, message: "Method not found")
}
}
}
Loading

0 comments on commit 34b9c16

Please sign in to comment.