Skip to content

Commit

Permalink
[API] Add GET /transactions
Browse files Browse the repository at this point in the history
  • Loading branch information
banool committed Jul 20, 2022
1 parent f76e8e0 commit 9961ce6
Show file tree
Hide file tree
Showing 13 changed files with 304 additions and 118 deletions.
2 changes: 2 additions & 0 deletions api/src/poem_backend/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ mod page;
mod post;
mod response;
mod runtime;
mod transactions;

#[derive(Tags)]
pub enum ApiTags {
Expand All @@ -32,6 +33,7 @@ pub use response::{
AptosResponseContent,
};
pub use runtime::attach_poem_to_runtime;
pub use transactions::TransactionsApi;

// TODO: Move these impls throughout each of the files in the parent directory.
// The only reason I do it here right now is the existing handler functions return
Expand Down
7 changes: 5 additions & 2 deletions api/src/poem_backend/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::{net::SocketAddr, sync::Arc};

use super::{middleware_log, AccountsApi, BasicApi, EventsApi, IndexApi};

use crate::context::Context;
use crate::{context::Context, poem_backend::TransactionsApi};
use anyhow::Context as AnyhowContext;
use aptos_config::config::NodeConfig;
use aptos_logger::info;
Expand Down Expand Up @@ -36,7 +36,10 @@ pub fn attach_poem_to_runtime(
EventsApi {
context: context.clone(),
},
IndexApi { context },
IndexApi {
context: context.clone(),
},
TransactionsApi { context },
);

let version = std::env::var("CARGO_PKG_VERSION").unwrap_or_else(|_| "0.1.0".to_string());
Expand Down
116 changes: 116 additions & 0 deletions api/src/poem_backend/transactions.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

use std::convert::TryFrom;
use std::sync::Arc;

use super::accept_type::AcceptType;
use super::page::Page;
use super::{response::AptosResponseResult, ApiTags, AptosResponse};
use super::{AptosError, AptosErrorCode, AptosErrorResponse};
use crate::context::Context;
use crate::failpoint::fail_point_poem;
use anyhow::format_err;
use aptos_api_types::AsConverter;
use aptos_api_types::{LedgerInfo, Transaction, TransactionOnChainData};
use poem::web::Accept;
use poem_openapi::param::Query;
use poem_openapi::payload::Json;
use poem_openapi::OpenApi;

// TODO: Make a helper that builds an AptosResponse from just an anyhow error,
// that assumes that it's an internal error. We can use .context() add more info.

pub struct TransactionsApi {
pub context: Arc<Context>,
}

#[OpenApi]
impl TransactionsApi {
/// Get transactions
///
/// todo
#[oai(
path = "/transactions",
method = "get",
operation_id = "get_transactions",
tag = "ApiTags::General"
)]
async fn get_transactions(
&self,
accept: Accept,
start: Query<Option<u64>>,
limit: Query<Option<u16>>,
) -> AptosResponseResult<Vec<Transaction>> {
fail_point_poem("endpoint_get_transactions")?;
let accept_type = AcceptType::try_from(&accept)?;
let page = Page::new(start.0, limit.0);
self.list(&accept_type, page)
}
}

impl TransactionsApi {
fn list(&self, accept_type: &AcceptType, page: Page) -> AptosResponseResult<Vec<Transaction>> {
let latest_ledger_info = self.context.get_latest_ledger_info_poem()?;
let ledger_version = latest_ledger_info.version();
let limit = page.limit()?;
let last_page_start = if ledger_version > (limit as u64) {
ledger_version - (limit as u64)
} else {
0
};
let start_version = page.start(last_page_start, ledger_version)?;

let data = self
.context
.get_transactions(start_version, limit, ledger_version)
.map_err(|e| {
AptosErrorResponse::InternalServerError(Json(
AptosError::new(
format_err!("Failed to read raw transactions from storage: {}", e)
.to_string(),
)
.error_code(AptosErrorCode::InvalidBcsInStorageError),
))
})?;

self.render_transactions(data, accept_type, &latest_ledger_info)
}

fn render_transactions(
&self,
data: Vec<TransactionOnChainData>,
accept_type: &AcceptType,
latest_ledger_info: &LedgerInfo,
) -> AptosResponseResult<Vec<Transaction>> {
if data.is_empty() {
return AptosResponse::try_from_rust_value(vec![], latest_ledger_info, accept_type);
}

let resolver = self.context.move_resolver_poem()?;
let converter = resolver.as_converter();
let txns: Vec<Transaction> = data
.into_iter()
.map(|t| {
let version = t.version;
let timestamp = self.context.get_block_timestamp(version)?;
let txn = converter.try_into_onchain_transaction(timestamp, t)?;
Ok(txn)
})
.collect::<Result<_, anyhow::Error>>()
.map_err(|e| {
AptosErrorResponse::InternalServerError(Json(
AptosError::new(
format_err!("Failed to convert transaction data from storage: {}", e)
.to_string(),
)
.error_code(AptosErrorCode::InvalidBcsInStorageError),
))
})?;

AptosResponse::try_from_rust_value(txns, latest_ledger_info, accept_type)
}
}
6 changes: 6 additions & 0 deletions api/types/src/address.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,12 @@ impl<'de> Deserialize<'de> for Address {
}
}

impl Default for Address {
fn default() -> Self {
Self(AccountAddress::ONE)
}
}

impl_poem_type!(Address);
impl_poem_parameter!(Address);

Expand Down
29 changes: 16 additions & 13 deletions api/types/src/convert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
// SPDX-License-Identifier: Apache-2.0

use crate::{
transaction::{ModuleBundlePayload, StateCheckpointTransaction},
transaction::{
DeleteModule, DeleteResource, DeleteTableItem, ModuleBundlePayload,
StateCheckpointTransaction, WriteModule, WriteResource, WriteTableItem,
},
Bytecode, DirectWriteSet, Event, HexEncodedBytes, MoveFunction, MoveModuleBytecode,
MoveResource, MoveScriptBytecode, MoveValue, ScriptFunctionId, ScriptFunctionPayload,
ScriptPayload, ScriptWriteSet, Transaction, TransactionInfo, TransactionOnChainData,
Expand Down Expand Up @@ -233,28 +236,28 @@ impl<'a, R: MoveResolverExt + ?Sized> MoveConverter<'a, R> {
) -> Result<WriteSetChange> {
let ret = match op {
WriteOp::Deletion => match access_path.get_path() {
Path::Code(module_id) => WriteSetChange::DeleteModule {
Path::Code(module_id) => WriteSetChange::DeleteModule(DeleteModule {
address: access_path.address.into(),
state_key_hash,
module: module_id.into(),
},
Path::Resource(typ) => WriteSetChange::DeleteResource {
}),
Path::Resource(typ) => WriteSetChange::DeleteResource(DeleteResource {
address: access_path.address.into(),
state_key_hash,
resource: typ.into(),
},
}),
},
WriteOp::Value(val) => match access_path.get_path() {
Path::Code(_) => WriteSetChange::WriteModule {
Path::Code(_) => WriteSetChange::WriteModule(WriteModule {
address: access_path.address.into(),
state_key_hash,
data: MoveModuleBytecode::new(val).try_parse_abi()?,
},
Path::Resource(typ) => WriteSetChange::WriteResource {
}),
Path::Resource(typ) => WriteSetChange::WriteResource(WriteResource {
address: access_path.address.into(),
state_key_hash,
data: self.try_into_resource(&typ, &val)?,
},
}),
},
};
Ok(ret)
Expand All @@ -270,17 +273,17 @@ impl<'a, R: MoveResolverExt + ?Sized> MoveConverter<'a, R> {
let handle = handle.to_be_bytes().to_vec().into();
let key = key.into();
let ret = match op {
WriteOp::Deletion => WriteSetChange::DeleteTableItem {
WriteOp::Deletion => WriteSetChange::DeleteTableItem(DeleteTableItem {
state_key_hash,
handle,
key,
},
WriteOp::Value(value) => WriteSetChange::WriteTableItem {
}),
WriteOp::Value(value) => WriteSetChange::WriteTableItem(WriteTableItem {
state_key_hash,
handle,
key,
value: value.into(),
},
}),
};
Ok(ret)
}
Expand Down
3 changes: 3 additions & 0 deletions api/types/src/hash.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

use aptos_openapi::impl_poem_type;
use serde::{de::Error as _, Deserialize, Deserializer, Serialize, Serializer};
use std::{
fmt,
Expand Down Expand Up @@ -63,6 +64,8 @@ impl LowerHex for HashValue {
}
}

impl_poem_type!(HashValue);

#[cfg(test)]
mod tests {
use crate::hash::HashValue;
Expand Down
11 changes: 6 additions & 5 deletions api/types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,11 @@ pub use response::{
};
pub use table::TableItemRequest;
pub use transaction::{
BlockMetadataTransaction, DirectWriteSet, Event, GenesisTransaction, PendingTransaction,
ScriptFunctionPayload, ScriptPayload, ScriptWriteSet, Transaction, TransactionData,
TransactionId, TransactionInfo, TransactionOnChainData, TransactionPayload,
TransactionSigningMessage, UserCreateSigningMessageRequest, UserTransaction,
UserTransactionRequest, WriteSet, WriteSetChange, WriteSetPayload,
BlockMetadataTransaction, DeleteModule, DeleteResource, DeleteTableItem, DirectWriteSet, Event,
GenesisTransaction, PendingTransaction, ScriptFunctionPayload, ScriptPayload, ScriptWriteSet,
Transaction, TransactionData, TransactionId, TransactionInfo, TransactionOnChainData,
TransactionPayload, TransactionSigningMessage, UserCreateSigningMessageRequest,
UserTransaction, UserTransactionRequest, WriteModule, WriteResource, WriteSet, WriteSetChange,
WriteSetPayload, WriteTableItem,
};
pub use wrappers::{IdentifierWrapper, MoveStructTagWrapper};
8 changes: 4 additions & 4 deletions api/types/src/move_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ impl TryFrom<AnnotatedMoveStruct> for MoveResource {
}
}

#[derive(Clone, Debug, Eq, PartialEq, Copy, NewType)]
#[derive(Clone, Debug, Default, Eq, PartialEq, Copy, NewType)]
pub struct U64(pub u64);

impl U64 {
Expand Down Expand Up @@ -119,7 +119,7 @@ impl<'de> Deserialize<'de> for U64 {
}
}

#[derive(Clone, Debug, PartialEq, Copy)]
#[derive(Clone, Debug, Default, PartialEq, Copy)]
pub struct U128(u128);

impl U128 {
Expand Down Expand Up @@ -893,7 +893,7 @@ impl From<Module> for MoveModuleBytecode {
}
}

#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, Object)]
pub struct MoveScriptBytecode {
pub bytecode: HexEncodedBytes,
// We don't need deserialize MoveModule as it should be serialized
Expand Down Expand Up @@ -923,7 +923,7 @@ impl MoveScriptBytecode {
}
}

#[derive(Clone, Debug, PartialEq)]
#[derive(Clone, Debug, PartialEq, Object)]
pub struct ScriptFunctionId {
pub module: MoveModuleId,
pub name: IdentifierWrapper,
Expand Down
Loading

0 comments on commit 9961ce6

Please sign in to comment.