Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
stringhandler committed Mar 28, 2024
1 parent 86dd4f9 commit f277b15
Show file tree
Hide file tree
Showing 8 changed files with 409 additions and 1 deletion.
39 changes: 39 additions & 0 deletions Cargo.lock

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

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ members = [
"clients/base_node_client",
"clients/validator_node_client",
"clients/wallet_daemon_client",
"clients/tari_wallet_sdk_ffi",
"dan_layer/consensus",
"dan_layer/consensus_tests",
"dan_layer/epoch_manager",
Expand Down Expand Up @@ -79,6 +80,7 @@ tari_dan_engine = { path = "dan_layer/engine" }
tari_dan_storage = { path = "dan_layer/storage" }
tari_dan_storage_sqlite = { path = "dan_layer/storage_sqlite" }
tari_dan_wallet_daemon = { path = "applications/tari_dan_wallet_daemon" }
tari_wallet_sdk_ffi = { path = "clients/tari_wallet_sdk_ffi" }
tari_dan_wallet_sdk = { path = "dan_layer/wallet/sdk" }
tari_dan_wallet_crypto = { path = "dan_layer/wallet/crypto" }
tari_dan_wallet_storage_sqlite = { path = "dan_layer/wallet/storage_sqlite" }
Expand Down
33 changes: 33 additions & 0 deletions clients/tari_wallet_sdk_ffi/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
[package]
name = "tari_wallet_sdk_ffi"
version.workspace = true
edition.workspace = true
authors.workspace = true
repository.workspace = true
license.workspace = true

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
tari_engine_types = { workspace = true }
tari_dan_common_types = { workspace = true }
tari_dan_wallet_sdk = { workspace = true }
tari_dan_wallet_storage_sqlite = { workspace = true }
tari_indexer_client = {workspace = true }
tari_template_abi = {workspace = true}
tari_template_lib = { workspace = true }
tari_transaction = {workspace = true }


axum = { workspace = true, features = ["headers"] }
reqwest = { workspace = true, features = ["json"] }
thiserror = { workspace = true }
url = { workspace = true }


[build-dependencies]
tari_common = {workspace = true, features = ["build"]}
cbindgen = "0.24.3"

[lib]
crate-type = ["cdylib"]
58 changes: 58 additions & 0 deletions clients/tari_wallet_sdk_ffi/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// Copyright 2019, The Tari Project
//
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
// following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
// disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
// following disclaimer in the documentation and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
// products derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

use std::{env, path::PathBuf};

use cbindgen::{Config, Language, LineEndingStyle, ParseConfig, Style};
// use tari_common::build::StaticApplicationInfo;

fn main() {
let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap();

// generate version info
// let gen = StaticApplicationInfo::initialize().unwrap();
// gen.write_consts_to_outdir("consts.rs").unwrap();

let output_file = PathBuf::from(&crate_dir)
.join("tari_wallet_sdk_ffi.h")
.display()
.to_string();

let config = Config {
language: Language::C,
header: Some("// Copyright 2024. The Tari Project\n// SPDX-License-Identifier: BSD-3-Clause".to_string()),
parse: ParseConfig {
//parse_deps: true,
// include: Some(vec!["tari_comms".to_string()]),
..Default::default()
},
autogen_warning: Some("// This file was generated by cargo-bindgen. Please do not edit manually.".to_string()),
style: Style::Tag,
cpp_compat: true,
line_endings: LineEndingStyle::CRLF,
..Default::default()
};

cbindgen::generate_with_config(&crate_dir, config)
.unwrap()
.write_to_file(output_file);
}
191 changes: 191 additions & 0 deletions clients/tari_wallet_sdk_ffi/src/indexer_jrpc_impl.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
// Copyright 2023 The Tari Project
// SPDX-License-Identifier: BSD-3-Clause

use std::sync::{Arc, Mutex};

use axum::async_trait;
use reqwest::{IntoUrl, Url};
use tari_dan_common_types::optional::IsNotFoundError;
use tari_dan_wallet_sdk::network::{
SubstateQueryResult,
TransactionFinalizedResult,
TransactionQueryResult,
WalletNetworkInterface,
};
use tari_engine_types::substate::SubstateId;
use tari_indexer_client::{
error::IndexerClientError,
json_rpc_client::IndexerJsonRpcClient,
types::{
GetSubstateRequest,
GetTransactionResultRequest,
IndexerTransactionFinalizedResult,
SubmitTransactionRequest,
},
};
use tari_template_lib::models::TemplateAddress;
use tari_transaction::{SubstateRequirement, Transaction, TransactionId};
use url::ParseError;

#[derive(Debug, Clone)]
pub struct IndexerJsonRpcNetworkInterface {
indexer_jrpc_address: Arc<Mutex<Url>>,
}

impl IndexerJsonRpcNetworkInterface {
pub fn new<T: IntoUrl>(indexer_jrpc_address: T) -> Self {
Self {
indexer_jrpc_address: Arc::new(Mutex::new(
indexer_jrpc_address
.into_url()
.expect("Malformed indexer JSON-RPC address"),
)),
}
}

fn get_client(&self) -> Result<IndexerJsonRpcClient, IndexerJrpcError> {
let client = IndexerJsonRpcClient::connect((*self.indexer_jrpc_address.lock().unwrap()).clone())?;
Ok(client)
}

pub fn set_endpoint(&mut self, endpoint: &str) -> Result<(), IndexerJrpcError> {
*self.indexer_jrpc_address.lock().unwrap() = Url::parse(endpoint)?;
Ok(())
}

pub fn get_endpoint(&self) -> Url {
(*self.indexer_jrpc_address.lock().unwrap()).clone()
}
}

#[async_trait]
impl WalletNetworkInterface for IndexerJsonRpcNetworkInterface {
type Error = IndexerJrpcError;

async fn query_substate(
&self,
address: &SubstateId,
version: Option<u32>,
local_search_only: bool,
) -> Result<SubstateQueryResult, Self::Error> {
let mut client = self.get_client()?;
let result = client
.get_substate(GetSubstateRequest {
address: address.clone(),
version,
local_search_only,
})
.await?;
Ok(SubstateQueryResult {
address: result.address,
version: result.version,
substate: result.substate,
created_by_transaction: result.created_by_transaction,
})
}

async fn submit_transaction(
&self,
transaction: Transaction,
required_substates: Vec<SubstateRequirement>,
) -> Result<TransactionId, Self::Error> {
let mut client = self.get_client()?;
let result = client
.submit_transaction(SubmitTransactionRequest {
transaction,
required_substates,
is_dry_run: false,
})
.await?;
Ok(result.transaction_id)
}

async fn submit_dry_run_transaction(
&self,
transaction: Transaction,
required_substates: Vec<SubstateRequirement>,
) -> Result<TransactionQueryResult, Self::Error> {
let mut client = self.get_client()?;
let resp = client
.submit_transaction(SubmitTransactionRequest {
transaction,
required_substates,
is_dry_run: true,
})
.await?;

Ok(TransactionQueryResult {
transaction_id: resp.transaction_id,
result: convert_indexer_result_to_wallet_result(resp.result),
})
}

async fn query_transaction_result(
&self,
transaction_id: TransactionId,
) -> Result<TransactionQueryResult, Self::Error> {
let mut client = self.get_client()?;
let resp = client
.get_transaction_result(GetTransactionResultRequest { transaction_id })
.await?;

Ok(TransactionQueryResult {
transaction_id,
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)]
pub enum IndexerJrpcError {
#[error("Indexer client error: {0}")]
IndexerClientError(#[from] IndexerClientError),
#[error("Indexer parse error : {0}")]
IndexerParseError(#[from] ParseError),
}

impl IsNotFoundError for IndexerJrpcError {
fn is_not_found_error(&self) -> bool {
match self {
IndexerJrpcError::IndexerClientError(err) => err.is_not_found_error(),
_ => false,
}
}
}

/// These types are identical, however in order to keep the wallet decoupled from the indexer, we define two types and
/// this conversion function.
// TODO: the common interface and types between the wallet and indexer could be made into a shared "view of the network"
// interface and we can avoid defining two types.
fn convert_indexer_result_to_wallet_result(result: IndexerTransactionFinalizedResult) -> TransactionFinalizedResult {
match result {
IndexerTransactionFinalizedResult::Pending => TransactionFinalizedResult::Pending,
IndexerTransactionFinalizedResult::Finalized {
final_decision,
execution_result,
finalized_time,
execution_time,
abort_details,
json_results,
} => TransactionFinalizedResult::Finalized {
final_decision,
execution_result,
execution_time,
finalized_time,
abort_details,
json_results,
},
}
}
Loading

0 comments on commit f277b15

Please sign in to comment.