Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Encoding Server, Go Request builder package, client example #262

Merged
merged 12 commits into from
Jun 28, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ default-members = [
resolver = "2"

[workspace.package]
version = "4.2.2"
version = "4.2.3"
edition = "2021"

[workspace.dependencies]
Expand Down
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,21 @@ It integrates the full functionality of [Gorc](https://github.com/PeggyJV/gravit

Steward is built with the [Abscissa](https://github.com/iqlusioninc/abscissa) app micro-framework.

## Installation

You can build steward from source or download one of the provided binaries.

To build from source, you will need to have Rust and Git installed.

```bash
git clone https://github.com/peggyjv/steward
cd steward
git checkout v4.2.3
cargo install --path .
```

[Download the latest release here](https://github.com/PeggyJV/steward/releases/tag/v4.2.3)

## Steward use cases

### 1. Gravity Bridge Operator
Expand Down
Binary file modified crates/steward-proto/src/gen/descriptor.bin
Binary file not shown.
204 changes: 204 additions & 0 deletions crates/steward-proto/src/gen/steward.v4.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5246,6 +5246,37 @@ pub struct ScheduleResponse {
#[prost(uint64, tag = "2")]
pub chain_id: u64,
}
#[derive(serde::Deserialize, serde::Serialize, Clone, PartialEq, ::prost::Message)]
pub struct EncodeRequest {
#[prost(string, tag = "1")]
pub cellar_id: ::prost::alloc::string::String,
/// The data from which the desired contract function will be encoded
#[prost(oneof = "encode_request::CallData", tags = "2, 3, 4, 5, 6")]
pub call_data: ::core::option::Option<encode_request::CallData>,
}
/// Nested message and enum types in `EncodeRequest`.
pub mod encode_request {
/// The data from which the desired contract function will be encoded
#[derive(serde::Deserialize, serde::Serialize, Clone, PartialEq, ::prost::Oneof)]
pub enum CallData {
#[prost(message, tag = "2")]
AaveV2Stablecoin(super::AaveV2Stablecoin),
#[prost(message, tag = "3")]
CellarV1(super::CellarV1),
#[prost(message, tag = "4")]
CellarV2(super::CellarV2),
#[prost(message, tag = "5")]
CellarV22(super::CellarV22),
#[prost(message, tag = "6")]
CellarV25(super::CellarV25),
}
}
#[derive(serde::Deserialize, serde::Serialize, Clone, PartialEq, ::prost::Message)]
pub struct EncodeResponse {
/// The encoded contract call
#[prost(string, tag = "1")]
pub encoded_call: ::prost::alloc::string::String,
}
///
/// Represents a request for Steward's current status
#[derive(serde::Deserialize, serde::Serialize, Clone, PartialEq, ::prost::Message)]
Expand Down Expand Up @@ -5347,6 +5378,70 @@ pub mod contract_call_service_client {
}
}
#[doc = r" Generated client implementations."]
pub mod encoding_service_client {
#![allow(unused_variables, dead_code, missing_docs)]
use tonic::codegen::*;
#[doc = ""]
#[doc = " Service for testing contract call encoding. Simply returns the encoded call data in the response."]
pub struct EncodingServiceClient<T> {
inner: tonic::client::Grpc<T>,
}
impl EncodingServiceClient<tonic::transport::Channel> {
#[doc = r" Attempt to create a new client by connecting to a given endpoint."]
pub async fn connect<D>(dst: D) -> Result<Self, tonic::transport::Error>
where
D: std::convert::TryInto<tonic::transport::Endpoint>,
D::Error: Into<StdError>,
{
let conn = tonic::transport::Endpoint::new(dst)?.connect().await?;
Ok(Self::new(conn))
}
}
impl<T> EncodingServiceClient<T>
where
T: tonic::client::GrpcService<tonic::body::BoxBody>,
T::ResponseBody: Body + HttpBody + Send + 'static,
T::Error: Into<StdError>,
<T::ResponseBody as HttpBody>::Error: Into<StdError> + Send,
{
pub fn new(inner: T) -> Self {
let inner = tonic::client::Grpc::new(inner);
Self { inner }
}
pub fn with_interceptor(inner: T, interceptor: impl Into<tonic::Interceptor>) -> Self {
let inner = tonic::client::Grpc::with_interceptor(inner, interceptor);
Self { inner }
}
#[doc = " Handles contract call encoding"]
pub async fn encode(
&mut self,
request: impl tonic::IntoRequest<super::EncodeRequest>,
) -> Result<tonic::Response<super::EncodeResponse>, tonic::Status> {
self.inner.ready().await.map_err(|e| {
tonic::Status::new(
tonic::Code::Unknown,
format!("Service was not ready: {}", e.into()),
)
})?;
let codec = tonic::codec::ProstCodec::default();
let path = http::uri::PathAndQuery::from_static("/steward.v4.EncodingService/Encode");
self.inner.unary(request.into_request(), path, codec).await
}
}
impl<T: Clone> Clone for EncodingServiceClient<T> {
fn clone(&self) -> Self {
Self {
inner: self.inner.clone(),
}
}
}
impl<T> std::fmt::Debug for EncodingServiceClient<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "EncodingServiceClient {{ ... }}")
}
}
}
#[doc = r" Generated client implementations."]
pub mod simulate_contract_call_service_client {
#![allow(unused_variables, dead_code, missing_docs)]
use tonic::codegen::*;
Expand Down Expand Up @@ -5585,6 +5680,115 @@ pub mod contract_call_service_server {
}
}
#[doc = r" Generated server implementations."]
pub mod encoding_service_server {
#![allow(unused_variables, dead_code, missing_docs)]
use tonic::codegen::*;
#[doc = "Generated trait containing gRPC methods that should be implemented for use with EncodingServiceServer."]
#[async_trait]
pub trait EncodingService: Send + Sync + 'static {
#[doc = " Handles contract call encoding"]
async fn encode(
&self,
request: tonic::Request<super::EncodeRequest>,
) -> Result<tonic::Response<super::EncodeResponse>, tonic::Status>;
}
#[doc = ""]
#[doc = " Service for testing contract call encoding. Simply returns the encoded call data in the response."]
#[derive(Debug)]
pub struct EncodingServiceServer<T: EncodingService> {
inner: _Inner<T>,
}
struct _Inner<T>(Arc<T>, Option<tonic::Interceptor>);
impl<T: EncodingService> EncodingServiceServer<T> {
pub fn new(inner: T) -> Self {
let inner = Arc::new(inner);
let inner = _Inner(inner, None);
Self { inner }
}
pub fn with_interceptor(inner: T, interceptor: impl Into<tonic::Interceptor>) -> Self {
let inner = Arc::new(inner);
let inner = _Inner(inner, Some(interceptor.into()));
Self { inner }
}
}
impl<T, B> Service<http::Request<B>> for EncodingServiceServer<T>
where
T: EncodingService,
B: HttpBody + Send + Sync + 'static,
B::Error: Into<StdError> + Send + 'static,
{
type Response = http::Response<tonic::body::BoxBody>;
type Error = Never;
type Future = BoxFuture<Self::Response, Self::Error>;
fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
Poll::Ready(Ok(()))
}
fn call(&mut self, req: http::Request<B>) -> Self::Future {
let inner = self.inner.clone();
match req.uri().path() {
"/steward.v4.EncodingService/Encode" => {
#[allow(non_camel_case_types)]
struct EncodeSvc<T: EncodingService>(pub Arc<T>);
impl<T: EncodingService> tonic::server::UnaryService<super::EncodeRequest> for EncodeSvc<T> {
type Response = super::EncodeResponse;
type Future = BoxFuture<tonic::Response<Self::Response>, tonic::Status>;
fn call(
&mut self,
request: tonic::Request<super::EncodeRequest>,
) -> Self::Future {
let inner = self.0.clone();
let fut = async move { (*inner).encode(request).await };
Box::pin(fut)
}
}
let inner = self.inner.clone();
let fut = async move {
let interceptor = inner.1.clone();
let inner = inner.0;
let method = EncodeSvc(inner);
let codec = tonic::codec::ProstCodec::default();
let mut grpc = if let Some(interceptor) = interceptor {
tonic::server::Grpc::with_interceptor(codec, interceptor)
} else {
tonic::server::Grpc::new(codec)
};
let res = grpc.unary(method, req).await;
Ok(res)
};
Box::pin(fut)
}
_ => Box::pin(async move {
Ok(http::Response::builder()
.status(200)
.header("grpc-status", "12")
.header("content-type", "application/grpc")
.body(tonic::body::BoxBody::empty())
.unwrap())
}),
}
}
}
impl<T: EncodingService> Clone for EncodingServiceServer<T> {
fn clone(&self) -> Self {
let inner = self.inner.clone();
Self { inner }
}
}
impl<T: EncodingService> Clone for _Inner<T> {
fn clone(&self) -> Self {
Self(self.0.clone(), self.1.clone())
}
}
impl<T: std::fmt::Debug> std::fmt::Debug for _Inner<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{:?}", self.0)
}
}
impl<T: EncodingService> tonic::transport::NamedService for EncodingServiceServer<T> {
const NAME: &'static str = "steward.v4.EncodingService";
}
}
#[doc = r" Generated server implementations."]
pub mod simulate_contract_call_service_server {
#![allow(unused_variables, dead_code, missing_docs)]
use tonic::codegen::*;
Expand Down
1 change: 1 addition & 0 deletions docs/00-TableOfContents.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@
- [Create or import a Cosmos key](./03-TheOrchestrator.md#create-or-import-cosmos-key)
- [Configuration](./03-TheOrchestrator.md#configuration)
4. [Pubsub for Validators](./05-PubsubForValidators.md)
5. [Steward for Strategists](./06-StewardForStrategists.md)
60 changes: 60 additions & 0 deletions docs/06-StewardForStrategists.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# Steward for Strategists

## Installation

If you plan to use steward for development and testing you will need to install it first. You can follow the steps outlined [in the README](../README.md).

## Encode Mode

Steward can be started in encode mode, which runs a gRPC server that accepts call data params and returns the final hex-encoded contract call data. This is intended for testing parameter construction with the protos without needing to worry about authentication or network connectivity.

Strategists can run steward locally and send requests without needing TLS authentication. To Start the server simply run:

```bash
steward encode start
```

By default the server will run on port 5734.

Encode mode is only available in steward 4.2.3 and later.

### Sending Requests

The request type for the encoding server is a subset of the fields of a regular `ScheduleRequest` used in production requiring only a cellar ID and call data parameters:

```protobuf
# steward/proto/steward/v4/steward.proto

message EncodeRequest {
string cellar_id = 1;
// The data from which the desired contract function will be encoded
oneof call_data {
AaveV2Stablecoin aave_v2_stablecoin = 2;
CellarV1 cellar_v1 = 3;
CellarV2 cellar_v2 = 4;
CellarV2_2 cellar_v2_2 = 5;
CellarV2_5 cellar_v2_5 = 6;
}
}

message EncodeResponse {
// The encoded contract call
string encoded_call = 1;
}
```

The server can be called with any gRPC client, such as `grpcurl`:

```bash
grpcurl \
--plaintext \
-d '{"cellar_id": "0x0000000000000000000000000000000000000000", "cellar_v2_5": {"function_call": {"lift_shutdown": {}}}}' \
localhost:5734 \
steward.v4.EncodingService/Encode

# Output:
# {
# "encodedCall": "5e2c576e"
# }
#
```
6 changes: 6 additions & 0 deletions go.work
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
go 1.22.1

use (
./client_example
./steward_proto_go/steward_proto
)
Loading
Loading