Skip to content
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
108 changes: 54 additions & 54 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# NOTE: When editing this version, also edit the versions in template_built_in/templates/account and account_nft
[workspace.package]
version = "0.13.1"
version = "0.14.0"
edition = "2021"
authors = ["The Tari Development Community"]
repository = "https://github.com/tari-project/tari-ootle"
Expand Down
16 changes: 11 additions & 5 deletions applications/tari_walletd/src/handlers/accounts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use tari_ootle_wallet_crypto::{
use tari_ootle_wallet_sdk::{
apis::{
confidential_transfer::ConfidentialTransferParams,
stealth_transfer::StealthTransferParams,
stealth_transfer::{StealthTransferParams, TransferOutput},
substate::ValidatorScanResult,
},
models::{KeyBranch, NewAccountData},
Expand Down Expand Up @@ -970,12 +970,18 @@ pub async fn handle_stealth_transfer(

let params = StealthTransferParams {
input_selection: req.input_selection,
destination_address: req.destination_address,
resource_address: req.resource_address,
max_fee: req.max_fee,
blinded_output_amount: req.blinded_output_amount,
revealed_output_amount: req.revealed_output_amount,
output_memo: req.output_memo,
outputs: req
.transfers
.into_iter()
.map(|transfer| TransferOutput {
address: transfer.destination_address,
blinded_amount: transfer.blinded_output_amount,
revealed_amount: transfer.revealed_output_amount,
memo: transfer.output_memo,
})
.collect(),
is_dry_run: req.dry_run,
};
if let Err(err) = params.validate(network) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,11 +154,15 @@ export const useAccountsTransfer = () => {
owner_account: account,
input_selection: params.input_selection,
resource_address: params.resource_address,
destination_address: params.destination_address,
transfers: [
{
destination_address: params.destination_address,
blinded_output_amount: params.output_to_revealed ? 0 : params.amount,
revealed_output_amount: params.output_to_revealed ? params.amount : 0,
output_memo: params.output_memo || null,
},
],
max_fee,
blinded_output_amount: params.output_to_revealed ? 0 : params.amount,
revealed_output_amount: params.output_to_revealed ? params.amount : 0,
output_memo: params.output_memo || null,
dry_run: params.dry_run,
};
return accountsStealthTransfer(transferRequest);
Expand Down
2 changes: 1 addition & 1 deletion bindings/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@tari-project/typescript-bindings",
"version": "1.18.2",
"version": "1.19.0",
Comment thread
sdbondi marked this conversation as resolved.
"description": "TypeScript types synchronized to the Tari Ootle Rust codebase",
"homepage": "https://github.com/tari-project/tari-ootle#readme",
"bugs": {
Expand Down
1 change: 1 addition & 0 deletions bindings/src/types/Instruction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export type Instruction =
| { ClaimValidatorFees: { address: string } }
| "DropAllProofsInWorkspace"
| { AssertBucketContains: { key: WorkspaceOffsetId; resource_address: ResourceAddress; min_amount: Amount } }
| { TakeFromBucket: { input_bucket: WorkspaceOffsetId; amount: Amount; output_bucket: number } }
| { PublishTemplate: { binary: Array<number> } }
| { AllocateAddress: { allocatable_type: AllocatableAddressType; workspace_id: number } }
| {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ import type { RistrettoPublicKeyBytes } from "../RistrettoPublicKeyBytes";
export type IndexerGetIdentityResponse = {
peer_id: string;
public_key: RistrettoPublicKeyBytes;
public_addresses: string[];
public_addresses: Array<string>;
};
11 changes: 11 additions & 0 deletions bindings/src/types/wallet-daemon-client/StealthTransfer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { Amount } from "../Amount";
import type { Memo } from "../Memo";
import type { OotleAddress } from "../OotleAddress";

export type StealthTransfer = {
destination_address: OotleAddress;
blinded_output_amount: Amount;
revealed_output_amount: Amount;
output_memo?: Memo | null;
};
Original file line number Diff line number Diff line change
@@ -1,19 +1,14 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { Amount } from "../Amount";
import type { ConfidentialTransferInputSelection } from "../ConfidentialTransferInputSelection";
import type { Memo } from "../Memo";
import type { OotleAddress } from "../OotleAddress";
import type { ResourceAddress } from "../ResourceAddress";
import type { ComponentAddressOrName } from "./ComponentAddressOrName";
import type { StealthTransfer } from "./StealthTransfer";

export type StealthTransferRequest = {
owner_account: ComponentAddressOrName;
input_selection: ConfidentialTransferInputSelection;
resource_address: ResourceAddress;
destination_address: OotleAddress;
transfers: Array<StealthTransfer>;
max_fee: number;
blinded_output_amount: Amount;
revealed_output_amount: Amount;
output_memo?: Memo | null;
dry_run: boolean;
};
1 change: 1 addition & 0 deletions bindings/src/wallet-daemon-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export * from "./types/wallet-daemon-client/MintFaucetNftRequest";
export * from "./types/wallet-daemon-client/AuthLoginDenyRequest";
export * from "./types/wallet-daemon-client/PublishTemplateRequest";
export * from "./types/wallet-daemon-client/TransactionSubmitResponse";
export * from "./types/wallet-daemon-client/StealthTransfer";
export * from "./types/wallet-daemon-client/ProofsGenerateResponse";
export * from "./types/wallet-daemon-client/TransactionSubmitManifestResponse";
export * from "./types/wallet-daemon-client/ListNftsResponse";
Expand Down
2 changes: 1 addition & 1 deletion clients/javascript/wallet_daemon_client/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@tari-project/wallet_jrpc_client",
"version": "1.9.3",
"version": "1.10.0",
Comment thread
sdbondi marked this conversation as resolved.
"description": "Tari wallet JSON-RPC client library",
"homepage": "https://github.com/tari-project/tari-ootle#readme",
"bugs": {
Expand Down
10 changes: 8 additions & 2 deletions clients/wallet_daemon_client/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1061,14 +1061,20 @@ pub struct StealthTransferRequest {
pub owner_account: ComponentAddressOrName,
pub input_selection: ConfidentialTransferInputSelection,
pub resource_address: ResourceAddress,
pub destination_address: OotleAddress,
pub transfers: Vec<StealthTransfer>,
#[cfg_attr(feature = "ts", ts(type = "number"))]
pub max_fee: u64,
pub dry_run: bool,
}

#[derive(Debug, Clone, Deserialize, Serialize)]
#[cfg_attr(feature = "ts", derive(ts_rs::TS), ts(export, export_to = "wallet-daemon-client/"))]
pub struct StealthTransfer {
pub destination_address: OotleAddress,
pub blinded_output_amount: Amount,
pub revealed_output_amount: Amount,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub output_memo: Option<Memo>,
pub dry_run: bool,
}

#[derive(Debug, Clone, Deserialize, Serialize)]
Expand Down
14 changes: 12 additions & 2 deletions crates/engine/src/runtime/impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1950,7 +1950,7 @@ impl<TTemplateProvider: TemplateProvider<Template = LoadedTemplate>> RuntimeInte
self.tracker.write_with(|state| {
let bucket = state.get_bucket_mut(bucket_id)?;
let resource = bucket.take(amount)?;
let bucket_id = state.id_provider()?.new_bucket_id();
let bucket_id = state.new_bucket_id();
state.new_bucket(bucket_id, resource)?;
Ok(InvokeResult::encode(&bucket_id)?)
})
Expand Down Expand Up @@ -2244,7 +2244,7 @@ impl<TTemplateProvider: TemplateProvider<Template = LoadedTemplate>> RuntimeInte
debug!(target: LOG_TARGET, "Workspace invoke: {:?}", action,);

match action {
// Basically names an output on the workspace so that you can refer to it as an
// Names an output on the workspace so that you can refer to it as an
// Arg::Variable
WorkspaceAction::PutLastInstructionOutput => {
let key = args.assert_one_arg()?;
Expand Down Expand Up @@ -2694,6 +2694,16 @@ impl<TTemplateProvider: TemplateProvider<Template = LoadedTemplate>> RuntimeInte
})
}

fn put_on_workspace(&self, id: WorkspaceId, value: IndexedValue) -> Result<(), RuntimeError> {
self.invoke_modules_on_runtime_call("put_on_workspace")?;

self.validate_return_value(&value)?;

self.tracker
.with_workspace_mut(|workspace| workspace.insert(id, value))?;
Ok(())
}

fn signature_invoke(&self, action: SignatureAction, args: EngineArgs) -> Result<InvokeResult, RuntimeError> {
self.invoke_modules_on_runtime_call("signature_invoke")?;

Expand Down
1 change: 1 addition & 0 deletions crates/engine/src/runtime/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ pub trait RuntimeInterface: Send + Sync {
fn push_call_frame(&self, frame: PushCallFrame) -> Result<(), RuntimeError>;
fn pop_call_frame(&self) -> Result<(), RuntimeError>;
fn publish_template(&self, template: Vec<u8>) -> Result<(), RuntimeError>;
fn put_on_workspace(&self, id: WorkspaceId, value: IndexedValue) -> Result<(), RuntimeError>;

fn signature_invoke(&self, action: SignatureAction, args: EngineArgs) -> Result<InvokeResult, RuntimeError>;

Expand Down
5 changes: 3 additions & 2 deletions crates/engine/src/runtime/working_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -397,9 +397,10 @@ impl WorkingState {
}

pub(super) fn validate_finalized(&self) -> Result<(), RuntimeError> {
if !self.buckets.is_empty() {
let dangling_bucket_count = self.buckets.iter().filter(|(_, b)| !b.amount().is_zero()).count();
if dangling_bucket_count > 0 {
return Err(TransactionCommitError::DanglingBuckets {
count: self.buckets.len(),
count: dangling_bucket_count,
}
.into());
}
Expand Down
20 changes: 19 additions & 1 deletion crates/engine/src/transaction/processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ use tari_ootle_common_types::services::template_provider::TemplateProvider;
use tari_template_abi::{FunctionDef, Type};
use tari_template_builtin::ACCOUNT_TEMPLATE_ADDRESS;
use tari_template_lib::{
args::{AllocateAddressResult, WorkspaceAction},
args::{AllocateAddressResult, BucketAction, BucketRef, WorkspaceAction},
auth::{ComponentAccessRules, OwnerRule},
invoke_args,
models::{Bucket, NonFungibleAddress, StealthTransferStatement},
Expand Down Expand Up @@ -316,6 +316,24 @@ impl<TTemplateProvider: TemplateProvider<Template = LoadedTemplate> + 'static> T
)?;
Ok(InstructionResult::empty())
},
Instruction::TakeFromBucket {
input_bucket,
amount,
output_bucket,
} => {
let item = runtime
.interface()
.workspace_invoke(WorkspaceAction::Get, invoke_args![input_bucket].into())?;
let bucket = runtime.interface().bucket_invoke(
BucketRef::Ref(item.decode()?),
BucketAction::Take,
invoke_args![amount].into(),
)?;
runtime
.interface()
.put_on_workspace(output_bucket, IndexedValue::from_value(bucket.into_value()?)?)?;
Ok(InstructionResult::empty())
},
Instruction::PublishTemplate { binary } => Self::publish_template(config, runtime, binary),
Instruction::AllocateAddress {
allocatable_type: substate_type,
Expand Down
52 changes: 52 additions & 0 deletions crates/engine/tests/account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -277,3 +277,55 @@ fn custom_access_rules() {
vec![user2_account_proof],
);
}

#[test]
fn take_from_bucket() {
let mut test = TemplateTest::new(Vec::<&str>::new());

let faucet_template = test.get_template_address("TestFaucet");
let (alice, _proof, _alice_sk) = test.create_empty_account();
let (bob, _proof, _bob_sk) = test.create_empty_account();

let initial_supply = Amount::from(1_000_000_000_000u64);
test.execute_expect_success(
Transaction::builder()
.allocate_component_address("faucet")
.call_function(faucet_template, "mint_with_opts", args![
initial_supply,
"faucet".to_string(),
Workspace("faucet"),
])
.call_method("faucet", "take_free_coins_custom", args![1000])
.put_last_instruction_output_on_workspace("free_coins")
.take_from_bucket("free_coins", 100, "foo_bucket")
// Take all to test what happens when free_coins is empty (should not fail due to dangling buckets)
.take_from_bucket("free_coins", 900, "bar_bucket")
.call_method(alice, "deposit", args![Workspace("foo_bucket")])
.call_method(bob, "deposit", args![Workspace("bar_bucket")])
.build_and_seal(test.secret_key()),
vec![test.owner_proof()],
);

let resources = test.read_only_state_store().get_all_resources().unwrap();
let faucet_resource = resources
.iter()
.find(|(_, r)| r.token_symbol() == Some("faucet"))
.map(|(addr, _)| *addr)
.unwrap();

let alice_acc = test.read_only_state_store().get_account(alice).unwrap();
let bob_acc = test.read_only_state_store().get_account(bob).unwrap();
let alice_balance = test
.read_only_state_store()
.get_vault(&alice_acc.get_vault_by_resource(&faucet_resource).unwrap().vault_id())
.unwrap()
.balance();
let bob_balance = test
.read_only_state_store()
.get_vault(&bob_acc.get_vault_by_resource(&faucet_resource).unwrap().vault_id())
.unwrap()
.balance();

assert_eq!(alice_balance, 100);
assert_eq!(bob_balance, 900);
}
Loading
Loading