[hermes] add utoipa for API docs (#990)
* [hermes] add utoipa for docs * fix build * format
This commit is contained in:
parent
9e4242a20e
commit
61e29ac166
|
@ -1173,6 +1173,15 @@ dependencies = [
|
||||||
"subtle",
|
"subtle",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dirs"
|
||||||
|
version = "4.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059"
|
||||||
|
dependencies = [
|
||||||
|
"dirs-sys",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dirs-next"
|
name = "dirs-next"
|
||||||
version = "2.0.0"
|
version = "2.0.0"
|
||||||
|
@ -1183,6 +1192,17 @@ dependencies = [
|
||||||
"dirs-sys-next",
|
"dirs-sys-next",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dirs-sys"
|
||||||
|
version = "0.3.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"redox_users",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dirs-sys-next"
|
name = "dirs-sys-next"
|
||||||
version = "0.1.2"
|
version = "0.1.2"
|
||||||
|
@ -1781,6 +1801,8 @@ dependencies = [
|
||||||
"strum",
|
"strum",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tower-http",
|
"tower-http",
|
||||||
|
"utoipa",
|
||||||
|
"utoipa-swagger-ui",
|
||||||
"wormhole-sdk",
|
"wormhole-sdk",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -2070,6 +2092,7 @@ checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"equivalent",
|
"equivalent",
|
||||||
"hashbrown 0.14.0",
|
"hashbrown 0.14.0",
|
||||||
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2969,6 +2992,16 @@ version = "0.3.17"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
|
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mime_guess"
|
||||||
|
version = "2.0.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef"
|
||||||
|
dependencies = [
|
||||||
|
"mime",
|
||||||
|
"unicase",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "minimal-lexical"
|
name = "minimal-lexical"
|
||||||
version = "0.2.1"
|
version = "0.2.1"
|
||||||
|
@ -4252,6 +4285,41 @@ dependencies = [
|
||||||
"thiserror",
|
"thiserror",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rust-embed"
|
||||||
|
version = "6.8.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a36224c3276f8c4ebc8c20f158eca7ca4359c8db89991c4925132aaaf6702661"
|
||||||
|
dependencies = [
|
||||||
|
"rust-embed-impl",
|
||||||
|
"rust-embed-utils",
|
||||||
|
"walkdir",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rust-embed-impl"
|
||||||
|
version = "6.8.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "49b94b81e5b2c284684141a2fb9e2a31be90638caf040bf9afbc5a0416afe1ac"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2 1.0.66",
|
||||||
|
"quote 1.0.31",
|
||||||
|
"rust-embed-utils",
|
||||||
|
"shellexpand",
|
||||||
|
"syn 2.0.26",
|
||||||
|
"walkdir",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rust-embed-utils"
|
||||||
|
version = "7.8.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9d38ff6bf570dc3bb7100fce9f7b60c33fa71d80e88da3f2580df4ff2bdded74"
|
||||||
|
dependencies = [
|
||||||
|
"sha2 0.10.7",
|
||||||
|
"walkdir",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc-demangle"
|
name = "rustc-demangle"
|
||||||
version = "0.1.23"
|
version = "0.1.23"
|
||||||
|
@ -4414,6 +4482,15 @@ dependencies = [
|
||||||
"cipher 0.4.4",
|
"cipher 0.4.4",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "same-file"
|
||||||
|
version = "1.0.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
|
||||||
|
dependencies = [
|
||||||
|
"winapi-util",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "schannel"
|
name = "schannel"
|
||||||
version = "0.1.22"
|
version = "0.1.22"
|
||||||
|
@ -4727,6 +4804,15 @@ version = "1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde"
|
checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "shellexpand"
|
||||||
|
version = "2.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7ccc8076840c4da029af4f87e4e8daeb0fca6b87bbb02e10cb60b791450e11e4"
|
||||||
|
dependencies = [
|
||||||
|
"dirs",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "signal-hook-registry"
|
name = "signal-hook-registry"
|
||||||
version = "1.4.1"
|
version = "1.4.1"
|
||||||
|
@ -6057,6 +6143,15 @@ dependencies = [
|
||||||
"static_assertions",
|
"static_assertions",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicase"
|
||||||
|
version = "2.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6"
|
||||||
|
dependencies = [
|
||||||
|
"version_check",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-bidi"
|
name = "unicode-bidi"
|
||||||
version = "0.3.13"
|
version = "0.3.13"
|
||||||
|
@ -6157,6 +6252,47 @@ version = "0.7.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
|
checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "utoipa"
|
||||||
|
version = "3.4.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8c624186f22e625eb8faa777cb33d34cd595aa16d1742aa1d8b6cf35d3e4dda9"
|
||||||
|
dependencies = [
|
||||||
|
"indexmap 2.0.0",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"utoipa-gen",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "utoipa-gen"
|
||||||
|
version = "3.4.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b9ce5f21ca77e010f5283fa791c6ab892c68b3668a1bdc6b7ac6cf978f5d5b30"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro-error",
|
||||||
|
"proc-macro2 1.0.66",
|
||||||
|
"quote 1.0.31",
|
||||||
|
"regex",
|
||||||
|
"syn 2.0.26",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "utoipa-swagger-ui"
|
||||||
|
version = "3.1.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4602d7100d3cfd8a086f30494e68532402ab662fa366c9d201d677e33cee138d"
|
||||||
|
dependencies = [
|
||||||
|
"axum",
|
||||||
|
"mime_guess",
|
||||||
|
"regex",
|
||||||
|
"rust-embed",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"utoipa",
|
||||||
|
"zip",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "value-bag"
|
name = "value-bag"
|
||||||
version = "1.4.1"
|
version = "1.4.1"
|
||||||
|
@ -6193,6 +6329,16 @@ version = "1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca"
|
checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "walkdir"
|
||||||
|
version = "2.3.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698"
|
||||||
|
dependencies = [
|
||||||
|
"same-file",
|
||||||
|
"winapi-util",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "want"
|
name = "want"
|
||||||
version = "0.3.1"
|
version = "0.3.1"
|
||||||
|
@ -6669,6 +6815,18 @@ dependencies = [
|
||||||
"syn 2.0.26",
|
"syn 2.0.26",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zip"
|
||||||
|
version = "0.6.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261"
|
||||||
|
dependencies = [
|
||||||
|
"byteorder",
|
||||||
|
"crc32fast",
|
||||||
|
"crossbeam-utils",
|
||||||
|
"flate2",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zstd"
|
name = "zstd"
|
||||||
version = "0.11.2+zstd.1.5.2"
|
version = "0.11.2+zstd.1.5.2"
|
||||||
|
|
|
@ -59,6 +59,8 @@ structopt = { version = "0.3.26" }
|
||||||
strum = { version = "0.24.1", features = ["derive"] }
|
strum = { version = "0.24.1", features = ["derive"] }
|
||||||
tokio = { version = "1.26.0", features = ["full"] }
|
tokio = { version = "1.26.0", features = ["full"] }
|
||||||
tower-http = { version = "0.4.0", features = ["cors"] }
|
tower-http = { version = "0.4.0", features = ["cors"] }
|
||||||
|
utoipa = { version = "3.4.0", features = ["axum_extras"] }
|
||||||
|
utoipa-swagger-ui = { version = "3.1.4", features = ["axum"] }
|
||||||
wormhole-sdk = { git = "https://github.com/wormhole-foundation/wormhole", tag = "v2.17.1" }
|
wormhole-sdk = { git = "https://github.com/wormhole-foundation/wormhole", tag = "v2.17.1" }
|
||||||
|
|
||||||
[patch.crates-io]
|
[patch.crates-io]
|
||||||
|
|
|
@ -75,6 +75,8 @@ fn main() {
|
||||||
.output()
|
.output()
|
||||||
.expect("failed to generate protobuf definitions");
|
.expect("failed to generate protobuf definitions");
|
||||||
|
|
||||||
|
let rust_target_arch = std::env::var("CARGO_CFG_TARGET_ARCH").unwrap();
|
||||||
|
|
||||||
// Build the Go library.
|
// Build the Go library.
|
||||||
let mut cmd = Command::new("go");
|
let mut cmd = Command::new("go");
|
||||||
cmd.arg("build")
|
cmd.arg("build")
|
||||||
|
@ -84,11 +86,28 @@ fn main() {
|
||||||
.arg("src/network/p2p.go")
|
.arg("src/network/p2p.go")
|
||||||
.arg("src/network/p2p.pb.go");
|
.arg("src/network/p2p.pb.go");
|
||||||
|
|
||||||
|
// Cross-compile the Go binary based on the Rust target architecture
|
||||||
|
match &*rust_target_arch {
|
||||||
|
"x86_64" => {
|
||||||
|
// CGO_ENABLED required for building amd64 on mac os
|
||||||
|
cmd.env("GOARCH", "amd64").env("CGO_ENABLED", "1");
|
||||||
|
}
|
||||||
|
"aarch64" => {
|
||||||
|
cmd.env("GOARCH", "arm64");
|
||||||
|
}
|
||||||
|
// Add other target architectures as needed.
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Tell Rust to link our Go library at compile time.
|
// Tell Rust to link our Go library at compile time.
|
||||||
println!("cargo:rustc-link-search=native={out_var}");
|
println!("cargo:rustc-link-search=native={out_var}");
|
||||||
println!("cargo:rustc-link-lib=static=pythnet");
|
println!("cargo:rustc-link-lib=static=pythnet");
|
||||||
println!("cargo:rustc-link-lib=resolv");
|
println!("cargo:rustc-link-lib=resolv");
|
||||||
|
|
||||||
let status = cmd.status().unwrap();
|
let go_build_output = cmd.output().expect("Failed to execute Go build command");
|
||||||
assert!(status.success());
|
if !go_build_output.status.success() {
|
||||||
|
let error_message = String::from_utf8_lossy(&go_build_output.stderr);
|
||||||
|
panic!("Go build failed:\n{}", error_message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,16 @@ use {
|
||||||
sync::mpsc::Receiver,
|
sync::mpsc::Receiver,
|
||||||
},
|
},
|
||||||
tower_http::cors::CorsLayer,
|
tower_http::cors::CorsLayer,
|
||||||
|
utoipa::{
|
||||||
|
openapi::security::{
|
||||||
|
ApiKey,
|
||||||
|
ApiKeyValue,
|
||||||
|
SecurityScheme,
|
||||||
|
},
|
||||||
|
Modify,
|
||||||
|
OpenApi,
|
||||||
|
},
|
||||||
|
utoipa_swagger_ui::SwaggerUi,
|
||||||
};
|
};
|
||||||
|
|
||||||
mod rest;
|
mod rest;
|
||||||
|
@ -38,12 +48,27 @@ impl State {
|
||||||
/// Currently this is based on Axum due to the simplicity and strong ecosystem support for the
|
/// Currently this is based on Axum due to the simplicity and strong ecosystem support for the
|
||||||
/// packages they are based on (tokio & hyper).
|
/// packages they are based on (tokio & hyper).
|
||||||
pub async fn run(store: Arc<Store>, mut update_rx: Receiver<()>, rpc_addr: String) -> Result<()> {
|
pub async fn run(store: Arc<Store>, mut update_rx: Receiver<()>, rpc_addr: String) -> Result<()> {
|
||||||
|
#[derive(OpenApi)]
|
||||||
|
#[openapi(
|
||||||
|
paths(
|
||||||
|
rest::latest_price_feeds,
|
||||||
|
),
|
||||||
|
components(
|
||||||
|
schemas(types::RpcPriceFeedMetadata, types::RpcPriceFeed)
|
||||||
|
),
|
||||||
|
tags(
|
||||||
|
(name = "hermes", description = "Pyth Real-Time Pricing API")
|
||||||
|
)
|
||||||
|
)]
|
||||||
|
struct ApiDoc;
|
||||||
|
|
||||||
let state = State::new(store);
|
let state = State::new(store);
|
||||||
|
|
||||||
// Initialize Axum Router. Note the type here is a `Router<State>` due to the use of the
|
// Initialize Axum Router. Note the type here is a `Router<State>` due to the use of the
|
||||||
// `with_state` method which replaces `Body` with `State` in the type signature.
|
// `with_state` method which replaces `Body` with `State` in the type signature.
|
||||||
let app = Router::new();
|
let app = Router::new();
|
||||||
let app = app
|
let app = app
|
||||||
|
.merge(SwaggerUi::new("/docs").url("/docs/openapi.json", ApiDoc::openapi()))
|
||||||
.route("/", get(rest::index))
|
.route("/", get(rest::index))
|
||||||
.route("/live", get(rest::live))
|
.route("/live", get(rest::live))
|
||||||
.route("/ready", get(rest::ready))
|
.route("/ready", get(rest::ready))
|
||||||
|
|
|
@ -31,6 +31,7 @@ use {
|
||||||
pyth_sdk::PriceIdentifier,
|
pyth_sdk::PriceIdentifier,
|
||||||
serde_qs::axum::QsQuery,
|
serde_qs::axum::QsQuery,
|
||||||
std::collections::HashSet,
|
std::collections::HashSet,
|
||||||
|
utoipa::IntoParams,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub enum RestError {
|
pub enum RestError {
|
||||||
|
@ -95,15 +96,32 @@ pub async fn latest_vaas(
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, serde::Deserialize)]
|
#[derive(Debug, serde::Deserialize, IntoParams)]
|
||||||
pub struct LatestPriceFeedsQueryParams {
|
pub struct LatestPriceFeedsQueryParams {
|
||||||
|
#[param(value_type = String)]
|
||||||
ids: Vec<PriceIdInput>,
|
ids: Vec<PriceIdInput>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
|
#[param(value_type = Option<bool>, required = false, nullable = true)]
|
||||||
verbose: bool,
|
verbose: bool,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
|
#[param(value_type = Option<bool>, required = false, nullable = true)]
|
||||||
binary: bool,
|
binary: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the latest prices by price feed ids.
|
||||||
|
///
|
||||||
|
/// Get the latest price updates for a provided collection of price feed ids.
|
||||||
|
///
|
||||||
|
#[utoipa::path(
|
||||||
|
get,
|
||||||
|
path = "/api/latest_price_feeds",
|
||||||
|
responses(
|
||||||
|
(status = 200, description = "Price feeds retrieved successfully", body = [Vec<RpcPriceFeed>])
|
||||||
|
),
|
||||||
|
params(
|
||||||
|
LatestPriceFeedsQueryParams
|
||||||
|
)
|
||||||
|
)]
|
||||||
pub async fn latest_price_feeds(
|
pub async fn latest_price_feeds(
|
||||||
State(state): State<super::State>,
|
State(state): State<super::State>,
|
||||||
QsQuery(params): QsQuery<LatestPriceFeedsQueryParams>,
|
QsQuery(params): QsQuery<LatestPriceFeedsQueryParams>,
|
||||||
|
|
|
@ -19,6 +19,14 @@ use {
|
||||||
Price,
|
Price,
|
||||||
PriceIdentifier,
|
PriceIdentifier,
|
||||||
},
|
},
|
||||||
|
utoipa::{
|
||||||
|
openapi::{
|
||||||
|
RefOr,
|
||||||
|
Schema,
|
||||||
|
},
|
||||||
|
IntoParams,
|
||||||
|
ToSchema,
|
||||||
|
},
|
||||||
wormhole_sdk::Chain,
|
wormhole_sdk::Chain,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -40,14 +48,16 @@ impl From<PriceIdInput> for PriceIdentifier {
|
||||||
|
|
||||||
type Base64String = String;
|
type Base64String = String;
|
||||||
|
|
||||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)]
|
||||||
pub struct RpcPriceFeedMetadata {
|
pub struct RpcPriceFeedMetadata {
|
||||||
|
#[schema(value_type = u64)]
|
||||||
pub slot: Slot,
|
pub slot: Slot,
|
||||||
pub emitter_chain: u16,
|
pub emitter_chain: u16,
|
||||||
|
#[schema(value_type = i64)]
|
||||||
pub price_service_receive_time: UnixTimestamp,
|
pub price_service_receive_time: UnixTimestamp,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)]
|
||||||
pub struct RpcPriceFeed {
|
pub struct RpcPriceFeed {
|
||||||
pub id: PriceIdentifier,
|
pub id: PriceIdentifier,
|
||||||
pub price: Price,
|
pub price: Price,
|
||||||
|
@ -56,6 +66,7 @@ pub struct RpcPriceFeed {
|
||||||
pub metadata: Option<RpcPriceFeedMetadata>,
|
pub metadata: Option<RpcPriceFeedMetadata>,
|
||||||
/// Vaa binary represented in base64.
|
/// Vaa binary represented in base64.
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
#[schema(value_type = Option<String>)]
|
||||||
pub vaa: Option<Base64String>,
|
pub vaa: Option<Base64String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue