Skip to content

Commit

Permalink
feat(walletd): add substates and templates calls to JSON-RPC (#936)
Browse files Browse the repository at this point in the history
Description
---

feat(walletd): adds substates.get and substates.list calls
feat(walletd): adds template.get call
feat(indexer): adds template.get call
feat(walletd/js/client): add JWT auth calls
feat(walletd/js/client): add substate and template calls
chore: update typescript bindings

Motivation and Context
---
These JSON-RPC calls allow clients to retrieve details about substates
managed by the wallet as well as retrieve the template definition for
arbitrary templates.

How Has This Been Tested?
---
Mnaually using
[tari-template-web](https://github.com/tari-project/tari-template-web)

What process can a PR reviewer use to test or verify this change?
---
Run
[tari-template-web](https://github.com/tari-project/tari-template-web)

Breaking Changes
---

- [x] None
- [ ] Requires data directory to be deleted
- [ ] Other - Please specify
  • Loading branch information
sdbondi authored Feb 14, 2024
1 parent a3f3135 commit 7e7dbef
Show file tree
Hide file tree
Showing 60 changed files with 834 additions and 283 deletions.
4 changes: 4 additions & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions applications/tari_dan_wallet_daemon/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ tari_wallet_daemon_client = { workspace = true }
tari_template_builtin = { workspace = true }
# TODO: Ideally we should not have to include the WASM template lib, we should perhaps extract the address types into a separate crate (e.g. template_types)
tari_template_lib = { workspace = true }
tari_template_abi = { workspace = true }
tari_indexer_client = { workspace = true }
tari_key_manager = { workspace = true }

Expand Down
2 changes: 2 additions & 0 deletions applications/tari_dan_wallet_daemon/src/handlers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ pub mod keys;
pub mod nfts;
pub mod rpc;
pub mod settings;
pub mod substates;
pub mod templates;
pub mod transaction;
pub mod validator;
pub mod webrtc;
Expand Down
67 changes: 67 additions & 0 deletions applications/tari_dan_wallet_daemon/src/handlers/substates.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// Copyright 2023 The Tari Project
// SPDX-License-Identifier: BSD-3-Clause

use tari_dan_wallet_sdk::{apis::jwt::JrpcPermission, network::WalletNetworkInterface};
use tari_wallet_daemon_client::types::{
SubstatesGetRequest,
SubstatesGetResponse,
SubstatesListRequest,
SubstatesListResponse,
WalletSubstateRecord,
};

use crate::handlers::HandlerContext;

pub async fn handle_get(
context: &HandlerContext,
token: Option<String>,
req: SubstatesGetRequest,
) -> Result<SubstatesGetResponse, anyhow::Error> {
let sdk = context.wallet_sdk().clone();
sdk.jwt_api().check_auth(token, &[JrpcPermission::SubstatesRead])?;

let record = sdk.substate_api().get_substate(&req.substate_id)?;

let substate = sdk
.get_network_interface()
.query_substate(&record.address.substate_id, Some(record.address.version), false)
.await?;

Ok(SubstatesGetResponse {
record: WalletSubstateRecord {
substate_id: record.address.substate_id,
parent_id: record.parent_address,
module_name: record.module_name,
version: record.address.version,
template_address: record.template_address,
},
value: substate.substate,
})
}

pub async fn handle_list(
context: &HandlerContext,
token: Option<String>,
req: SubstatesListRequest,
) -> Result<SubstatesListResponse, anyhow::Error> {
let sdk = context.wallet_sdk().clone();
sdk.jwt_api().check_auth(token, &[JrpcPermission::SubstatesRead])?;

// TODO: pagination
let substates =
sdk.substate_api()
.list_substates(req.filter_by_type, req.filter_by_template.as_ref(), None, None)?;

let substates = substates
.into_iter()
.map(|substate| WalletSubstateRecord {
substate_id: substate.address.substate_id,
parent_id: substate.parent_address,
version: substate.address.version,
template_address: substate.template_address,
module_name: substate.module_name,
})
.collect();

Ok(SubstatesListResponse { substates })
}
23 changes: 23 additions & 0 deletions applications/tari_dan_wallet_daemon/src/handlers/templates.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright 2023 The Tari Project
// SPDX-License-Identifier: BSD-3-Clause

use tari_dan_wallet_sdk::{apis::jwt::JrpcPermission, network::WalletNetworkInterface};
use tari_wallet_daemon_client::types::{TemplatesGetRequest, TemplatesGetResponse};

use crate::handlers::HandlerContext;

pub async fn handle_get(
context: &HandlerContext,
token: Option<String>,
req: TemplatesGetRequest,
) -> Result<TemplatesGetResponse, anyhow::Error> {
let sdk = context.wallet_sdk().clone();
sdk.jwt_api().check_auth(token, &[JrpcPermission::TemplatesRead])?;

let template_definition = sdk
.get_network_interface()
.fetch_template_definition(req.template_address)
.await?;

Ok(TemplatesGetResponse { template_definition })
}
13 changes: 13 additions & 0 deletions applications/tari_dan_wallet_daemon/src/indexer_jrpc_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use tari_indexer_client::{
SubmitTransactionRequest,
},
};
use tari_template_lib::models::TemplateAddress;
use tari_transaction::{SubstateRequirement, Transaction, TransactionId};
use url::ParseError;

Expand Down Expand Up @@ -133,6 +134,18 @@ impl WalletNetworkInterface for IndexerJsonRpcNetworkInterface {
result: convert_indexer_result_to_wallet_result(resp.result),
})
}

async fn fetch_template_definition(
&self,
template_address: TemplateAddress,
) -> Result<tari_template_abi::TemplateDef, Self::Error> {
let mut client = self.get_client()?;
let resp = client
.get_template_definition(tari_indexer_client::types::GetTemplateDefinitionRequest { template_address })
.await?;

Ok(resp.definition)
}
}

#[derive(Debug, thiserror::Error)]
Expand Down
8 changes: 7 additions & 1 deletion applications/tari_dan_wallet_daemon/src/jrpc_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use tari_dan_wallet_sdk::apis::jwt::JwtApiError;
use tari_shutdown::ShutdownSignal;
use tower_http::{cors::CorsLayer, trace::TraceLayer};

use super::handlers::HandlerContext;
use super::handlers::{substates, templates, HandlerContext};
use crate::handlers::{
accounts,
confidential,
Expand Down Expand Up @@ -154,6 +154,12 @@ async fn handler(
},
_ => Ok(value.method_not_found(&value.method)),
},
Some(("substates", method)) => match method {
"get" => call_handler(context, value, token, substates::handle_get).await,
"list" => call_handler(context, value, token, substates::handle_list).await,
_ => Ok(value.method_not_found(&value.method)),
},
Some(("templates", "get")) => call_handler(context, value, token, templates::handle_get).await,
Some(("nfts", method)) => match method {
"mint_account_nft" => call_handler(context, value, token, nfts::handle_mint_account_nft).await,
"get" => call_handler(context, value, token, nfts::handle_get_nft).await,
Expand Down
41 changes: 40 additions & 1 deletion applications/tari_indexer/src/json_rpc/handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,13 @@ use libp2p::swarm::dial_opts::{DialOpts, PeerCondition};
use log::{error, warn};
use serde_json::{self as json, json, Value};
use tari_base_node_client::{grpc::GrpcBaseNodeClient, types::BaseLayerConsensusConstants, BaseNodeClient};
use tari_dan_app_utilities::{keypair::RistrettoKeypair, substate_file_cache::SubstateFileCache};
use tari_dan_app_utilities::{
keypair::RistrettoKeypair,
substate_file_cache::SubstateFileCache,
template_manager::{implementation::TemplateManager, interface::TemplateExecutable},
};
use tari_dan_common_types::{optional::Optional, public_key_to_peer_id, PeerAddress};
use tari_dan_engine::{template::TemplateModuleLoader, wasm::WasmModule};
use tari_dan_p2p::TariMessagingSpec;
use tari_dan_storage::consensus_models::Decision;
use tari_epoch_manager::{base_layer::EpochManagerHandle, EpochManagerReader};
Expand Down Expand Up @@ -62,6 +67,8 @@ use tari_indexer_client::{
GetRelatedTransactionsResponse,
GetSubstateRequest,
GetSubstateResponse,
GetTemplateDefinitionRequest,
GetTemplateDefinitionResponse,
GetTransactionResultRequest,
GetTransactionResultResponse,
IndexerTransactionFinalizedResult,
Expand Down Expand Up @@ -99,6 +106,7 @@ pub struct JsonRpcHandlers {
epoch_manager: EpochManagerHandle<PeerAddress>,
transaction_manager:
TransactionManager<EpochManagerHandle<PeerAddress>, TariValidatorNodeRpcClientFactory, SubstateFileCache>,
template_manager: TemplateManager<PeerAddress>,
dry_run_transaction_processor: DryRunTransactionProcessor<SubstateFileCache>,
}

Expand All @@ -113,6 +121,7 @@ impl JsonRpcHandlers {
TariValidatorNodeRpcClientFactory,
SubstateFileCache,
>,
template_manager: TemplateManager<PeerAddress>,
dry_run_transaction_processor: DryRunTransactionProcessor<SubstateFileCache>,
) -> Self {
Self {
Expand All @@ -123,6 +132,7 @@ impl JsonRpcHandlers {
substate_manager,
epoch_manager: services.epoch_manager.clone(),
transaction_manager,
template_manager,
dry_run_transaction_processor,
}
}
Expand Down Expand Up @@ -587,6 +597,35 @@ impl JsonRpcHandlers {
Ok(JsonRpcResponse::success(answer_id, response))
}

pub async fn get_template_definition(&self, value: JsonRpcExtractor) -> JrpcResult {
let answer_id = value.get_answer_id();
let request: GetTemplateDefinitionRequest = value.parse_params()?;
let template = self
.template_manager
.fetch_template(&request.template_address)
.map_err(|e| Self::internal_error(answer_id, e))?;
let template = match template.executable {
TemplateExecutable::CompiledWasm(code) => WasmModule::from_code(code)
.load_template()
.map_err(|e| Self::internal_error(answer_id, format!("Error loading template: {}", e)))?,
TemplateExecutable::Manifest(_) | TemplateExecutable::Flow(_) => {
return Err(JsonRpcResponse::error(
answer_id,
JsonRpcError::new(
JsonRpcErrorReason::InvalidRequest,
"Template is not a wasm module".to_string(),
json::Value::Null,
),
));
},
};

Ok(JsonRpcResponse::success(answer_id, GetTemplateDefinitionResponse {
definition: template.template_def().clone(),
name: template.template_name().to_string(),
}))
}

pub async fn get_transaction_result(&self, value: JsonRpcExtractor) -> JrpcResult {
let answer_id = value.get_answer_id();
let request: GetTransactionResultRequest = value.parse_params()?;
Expand Down
1 change: 1 addition & 0 deletions applications/tari_indexer/src/json_rpc/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ async fn handler(Extension(handlers): Extension<Arc<JsonRpcHandlers>>, value: Js
"get_transaction_result" => handlers.get_transaction_result(value).await,
"get_substate_transactions" => handlers.get_substate_transactions(value).await,
"get_epoch_manager_stats" => handlers.get_epoch_manager_stats(value).await,
"get_template_definition" => handlers.get_template_definition(value).await,
method => Ok(value.method_not_found(method)),
}
}
1 change: 1 addition & 0 deletions applications/tari_indexer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ pub async fn run_indexer(config: ApplicationConfig, mut shutdown_signal: Shutdow
base_node_client,
substate_manager.clone(),
transaction_manager,
services.template_manager.clone(),
dry_run_transaction_processor,
);
task::spawn(run_json_rpc(jrpc_address, handlers));
Expand Down
2 changes: 1 addition & 1 deletion applications/tari_indexer_web_ui/package-lock.json

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

2 changes: 1 addition & 1 deletion applications/tari_validator_node/src/json_rpc/handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -762,7 +762,7 @@ impl JsonRpcHandlers {
.map(|(bucket, validators)| CommitteeShardInfo {
shard: bucket,
substate_address_range: bucket.to_substate_address_range(num_committees),
validators,
validators: validators.into_iter().map(Into::into).collect(),
})
.collect();

Expand Down
2 changes: 2 additions & 0 deletions bindings/build.sh
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Copyright 2023 The Tari Project
# SPDX-License-Identifier: BSD-3-Clause

set -e

cargo test --workspace --exclude integration_tests export_bindings --features ts
npx shx mv ../dan_layer/bindings/src/types/* ./src/types/
npx shx rm -rf ../dan_layer/bindings/
Expand Down
Loading

0 comments on commit 7e7dbef

Please sign in to comment.