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

gateway request refactor #1784

Merged
merged 2 commits into from
Oct 1, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
76 changes: 76 additions & 0 deletions sdk/core/src/gateway.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
mod gateway_account;
mod gateway_account_esdt_roles;
mod gateway_account_esdt_tokens;
mod gateway_account_storage;
mod gateway_block;
mod gateway_network_config;
mod gateway_network_economics;
mod gateway_network_status;
mod gateway_tx_cost;
mod gateway_tx_info;
mod gateway_tx_process_status;
mod gateway_tx_send;
mod gateway_tx_send_multi;
mod gateway_tx_status;
mod gateway_tx_vmquery;

pub use gateway_account::GetAccountRequest;
pub use gateway_account_esdt_roles::GetAccountEsdtRolesRequest;
pub use gateway_account_esdt_tokens::GetAccountEsdtTokensRequest;
pub use gateway_account_storage::GetAccountStorageRequest;
pub use gateway_block::GetHyperBlockRequest;
pub use gateway_network_config::NetworkConfigRequest;
pub use gateway_network_economics::NetworkEconimicsRequest;
pub use gateway_network_status::NetworkStatusRequest;
pub use gateway_tx_cost::GetTxCost;
pub use gateway_tx_info::GetTxInfo;
pub use gateway_tx_process_status::GetTxProcessStatus;
pub use gateway_tx_send::SendTxRequest;
pub use gateway_tx_send_multi::SendMultiTxRequest;
pub use gateway_tx_status::GetTxStatus;
pub use gateway_tx_vmquery::VMQueryRequest;

pub const MAINNET_GATEWAY: &str = "https://gateway.multiversx.com";
pub const TESTNET_GATEWAY: &str = "https://testnet-gateway.multiversx.com";
pub const DEVNET_GATEWAY: &str = "https://devnet-gateway.multiversx.com";

// MetachainShardId will be used to identify a shard ID as metachain
pub const METACHAIN_SHARD_ID: u32 = 0xFFFFFFFF;

const ACCOUNT_ENDPOINT: &str = "address/";
const KEYS_ENDPOINT: &str = "/keys/";
const NETWORK_CONFIG_ENDPOINT: &str = "network/config";
const NETWORK_ECONOMICS_ENDPOINT: &str = "network/economics";
const GET_NETWORK_STATUS_ENDPOINT: &str = "network/status";
const GET_HYPER_BLOCK_BY_NONCE_ENDPOINT: &str = "hyperblock/by-nonce";
const GET_HYPER_BLOCK_BY_HASH_ENDPOINT: &str = "hyperblock/by-hash";
const COST_TRANSACTION_ENDPOINT: &str = "transaction/cost";
const SEND_TRANSACTION_ENDPOINT: &str = "transaction/send";
const SEND_MULTIPLE_TRANSACTIONS_ENDPOINT: &str = "transaction/send-multiple";
const GET_TRANSACTION_INFO_ENDPOINT: &str = "transaction/";
const WITH_RESULTS_QUERY_PARAM: &str = "?withResults=true";
const VM_VALUES_ENDPOINT: &str = "vm-values/query";

pub enum GatewayRequestType {
Get,
Post,
}

/// Models requests to the gateway.
pub trait GatewayRequest {
type Payload: serde::ser::Serialize + ?Sized;

type DecodedJson: serde::de::DeserializeOwned;

type Result;

fn request_type(&self) -> GatewayRequestType;

fn get_endpoint(&self) -> String;

fn get_payload(&self) -> Option<&Self::Payload> {
None
}

fn process_json(&self, decoded: Self::DecodedJson) -> anyhow::Result<Self::Result>;
}
40 changes: 40 additions & 0 deletions sdk/core/src/gateway/gateway_account.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
use crate::data::{
account::{Account, AccountResponse},
address::Address,
};
use anyhow::anyhow;

use super::ACCOUNT_ENDPOINT;
use super::{GatewayRequest, GatewayRequestType};

/// Retrieves an account info from the network (nonce, balance).
pub struct GetAccountRequest<'a> {
pub address: &'a Address,
}

impl<'a> GetAccountRequest<'a> {
pub fn new(address: &'a Address) -> Self {
Self { address }
}
}

impl<'a> GatewayRequest for GetAccountRequest<'a> {
type Payload = ();
type DecodedJson = AccountResponse;
type Result = Account;

fn request_type(&self) -> GatewayRequestType {
GatewayRequestType::Get
}

fn get_endpoint(&self) -> String {
format!("{ACCOUNT_ENDPOINT}{}", self.address)
}

fn process_json(&self, decoded: Self::DecodedJson) -> anyhow::Result<Self::Result> {
match decoded.data {
None => Err(anyhow!("{}", decoded.error)),
Some(b) => Ok(b.account),
}
}
}
39 changes: 39 additions & 0 deletions sdk/core/src/gateway/gateway_account_esdt_roles.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
use crate::data::{address::Address, esdt::EsdtRolesResponse};
use anyhow::anyhow;
use std::collections::HashMap;

use super::{GatewayRequest, GatewayRequestType};

const ACCOUNT_ENDPOINT: &str = "address/";

/// Retrieves an all esdt roles of an account from the network.
pub struct GetAccountEsdtRolesRequest<'a> {
pub address: &'a Address,
}

impl<'a> GetAccountEsdtRolesRequest<'a> {
pub fn new(address: &'a Address) -> Self {
Self { address }
}
}

impl<'a> GatewayRequest for GetAccountEsdtRolesRequest<'a> {
type Payload = ();
type DecodedJson = EsdtRolesResponse;
type Result = HashMap<String, Vec<String>>;

fn request_type(&self) -> GatewayRequestType {
GatewayRequestType::Get
}

fn get_endpoint(&self) -> String {
format!("{ACCOUNT_ENDPOINT}/{}/esdts/roles", self.address)
}

fn process_json(&self, decoded: Self::DecodedJson) -> anyhow::Result<Self::Result> {
match decoded.data {
None => Err(anyhow!("{}", decoded.error)),
Some(b) => Ok(b.roles),
}
}
}
40 changes: 40 additions & 0 deletions sdk/core/src/gateway/gateway_account_esdt_tokens.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
use crate::data::{
address::Address,
esdt::{EsdtBalance, EsdtBalanceResponse},
};
use anyhow::anyhow;
use std::collections::HashMap;

use super::{GatewayRequest, GatewayRequestType, ACCOUNT_ENDPOINT};

/// Retrieves an all esdt tokens of an account from the network.
pub struct GetAccountEsdtTokensRequest<'a> {
pub address: &'a Address,
}

impl<'a> GetAccountEsdtTokensRequest<'a> {
pub fn new(address: &'a Address) -> Self {
Self { address }
}
}

impl<'a> GatewayRequest for GetAccountEsdtTokensRequest<'a> {
type Payload = ();
type DecodedJson = EsdtBalanceResponse;
type Result = HashMap<String, EsdtBalance>;

fn request_type(&self) -> GatewayRequestType {
GatewayRequestType::Get
}

fn get_endpoint(&self) -> String {
format!("{ACCOUNT_ENDPOINT}{}/esdt", self.address)
}

fn process_json(&self, decoded: Self::DecodedJson) -> anyhow::Result<Self::Result> {
match decoded.data {
None => Err(anyhow!("{}", decoded.error)),
Some(b) => Ok(b.esdts),
}
}
}
37 changes: 37 additions & 0 deletions sdk/core/src/gateway/gateway_account_storage.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
use crate::data::{account_storage::AccountStorageResponse, address::Address};
use anyhow::anyhow;
use std::collections::HashMap;

use super::{GatewayRequest, GatewayRequestType, ACCOUNT_ENDPOINT, KEYS_ENDPOINT};

/// Retrieves an account storage from the network.
pub struct GetAccountStorageRequest<'a> {
pub address: &'a Address,
}

impl<'a> GetAccountStorageRequest<'a> {
pub fn new(address: &'a Address) -> Self {
Self { address }
}
}

impl<'a> GatewayRequest for GetAccountStorageRequest<'a> {
type Payload = ();
type DecodedJson = AccountStorageResponse;
type Result = HashMap<String, String>;

fn request_type(&self) -> GatewayRequestType {
GatewayRequestType::Get
}

fn get_endpoint(&self) -> String {
format!("{ACCOUNT_ENDPOINT}{}{KEYS_ENDPOINT}", self.address)
}

fn process_json(&self, decoded: Self::DecodedJson) -> anyhow::Result<Self::Result> {
match decoded.data {
None => Err(anyhow!("{}", decoded.error)),
Some(b) => Ok(b.pairs),
}
}
}
47 changes: 47 additions & 0 deletions sdk/core/src/gateway/gateway_block.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
use crate::data::hyperblock::{HyperBlock, HyperBlockResponse};
use anyhow::anyhow;

use super::{
GatewayRequest, GatewayRequestType, GET_HYPER_BLOCK_BY_HASH_ENDPOINT,
GET_HYPER_BLOCK_BY_NONCE_ENDPOINT,
};

/// Retrieves the data of a hyper block.
pub struct GetHyperBlockRequest {
pub query: String,
}

impl GetHyperBlockRequest {
pub fn by_nonce(nonce: u64) -> Self {
Self {
query: format!("{GET_HYPER_BLOCK_BY_NONCE_ENDPOINT}/{nonce}"),
}
}

pub fn by_hash(hash: &str) -> Self {
Self {
query: format!("{GET_HYPER_BLOCK_BY_HASH_ENDPOINT}/{hash}"),
}
}
}

impl GatewayRequest for GetHyperBlockRequest {
type Payload = ();
type DecodedJson = HyperBlockResponse;
type Result = HyperBlock;

fn request_type(&self) -> GatewayRequestType {
GatewayRequestType::Get
}

fn get_endpoint(&self) -> String {
self.query.clone()
}

fn process_json(&self, decoded: Self::DecodedJson) -> anyhow::Result<Self::Result> {
match decoded.data {
None => Err(anyhow!("{}", decoded.error)),
Some(b) => Ok(b.hyperblock),
}
}
}
28 changes: 28 additions & 0 deletions sdk/core/src/gateway/gateway_network_config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
use crate::data::network_config::{NetworkConfig, NetworkConfigResponse};
use anyhow::anyhow;

use super::{GatewayRequest, GatewayRequestType, NETWORK_CONFIG_ENDPOINT};

/// Retrieves the network configuration from the proxy.
pub struct NetworkConfigRequest;

impl GatewayRequest for NetworkConfigRequest {
type Payload = ();
type DecodedJson = NetworkConfigResponse;
type Result = NetworkConfig;

fn request_type(&self) -> GatewayRequestType {
GatewayRequestType::Get
}

fn get_endpoint(&self) -> String {
NETWORK_CONFIG_ENDPOINT.to_owned()
}

fn process_json(&self, decoded: Self::DecodedJson) -> anyhow::Result<Self::Result> {
match decoded.data {
None => Err(anyhow!("{}", decoded.error)),
Some(b) => Ok(b.config),
}
}
}
28 changes: 28 additions & 0 deletions sdk/core/src/gateway/gateway_network_economics.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
use crate::data::network_economics::{NetworkEconomics, NetworkEconomicsResponse};
use anyhow::anyhow;

use super::{GatewayRequest, GatewayRequestType, NETWORK_ECONOMICS_ENDPOINT};

/// Retrieves the network economics from the proxy.
pub struct NetworkEconimicsRequest;

impl GatewayRequest for NetworkEconimicsRequest {
type Payload = ();
type DecodedJson = NetworkEconomicsResponse;
type Result = NetworkEconomics;

fn request_type(&self) -> GatewayRequestType {
GatewayRequestType::Get
}

fn get_endpoint(&self) -> String {
NETWORK_ECONOMICS_ENDPOINT.to_owned()
}

fn process_json(&self, decoded: Self::DecodedJson) -> anyhow::Result<Self::Result> {
match decoded.data {
None => Err(anyhow!("{}", decoded.error)),
Some(b) => Ok(b.metrics),
}
}
}
38 changes: 38 additions & 0 deletions sdk/core/src/gateway/gateway_network_status.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
use crate::data::network_status::{NetworkStatus, NetworkStatusResponse};
use anyhow::anyhow;

use super::{GatewayRequest, GatewayRequestType, GET_NETWORK_STATUS_ENDPOINT, METACHAIN_SHARD_ID};

/// Retrieves the network status from the proxy.
pub struct NetworkStatusRequest {
shard: u32,
}

impl Default for NetworkStatusRequest {
fn default() -> Self {
Self {
shard: METACHAIN_SHARD_ID,
}
}
}

impl GatewayRequest for NetworkStatusRequest {
type Payload = ();
type DecodedJson = NetworkStatusResponse;
type Result = NetworkStatus;

fn request_type(&self) -> GatewayRequestType {
GatewayRequestType::Get
}

fn get_endpoint(&self) -> String {
format!("{GET_NETWORK_STATUS_ENDPOINT}/{}", self.shard)
}

fn process_json(&self, decoded: Self::DecodedJson) -> anyhow::Result<Self::Result> {
match decoded.data {
None => Err(anyhow!("{}", decoded.error)),
Some(b) => Ok(b.status),
}
}
}
Loading
Loading