Skip to content

Commit

Permalink
Add endpoint to v0.1 and v0.2
Browse files Browse the repository at this point in the history
  • Loading branch information
perekopskiy committed Nov 8, 2021
1 parent 56184cd commit 67bb8c1
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 3 deletions.
48 changes: 46 additions & 2 deletions core/bin/zksync_api/src/api_server/rest/v02/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use zksync_api_types::v02::{
use zksync_config::ZkSyncConfig;
use zksync_crypto::params::MIN_NFT_TOKEN_ID;
use zksync_storage::{ConnectionPool, StorageProcessor};
use zksync_types::{AccountId, Token, TokenId, TokenLike};
use zksync_types::{tx::TxHash, AccountId, Token, TokenId, TokenLike};

// Local uses
use super::{
Expand Down Expand Up @@ -260,6 +260,20 @@ async fn get_nft_owner(
ApiResult::Ok(owner_id)
}

async fn get_nft_id_by_tx_hash(
data: web::Data<ApiTokenData>,
tx_hash: web::Path<TxHash>,
) -> ApiResult<Option<TokenId>> {
let mut storage = api_try!(data.pool.access_storage().await.map_err(Error::storage));
let nft_id = api_try!(storage
.chain()
.state_schema()
.get_nft_id_by_tx_hash(*tx_hash)
.await
.map_err(Error::storage));
ApiResult::Ok(nft_id)
}

pub fn api_scope(
config: &ZkSyncConfig,
pool: ConnectionPool,
Expand All @@ -278,6 +292,10 @@ pub fn api_scope(
)
.route("nft/{id}", web::get().to(get_nft))
.route("nft/{id}/owner", web::get().to(get_nft_owner))
.route(
"nft_id_by_tx_hash/{tx_hash}",
web::get().to(get_nft_id_by_tx_hash),
)
}

#[cfg(test)]
Expand All @@ -288,7 +306,7 @@ mod tests {
SharedData,
};
use zksync_api_types::v02::{pagination::PaginationDirection, ApiVersion};
use zksync_types::Address;
use zksync_types::{Address, BlockNumber, ZkSyncTx};

async fn is_token_enabled_for_fees(
storage: &mut StorageProcessor<'_>,
Expand Down Expand Up @@ -441,6 +459,32 @@ mod tests {
};
assert_eq!(owner_id, expected_owner_id);

let mut block_number = BlockNumber(0);
let tx_hash = loop {
let mut storage = cfg.pool.access_storage().await?;
let ops = storage
.chain()
.block_schema()
.get_block_executed_ops(block_number)
.await?;
let mut tx_hash: Option<TxHash> = None;
for op in ops {
if let Some(tx) = op.get_executed_tx() {
if matches!(tx.signed_tx.tx, ZkSyncTx::MintNFT(_)) {
tx_hash = Some(tx.signed_tx.tx.hash());
}
}
}
if let Some(tx_hash) = tx_hash {
break tx_hash;
}
block_number.0 += 1;
};

let response = client.nft_id_by_tx_hash(tx_hash).await?;
let nft_id: Option<TokenId> = deserialize_response_result(response)?;
assert!(nft_id.is_some());

server.stop().await;
Ok(())
}
Expand Down
18 changes: 18 additions & 0 deletions core/bin/zksync_api/src/api_server/rpc_server/rpc_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -335,4 +335,22 @@ impl RpcApp {
metrics::histogram!("api.rpc.toggle_2fa", start.elapsed());
response
}

pub async fn _impl_get_nft_id_by_tx_hash(self, tx_hash: TxHash) -> Result<Option<TokenId>> {
let start = Instant::now();

let mut storage = self.access_storage().await?;
let response = storage
.chain()
.state_schema()
.get_nft_id_by_tx_hash(tx_hash)
.await
.map_err(|err| {
vlog::warn!("Internal Server Error: '{}'; input: N/A", err);
Error::internal_error()
})?;

metrics::histogram!("api.rpc.get_nft_id_by_tx_hash", start.elapsed());
Ok(response)
}
}
7 changes: 7 additions & 0 deletions core/bin/zksync_api/src/api_server/rpc_server/rpc_trait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@ pub trait Rpc {

#[rpc(name = "toggle_2fa", returns = "Toggle2FAResponse")]
fn toggle_2fa(&self, toggle_2fa: Toggle2FA) -> BoxFutureResult<Toggle2FAResponse>;

#[rpc(name = "get_nft_id_by_tx_hash", returns = "Option<TokenId>")]
fn get_nft_id_by_tx_hash(&self, tx_hash: TxHash) -> BoxFutureResult<Option<TokenId>>;
}

impl Rpc for RpcApp {
Expand Down Expand Up @@ -191,4 +194,8 @@ impl Rpc for RpcApp {
fn toggle_2fa(&self, toggle_2fa: Toggle2FA) -> BoxFutureResult<Toggle2FAResponse> {
spawn!(self._impl_toggle_2fa(toggle_2fa))
}

fn get_nft_id_by_tx_hash(&self, tx_hash: TxHash) -> BoxFutureResult<Option<TokenId>> {
spawn!(self._impl_get_nft_id_by_tx_hash(tx_hash))
}
}
11 changes: 10 additions & 1 deletion core/lib/api_client/src/rest/v02/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use zksync_api_types::v02::{
pagination::{ApiEither, PaginationQuery},
Response,
};
use zksync_types::{TokenId, TokenLike};
use zksync_types::{tx::TxHash, TokenId, TokenLike};

impl Client {
pub async fn token_pagination(
Expand Down Expand Up @@ -42,4 +42,13 @@ impl Client {
.send()
.await
}

pub async fn nft_id_by_tx_hash(&self, tx_hash: TxHash) -> Result<Response> {
self.get_with_scope(
super::API_V02_SCOPE,
&format!("tokens/nft_id_by_tx_hash/{}", tx_hash.to_string()),
)
.send()
.await
}
}
20 changes: 20 additions & 0 deletions core/lib/storage/sqlx-data.json
Original file line number Diff line number Diff line change
Expand Up @@ -4063,6 +4063,26 @@
"nullable": []
}
},
"924c04e90c91241f25e8ad84e6d274ff7769fbf11fa5ca54b0f848e701aaa03e": {
"query": "\n SELECT token_id FROM executed_transactions\n LEFT JOIN mint_nft_updates\n ON executed_transactions.from_account = mint_nft_updates.creator_address\n AND executed_transactions.nonce = mint_nft_updates.nonce\n WHERE executed_transactions.tx_hash = $1\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "token_id",
"type_info": "Int4"
}
],
"parameters": {
"Left": [
"Bytea"
]
},
"nullable": [
false
]
}
},
"92663f125319988e4b5d80d3d58286ca90a29ec2fa97d87750942c9e0615d1bc": {
"query": "SELECT COUNT(*) FROM prover_job_queue WHERE job_status != $1",
"describe": {
Expand Down
20 changes: 20 additions & 0 deletions core/lib/storage/src/chain/state/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use sqlx::types::BigDecimal;
// Workspace imports
use zksync_types::{
helpers::{apply_updates, reverse_updates},
tx::TxHash,
AccountId, AccountMap, AccountUpdate, AccountUpdates, Address, BlockNumber, Nonce, PubKeyHash,
TokenId, ZkSyncTx, NFT,
};
Expand Down Expand Up @@ -698,6 +699,25 @@ impl<'a, 'c> StateSchema<'a, 'c> {
Ok(nft.map(|p| p.into()))
}

pub async fn get_nft_id_by_tx_hash(&mut self, tx_hash: TxHash) -> QueryResult<Option<TokenId>> {
let start = Instant::now();
let record = sqlx::query!(
r#"
SELECT token_id FROM executed_transactions
LEFT JOIN mint_nft_updates
ON executed_transactions.from_account = mint_nft_updates.creator_address
AND executed_transactions.nonce = mint_nft_updates.nonce
WHERE executed_transactions.tx_hash = $1
"#,
tx_hash.as_ref()
)
.fetch_optional(self.0.conn())
.await?;

metrics::histogram!("sql.chain.state.get_nft_id_by_tx_hash", start.elapsed());
Ok(record.map(|r| TokenId(r.token_id as u32)))
}

pub async fn load_committed_nft_tokens(
&mut self,
block_number: Option<BlockNumber>,
Expand Down

0 comments on commit 67bb8c1

Please sign in to comment.