Skip to content

Commit

Permalink
Automatically generate RPC docs, bump version number for release
Browse files Browse the repository at this point in the history
  • Loading branch information
Ash-L2L committed Jun 10, 2024
1 parent 26fd6c0 commit 2379616
Show file tree
Hide file tree
Showing 12 changed files with 300 additions and 46 deletions.
142 changes: 103 additions & 39 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ authors = [
"Nikita Chashchinskii <[email protected]>"
]
edition = "2021"
version = "0.8.12"
version = "0.8.13"

[workspace.dependencies.bip300301]
git = "https://github.com/Ash-L2L/bip300301.git"
Expand Down
1 change: 1 addition & 0 deletions app/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ tokio-util = { version = "0.7.10", features = ["rt"] }
tracing = "0.1.40"
tracing-appender = "0.2.3"
tracing-subscriber = "0.3.18"
utoipa = "4.2.3"

[[bin]]
name = "thunder_app"
Expand Down
5 changes: 5 additions & 0 deletions app/rpc_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,11 @@ impl RpcServer for RpcServerImpl {
}).await.unwrap()
}

async fn openapi_schema(&self) -> RpcResult<utoipa::openapi::OpenApi> {
let res = <thunder_app_rpc_api::RpcDoc as utoipa::OpenApi>::openapi();
Ok(res)
}

async fn remove_from_mempool(&self, txid: Txid) -> RpcResult<()> {
self.app
.node
Expand Down
1 change: 1 addition & 0 deletions cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ serde_json = "1.0.113"
thunder = { path = "../lib" }
thunder_app_rpc_api = { path = "../rpc-api" }
tokio = "1.29.1"
utoipa = "4.2.3"

[lib]
name = "thunder_app_cli_lib"
Expand Down
8 changes: 8 additions & 0 deletions cli/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ pub enum Command {
#[arg(long)]
fee_sats: Option<u64>,
},
/// Show OpenAPI schema
#[command(name = "openapi-schema")]
OpenApiSchema,
/// Remove a tx from the mempool
RemoveFromMempool { txid: Txid },
/// Set the wallet seed from a mnemonic seed phrase
Expand Down Expand Up @@ -120,6 +123,11 @@ impl Cli {
let () = rpc_client.mine(fee_sats).await?;
String::default()
}
Command::OpenApiSchema => {
let openapi =
<thunder_app_rpc_api::RpcDoc as utoipa::OpenApi>::openapi();
openapi.to_pretty_json()?
}
Command::RemoveFromMempool { txid } => {
let () = rpc_client.remove_from_mempool(txid).await?;
String::default()
Expand Down
1 change: 1 addition & 0 deletions lib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ tokio = { version = "1.29.1", features = ["sync"] }
tokio-stream = { version = "0.1.15", features = ["sync"] }
tokio-util = { version = "0.7.10", features = ["rt"] }
tracing = "0.1.40"
utoipa = "4.2.3"

[lib]
name = "thunder"
Expand Down
18 changes: 18 additions & 0 deletions lib/types/address.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,21 @@ impl Serialize for Address {
}
}
}

impl utoipa::PartialSchema for Address {
fn schema() -> utoipa::openapi::RefOr<utoipa::openapi::schema::Schema> {
let obj = utoipa::openapi::Object::with_type(
utoipa::openapi::SchemaType::String,
);
utoipa::openapi::RefOr::T(utoipa::openapi::Schema::Object(obj))
}
}

impl utoipa::ToSchema<'static> for Address {
fn schema() -> (
&'static str,
utoipa::openapi::RefOr<utoipa::openapi::schema::Schema>,
) {
("Address", <Address as utoipa::PartialSchema>::schema())
}
}
36 changes: 36 additions & 0 deletions lib/types/hashes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,24 @@ impl std::fmt::Debug for MerkleRoot {
}
}

impl utoipa::PartialSchema for MerkleRoot {
fn schema() -> utoipa::openapi::RefOr<utoipa::openapi::schema::Schema> {
let obj = utoipa::openapi::Object::with_type(
utoipa::openapi::SchemaType::String,
);
utoipa::openapi::RefOr::T(utoipa::openapi::Schema::Object(obj))
}
}

impl utoipa::ToSchema<'static> for MerkleRoot {
fn schema() -> (
&'static str,
utoipa::openapi::RefOr<utoipa::openapi::schema::Schema>,
) {
("MerkleRoot", <Txid as utoipa::PartialSchema>::schema())
}
}

#[derive(
BorshSerialize,
Clone,
Expand Down Expand Up @@ -163,6 +181,24 @@ impl FromStr for Txid {
}
}

impl utoipa::PartialSchema for Txid {
fn schema() -> utoipa::openapi::RefOr<utoipa::openapi::schema::Schema> {
let obj = utoipa::openapi::Object::with_type(
utoipa::openapi::SchemaType::String,
);
utoipa::openapi::RefOr::T(utoipa::openapi::Schema::Object(obj))
}
}

impl utoipa::ToSchema<'static> for Txid {
fn schema() -> (
&'static str,
utoipa::openapi::RefOr<utoipa::openapi::schema::Schema>,
) {
("Txid", <Txid as utoipa::PartialSchema>::schema())
}
}

pub fn hash<T>(data: &T) -> Hash
where
T: BorshSerialize,
Expand Down
35 changes: 32 additions & 3 deletions lib/types/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use rustreexo::accumulator::{
node_hash::NodeHash, pollard::Pollard, proof::Proof,
};
use serde::{Deserialize, Serialize};
use utoipa::ToSchema;

use super::{hash, Address, Hash, MerkleRoot, Txid};
use crate::authorization::Authorization;
Expand Down Expand Up @@ -34,6 +35,7 @@ where
PartialEq,
PartialOrd,
Serialize,
ToSchema,
)]
pub enum OutPoint {
// Created by transactions.
Expand Down Expand Up @@ -98,8 +100,16 @@ where
}

#[derive(
BorshSerialize, Clone, Debug, Deserialize, Eq, PartialEq, Serialize,
BorshSerialize,
Clone,
Debug,
Deserialize,
Eq,
PartialEq,
Serialize,
ToSchema,
)]
#[schema(as = OutputContent)]
pub enum Content {
Value(u64),
Withdrawal {
Expand Down Expand Up @@ -129,11 +139,23 @@ impl GetValue for Content {
}
}

fn output_content_schema_ref() -> utoipa::openapi::Ref {
utoipa::openapi::Ref::new("OutputContent")
}

#[derive(
BorshSerialize, Clone, Debug, Deserialize, Eq, PartialEq, Serialize,
BorshSerialize,
Clone,
Debug,
Deserialize,
Eq,
PartialEq,
Serialize,
ToSchema,
)]
pub struct Output {
pub address: Address,
#[schema(schema_with = output_content_schema_ref)]
pub content: Content,
}

Expand All @@ -145,7 +167,14 @@ impl GetValue for Output {
}

#[derive(
BorshSerialize, Clone, Debug, Deserialize, Eq, PartialEq, Serialize,
BorshSerialize,
Clone,
Debug,
Deserialize,
Eq,
PartialEq,
Serialize,
ToSchema,
)]
pub struct PointedOutput {
pub outpoint: OutPoint,
Expand Down
6 changes: 6 additions & 0 deletions rpc-api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ version.workspace = true
bip300301.workspace = true
jsonrpsee = { version = "0.20.0", features = ["macros"] }
thunder = { path = "../lib" }
serde_json = "1.0.113"
utoipa = "4.2.3"

[dependencies.l2l-openapi]
git = "https://github.com/Ash-L2L/l2l-openapi"
rev = "6e440bb2715ec0d495050e9dbbda3f1590a07385"

[lib]
name = "thunder_app_rpc_api"
Expand Down
91 changes: 88 additions & 3 deletions rpc-api/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,90 @@ use std::net::SocketAddr;

use bip300301::bitcoin;
use jsonrpsee::{core::RpcResult, proc_macros::rpc};
use thunder::types::{Address, PointedOutput, Txid};
use l2l_openapi::open_api;
use thunder::types::{
Address, MerkleRoot, OutPoint, Output, OutputContent, PointedOutput, Txid,
};
use utoipa::{
openapi::{RefOr, Schema, SchemaType},
PartialSchema, ToSchema,
};

struct BitcoinAddrSchema;

impl PartialSchema for BitcoinAddrSchema {
fn schema() -> RefOr<Schema> {
let obj = utoipa::openapi::Object::with_type(SchemaType::String);
RefOr::T(Schema::Object(obj))
}
}

impl ToSchema<'static> for BitcoinAddrSchema {
fn schema() -> (&'static str, RefOr<Schema>) {
("bitcoin.Address", <Self as PartialSchema>::schema())
}
}

struct BitcoinAmountSchema;

impl PartialSchema for BitcoinAmountSchema {
fn schema() -> RefOr<Schema> {
let obj = utoipa::openapi::Object::with_type(SchemaType::String);
RefOr::T(Schema::Object(obj))
}
}

struct BitcoinOutPointSchema;

impl PartialSchema for BitcoinOutPointSchema {
fn schema() -> RefOr<Schema> {
let obj = utoipa::openapi::Object::new();
RefOr::T(Schema::Object(obj))
}
}

impl ToSchema<'static> for BitcoinOutPointSchema {
fn schema() -> (&'static str, RefOr<Schema>) {
("bitcoin.OutPoint", <Self as PartialSchema>::schema())
}
}

struct OpenApiSchema;

impl PartialSchema for OpenApiSchema {
fn schema() -> RefOr<Schema> {
let obj = utoipa::openapi::Object::new();
RefOr::T(Schema::Object(obj))
}
}

struct SocketAddrSchema;

impl PartialSchema for SocketAddrSchema {
fn schema() -> RefOr<Schema> {
let obj = utoipa::openapi::Object::with_type(SchemaType::String);
RefOr::T(Schema::Object(obj))
}
}

#[open_api(ref_schemas[
Address, BitcoinAddrSchema, BitcoinOutPointSchema, MerkleRoot, OutPoint, Output,
OutputContent, Txid
])]
#[rpc(client, server)]
pub trait Rpc {
/// Get balance in sats
#[method(name = "balance")]
async fn balance(&self) -> RpcResult<u64>;

/// Connect to a peer
#[open_api_method(output_schema(ToSchema))]
#[method(name = "connect_peer")]
async fn connect_peer(&self, addr: SocketAddr) -> RpcResult<()>;
async fn connect_peer(
&self,
#[open_api_method_arg(schema(PartialSchema = "SocketAddrSchema"))]
addr: SocketAddr,
) -> RpcResult<()>;

/// Format a deposit address
#[method(name = "format_deposit_address")]
Expand Down Expand Up @@ -48,18 +121,27 @@ pub trait Rpc {
async fn list_utxos(&self) -> RpcResult<Vec<PointedOutput>>;

/// Attempt to mine a sidechain block
#[open_api_method(output_schema(ToSchema))]
#[method(name = "mine")]
async fn mine(&self, fee: Option<u64>) -> RpcResult<()>;

/// Get OpenRPC schema
#[open_api_method(output_schema(PartialSchema = "OpenApiSchema"))]
#[method(name = "openapi_schema")]
async fn openapi_schema(&self) -> RpcResult<utoipa::openapi::OpenApi>;

/// Remove a tx from the mempool
#[open_api_method(output_schema(ToSchema))]
#[method(name = "remove_from_mempool")]
async fn remove_from_mempool(&self, txid: Txid) -> RpcResult<()>;

/// Set the wallet seed from a mnemonic seed phrase
#[open_api_method(output_schema(ToSchema))]
#[method(name = "set_seed_from_mnemonic")]
async fn set_seed_from_mnemonic(&self, mnemonic: String) -> RpcResult<()>;

/// Get total sidechain wealth
#[open_api_method(output_schema(PartialSchema = "BitcoinAmountSchema"))]
#[method(name = "sidechain_wealth")]
async fn sidechain_wealth(&self) -> RpcResult<bitcoin::Amount>;

Expand All @@ -80,7 +162,10 @@ pub trait Rpc {
#[method(name = "withdraw")]
async fn withdraw(
&self,
mainchain_address: bitcoin::Address<bitcoin::address::NetworkUnchecked>,
#[open_api_method_arg(schema(PartialSchema = "BitcoinAddrSchema"))]
mainchain_address: bitcoin::Address<
bitcoin::address::NetworkUnchecked,
>,
amount_sats: u64,
fee_sats: u64,
mainchain_fee_sats: u64,
Expand Down

0 comments on commit 2379616

Please sign in to comment.