From 96f1d5ce636bc288b619bc4066d3a0dcd0883b4c Mon Sep 17 00:00:00 2001 From: zackdilan Date: Wed, 24 Feb 2021 02:21:53 -0800 Subject: [PATCH 01/11] edited mismatched args --- bindings/python/examples/example.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/python/examples/example.py b/bindings/python/examples/example.py index 7bc4d3fd3..234c0fcac 100644 --- a/bindings/python/examples/example.py +++ b/bindings/python/examples/example.py @@ -30,7 +30,7 @@ def main(): print('get_addresses') address_changed_list = client.get_addresses( - seed=SEED, account_index=0, begin=0, end=10, get_all=True) + seed=SEED, account_index=0, input_range_begin=0, input_range_end=10, get_all=True) print(f'address_changed list: {address_changed_list}') # Get the (address, changed ) for the first found address From e62705db25421dc5a08de1892a9f3f830597b9ad Mon Sep 17 00:00:00 2001 From: Robin Chacko <50382476+zackdilan@users.noreply.github.com> Date: Wed, 24 Feb 2021 02:54:02 -0800 Subject: [PATCH 02/11] edited mismatched args (#353) Co-authored-by: zackdilan --- bindings/python/examples/example.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/python/examples/example.py b/bindings/python/examples/example.py index 7bc4d3fd3..234c0fcac 100644 --- a/bindings/python/examples/example.py +++ b/bindings/python/examples/example.py @@ -30,7 +30,7 @@ def main(): print('get_addresses') address_changed_list = client.get_addresses( - seed=SEED, account_index=0, begin=0, end=10, get_all=True) + seed=SEED, account_index=0, input_range_begin=0, input_range_end=10, get_all=True) print(f'address_changed list: {address_changed_list}') # Get the (address, changed ) for the first found address From 126d9b3ffb5281e948dcd843e76200f9ee524f9d Mon Sep 17 00:00:00 2001 From: Thoralf-M <46689931+Thoralf-M@users.noreply.github.com> Date: Wed, 24 Feb 2021 12:00:18 +0100 Subject: [PATCH 03/11] use latest commits (#356) --- iota-client/Cargo.toml | 6 +++--- iota-core/Cargo.toml | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/iota-client/Cargo.toml b/iota-client/Cargo.toml index 9c3e7a5c5..891a4cf86 100644 --- a/iota-client/Cargo.toml +++ b/iota-client/Cargo.toml @@ -18,9 +18,9 @@ name = "iota_client" # bee-pow = { git = "https://github.com/iotaledger/bee.git", branch = "chrysalis-pt-2" } # bee-common-derive = { git = "https://github.com/iotaledger/bee.git", branch = "dev" } # bee-crypto = { git = "https://github.com/iotaledger/bee.git", branch = "dev" } -bee-rest-api = { git = "https://github.com/iotaledger/bee.git", rev = "8ee15fbc064b2aa1a506fa7ac5d88b5073e5d0f7" } -bee-message = { git = "https://github.com/iotaledger/bee.git", rev = "8ee15fbc064b2aa1a506fa7ac5d88b5073e5d0f7" } -bee-pow = { git = "https://github.com/iotaledger/bee.git", rev = "8ee15fbc064b2aa1a506fa7ac5d88b5073e5d0f7" } +bee-rest-api = { git = "https://github.com/iotaledger/bee.git", rev = "8baba875c0f07e62f159f264e8edf1667e013433" } +bee-message = { git = "https://github.com/iotaledger/bee.git", rev = "8baba875c0f07e62f159f264e8edf1667e013433" } +bee-pow = { git = "https://github.com/iotaledger/bee.git", rev = "8baba875c0f07e62f159f264e8edf1667e013433" } bee-common-derive = { git = "https://github.com/iotaledger/bee.git", rev = "c42171ff33c80cc2efb183e244dc79b7f58d9ac4" } bee-crypto = { git = "https://github.com/iotaledger/bee.git", rev = "c42171ff33c80cc2efb183e244dc79b7f58d9ac4" } iota-crypto = { git = "https://github.com/iotaledger/crypto.rs.git", rev = "6e67b652dd55df05877f575b9a09ccb5a7006694", features = ["ed25519", "random"]} diff --git a/iota-core/Cargo.toml b/iota-core/Cargo.toml index d43663375..4954bdc0b 100644 --- a/iota-core/Cargo.toml +++ b/iota-core/Cargo.toml @@ -12,8 +12,8 @@ homepage = "https://iota.org" name = "iota" [dependencies] -bee-message = { git = "https://github.com/iotaledger/bee.git", rev = "8ee15fbc064b2aa1a506fa7ac5d88b5073e5d0f7" } -bee-pow = { git = "https://github.com/iotaledger/bee.git", rev = "8ee15fbc064b2aa1a506fa7ac5d88b5073e5d0f7" } +bee-message = { git = "https://github.com/iotaledger/bee.git", rev = "8baba875c0f07e62f159f264e8edf1667e013433" } +bee-pow = { git = "https://github.com/iotaledger/bee.git", rev = "8baba875c0f07e62f159f264e8edf1667e013433" } bee-common = { git = "https://github.com/iotaledger/bee.git", rev = "c42171ff33c80cc2efb183e244dc79b7f58d9ac4" } # bee-common = { git = "https://github.com/iotaledger/bee.git", branch = "dev" } # bee-message = { git = "https://github.com/iotaledger/bee.git", branch = "chrysalis-pt-2" } From a227c29eeadec893ebfd746f76d0d83afe054933 Mon Sep 17 00:00:00 2001 From: Thoralf-M Date: Wed, 24 Feb 2021 12:23:25 +0100 Subject: [PATCH 04/11] use blake2b from crypto.rs --- iota-client/Cargo.toml | 3 +-- iota-client/src/api/address.rs | 14 +++----------- iota-client/src/client.rs | 19 +++++++------------ 3 files changed, 11 insertions(+), 25 deletions(-) diff --git a/iota-client/Cargo.toml b/iota-client/Cargo.toml index 891a4cf86..be853ef06 100644 --- a/iota-client/Cargo.toml +++ b/iota-client/Cargo.toml @@ -23,14 +23,13 @@ bee-message = { git = "https://github.com/iotaledger/bee.git", rev = "8baba875c0 bee-pow = { git = "https://github.com/iotaledger/bee.git", rev = "8baba875c0f07e62f159f264e8edf1667e013433" } bee-common-derive = { git = "https://github.com/iotaledger/bee.git", rev = "c42171ff33c80cc2efb183e244dc79b7f58d9ac4" } bee-crypto = { git = "https://github.com/iotaledger/bee.git", rev = "c42171ff33c80cc2efb183e244dc79b7f58d9ac4" } -iota-crypto = { git = "https://github.com/iotaledger/crypto.rs.git", rev = "6e67b652dd55df05877f575b9a09ccb5a7006694", features = ["ed25519", "random"]} +iota-crypto = { git = "https://github.com/iotaledger/crypto.rs", rev = "09ff1a94d6a87838589ccf1b874cfa3283a00f26", features = ["blake2b", "ed25519", "random"] } slip10 = "0.4" reqwest = { version = "0.11", features = ["json", "rustls-tls", "blocking"], default-features = false } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0.58" chrono = { version = "0.4", features = ["serde"] } hex = "0.4.2" -blake2 = "0.9" tokio = { version = "1.1", features = ["macros", "sync", "rt-multi-thread"] } thiserror = "1.0" num_cpus = "1.13" diff --git a/iota-client/src/api/address.rs b/iota-client/src/api/address.rs index c2496d384..531f22cbe 100644 --- a/iota-client/src/api/address.rs +++ b/iota-client/src/api/address.rs @@ -4,11 +4,8 @@ use crate::{Client, Error, Result, Seed}; use bee_message::prelude::{Address, Bech32Address, Ed25519Address}; -use blake2::{ - digest::{Update, VariableOutput}, - VarBlake2b, -}; use core::convert::TryInto; +use crypto::hashes::{blake2b::Blake2b256, Digest}; use slip10::BIP32Path; use std::ops::Range; @@ -110,17 +107,12 @@ fn generate_address(seed: &Seed, path: &mut BIP32Path, index: usize, internal: b let public_key = seed.generate_private_key(path)?.public_key().to_compressed_bytes(); // Hash the public key to get the address - let mut hasher = VarBlake2b::new(32).unwrap(); - hasher.update(public_key); - let mut result: [u8; 32] = [0; 32]; - hasher.finalize_variable(|res| { - result = res.try_into().expect("Invalid Length of Public Key"); - }); + let result = Blake2b256::digest(&public_key); path.pop(); path.pop(); - Ok(Address::Ed25519(Ed25519Address::new(result))) + Ok(Address::Ed25519(Ed25519Address::new(result.try_into().unwrap()))) } /// Function to find the index and public or internal type of an Bech32 encoded address diff --git a/iota-client/src/client.rs b/iota-client/src/client.rs index 3bdf6bb1a..d4057e6b0 100644 --- a/iota-client/src/client.rs +++ b/iota-client/src/client.rs @@ -22,11 +22,8 @@ use bee_rest_api::{ }, types::{MessageDto, PeerDto}, }; +use crypto::hashes::{blake2b::Blake2b256, Digest}; -use blake2::{ - digest::{Update, VariableOutput}, - VarBlake2b, -}; #[cfg(feature = "mqtt")] use paho_mqtt::Client as MqttClient; use reqwest::{IntoUrl, Url}; @@ -870,12 +867,10 @@ impl Client { } /// Hash the network id str from the nodeinfo to an u64 for the messageBuilder -pub fn hash_network(network_id: &str) -> u64 { - let mut hasher = VarBlake2b::new(32).unwrap(); - hasher.update(network_id.as_bytes()); - let mut result: [u8; 32] = [0; 32]; - hasher.finalize_variable(|res| { - result = res.try_into().unwrap(); - }); - u64::from_le_bytes(result[0..8].try_into().unwrap()) +pub fn hash_network(network_id_string: &str) -> u64 { + u64::from_le_bytes( + Blake2b256::digest(network_id_string.as_bytes())[0..8] + .try_into() + .unwrap(), + ) } From 83a028990ea6e28c145061a61402bc8acb7a5a59 Mon Sep 17 00:00:00 2001 From: Thoralf-M Date: Wed, 24 Feb 2021 12:29:46 +0100 Subject: [PATCH 05/11] IRICIDE --- bindings/python/native/src/client/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/python/native/src/client/mod.rs b/bindings/python/native/src/client/mod.rs index 9d2c97cf5..f06df95cb 100644 --- a/bindings/python/native/src/client/mod.rs +++ b/bindings/python/native/src/client/mod.rs @@ -21,7 +21,7 @@ pub struct Client { pub client: RustClient, } -/// An instance of the client using IRI URI. +/// An instance of the client using IOTA node URI. #[pymethods] impl Client { #[new] From 51e635e326755572167cbb675bb96444809077a4 Mon Sep 17 00:00:00 2001 From: Thoralf-M Date: Wed, 24 Feb 2021 13:05:53 +0100 Subject: [PATCH 06/11] refactor transaction example and add send_all --- examples/Cargo.toml | 4 ++ examples/send_all.rs | 54 +++++++++++++++++++++++ examples/transaction.rs | 95 +++++++++++++++-------------------------- 3 files changed, 92 insertions(+), 61 deletions(-) create mode 100644 examples/send_all.rs diff --git a/examples/Cargo.toml b/examples/Cargo.toml index 9e1622b7d..be6a88244 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -74,3 +74,7 @@ path = "peers.rs" [[example]] name = "message_time" path = "message_time.rs" + +[[example]] +name = "send_all" +path = "send_all.rs" diff --git a/examples/send_all.rs b/examples/send_all.rs new file mode 100644 index 000000000..494d99d1a --- /dev/null +++ b/examples/send_all.rs @@ -0,0 +1,54 @@ +// Copyright 2021 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +//! cargo run --example send_all --release +use iota::{client::Result, Client, MessageId, Seed}; +use std::time::Duration; +use tokio::time::sleep; +extern crate dotenv; +use dotenv::dotenv; +use std::env; + +/// In this example, we get the balance of the first account of the seed and send everything + +#[tokio::main] +async fn main() -> Result<()> { + let iota = Client::builder() // Crate a client instance builder + .with_node("http://api.lb-0.testnet.chrysalis2.com")? + .finish() + .await?; + + // Insert your seed in the .env. Since the output amount cannot be zero. The seed must contain non-zero balance. + println!("This example uses dotenv, which is not safe for use in production."); + dotenv().ok(); + let seed_1 = Seed::from_bytes(&hex::decode(env::var("NONSECURE_USE_OF_DEVELOPMENT_SEED_1").unwrap())?)?; + + let total_balance = iota.get_balance(&seed_1).finish().await?; + let message = iota + .message() + .with_seed(&seed_1) + .with_output( + &"atoi1qrk69lxuxljdgeqt7tucvtdfk3hrvrly7rzz65w57te6drf3expsj3gqrf9".into(), + total_balance, + )? + .finish() + .await?; + println!( + "Transaction sent: https://explorer.iota.org/chrysalis/message/{}", + message.id().0 + ); + reattach_promote_until_confirmed(message.id().0, &iota).await; + Ok(()) +} + +async fn reattach_promote_until_confirmed(message_id: MessageId, iota: &Client) { + while let Ok(metadata) = iota.get_message().metadata(&message_id).await { + if let Some(state) = metadata.ledger_inclusion_state { + println!("Leder inclusion state: {:?}", state); + break; + } else if let Ok(msg_id) = iota.reattach(&message_id).await { + println!("Reattached or promoted {}", msg_id.0); + } + sleep(Duration::from_secs(5)).await; + } +} diff --git a/examples/transaction.rs b/examples/transaction.rs index 60101face..41b795ca4 100644 --- a/examples/transaction.rs +++ b/examples/transaction.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 //! cargo run --example transaction --release -use iota::{Client, MessageId, Seed}; +use iota::{client::Result, Client, MessageId, Seed}; use std::time::Duration; use tokio::time::sleep; extern crate dotenv; @@ -21,115 +21,88 @@ use std::env; /// /// /// Then we send 6_000_000 tokens from the second seed to the first one -/// to addresses "atoi1qpnrumvaex24dy0duulp4q07lpa00w20ze6jfd0xly422kdcjxzakzsz5kf" and -/// "atoi1qzu7dnlfld2p0rhld20nr6axdnl0katmwu59fprwcnahglmnvgpwjsc20jg", and check the ledger -/// inclusion state, which should be "included". +/// to addresses "atoi1qpnrumvaex24dy0duulp4q07lpa00w20ze6jfd0xly422kdcjxzakzsz5kf" (index 1) and +/// "atoi1qz4sfmp605vnj6fxt0sf0cwclffw5hpxjqkf6fthyd74r9nmmu337m3lwl2" (index 2), and check the ledger +/// inclusion state, which should be "Some(Included)". #[tokio::main] -async fn main() { +async fn main() -> Result<()> { + let explorer_url = "https://explorer.iota.org/chrysalis/message/"; let iota = Client::builder() // Crate a client instance builder - .with_node("http://localhost:14265") // Insert the node here - .unwrap() + .with_node("http://api.lb-0.testnet.chrysalis2.com")? // Insert the node here .with_node_sync_disabled() .finish() - .await - .unwrap(); + .await?; // Insert your seed in the .env. Since the output amount cannot be zero. The seed must contain non-zero balance. // First address from the seed in the .env is iot1qxt0nhsf38nh6rs4p6zs5knqp6psgha9wsv74uajqgjmwc75ugupxgecea4 println!("This example uses dotenv, which is not safe for use in production."); dotenv().ok(); - let seed = - Seed::from_bytes(&hex::decode(env::var("NONSECURE_USE_OF_DEVELOPMENT_SEED_1").unwrap()).unwrap()).unwrap(); + let seed_1 = Seed::from_bytes(&hex::decode(env::var("NONSECURE_USE_OF_DEVELOPMENT_SEED_1").unwrap())?)?; + let seed_2 = Seed::from_bytes(&hex::decode(env::var("NONSECURE_USE_OF_DEVELOPMENT_SEED_2").unwrap())?)?; let message = iota .message() - .with_seed(&seed) + .with_seed(&seed_1) // Insert the output address and amount to spent. The amount cannot be zero. .with_output( - &"atoi1qzj8s3kpacr6kmh05sxul4zp0xqulzn2vy9rznqj6rrc4nwd304pk6w523x".into(), + &iota.get_addresses(&seed_2).with_range(0..1).finish().await?[0], 3_000_000, - ) - .unwrap() + )? .finish() - .await - .unwrap(); + .await?; - println!( - "First transaction sent: http://127.0.0.1:14265/api/v1/messages/{}", - message.id().0 - ); + println!("First transaction sent: {}{}", explorer_url, message.id().0); reattach_promote_until_confirmed(message.id().0, &iota).await; let message = iota .message() - .with_seed(&seed) - // Insert the output address and amount to spent. The amount cannot be zero. + .with_seed(&seed_1) .with_output( - &"atoi1qzu7dnlfld2p0rhld20nr6axdnl0katmwu59fprwcnahglmnvgpwjsc20jg".into(), + &iota.get_addresses(&seed_2).with_range(1..2).finish().await?[0], 3_000_000, - ) - .unwrap() + )? .finish() - .await - .unwrap(); + .await?; - println!( - "Second transaction sent: http://127.0.0.1:14265/api/v1/messages/{}", - message.id().0 - ); + println!("Second transaction sent: {}{}", explorer_url, message.id().0); reattach_promote_until_confirmed(message.id().0, &iota).await; let message = iota .message() - .with_seed(&seed) - // Insert the output address and amount to spent. The amount cannot be zero. + .with_seed(&seed_1) .with_output( - &"atoi1qz0vue67w2e2wjk9jh07s7wfgxmsxgy9ssctn3nntyf9uqd6qs3zsp0k73u".into(), + &iota.get_addresses(&seed_2).with_range(2..3).finish().await?[0], 3_000_000, - ) - .unwrap() + )? .finish() - .await - .unwrap(); - println!( - "Third transaction sent: http://127.0.0.1:14265/api/v1/messages/{}", - message.id().0 - ); + .await?; + println!("Third transaction sent: {}{}", explorer_url, message.id().0); reattach_promote_until_confirmed(message.id().0, &iota).await; - let seed = - Seed::from_bytes(&hex::decode(env::var("NONSECURE_USE_OF_DEVELOPMENT_SEED_2").unwrap()).unwrap()).unwrap(); - let message = iota .message() - .with_seed(&seed) - // Insert the output address and amount to spent. The amount cannot be zero. + .with_seed(&seed_2) // Note that we can transfer to multiple outputs by using the `SendTransactionBuilder` .with_output( - &"atoi1qzj8s3kpacr6kmh05sxul4zp0xqulzn2vy9rznqj6rrc4nwd304pk6w523x".into(), + &iota.get_addresses(&seed_1).with_range(1..2).finish().await?[0], 3_000_000, - ) - .unwrap() + )? .with_output( - &"atoi1qzu7dnlfld2p0rhld20nr6axdnl0katmwu59fprwcnahglmnvgpwjsc20jg".into(), + &iota.get_addresses(&seed_1).with_range(2..3).finish().await?[0], 3_000_000, - ) - .unwrap() + )? .finish() - .await - .unwrap(); + .await?; - println!( - "Last transaction sent: http://127.0.0.1:14265/api/v1/messages/{}", - message.id().0 - ); + println!("Last transaction sent: {}{}", explorer_url, message.id().0); reattach_promote_until_confirmed(message.id().0, &iota).await; let message_metadata = iota.get_message().metadata(&message.id().0).await; println!( "The ledgerInclusionState: {:?}", - message_metadata.unwrap().ledger_inclusion_state + message_metadata?.ledger_inclusion_state ); + Ok(()) } async fn reattach_promote_until_confirmed(message_id: MessageId, iota: &Client) { From 9410e2c71624a7ca1512378ede452884db1e522e Mon Sep 17 00:00:00 2001 From: Thoralf-M Date: Wed, 24 Feb 2021 17:18:42 +0100 Subject: [PATCH 07/11] post binary message instead of json --- iota-client/Cargo.toml | 1 + iota-client/src/client.rs | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/iota-client/Cargo.toml b/iota-client/Cargo.toml index be853ef06..4e8053932 100644 --- a/iota-client/Cargo.toml +++ b/iota-client/Cargo.toml @@ -21,6 +21,7 @@ name = "iota_client" bee-rest-api = { git = "https://github.com/iotaledger/bee.git", rev = "8baba875c0f07e62f159f264e8edf1667e013433" } bee-message = { git = "https://github.com/iotaledger/bee.git", rev = "8baba875c0f07e62f159f264e8edf1667e013433" } bee-pow = { git = "https://github.com/iotaledger/bee.git", rev = "8baba875c0f07e62f159f264e8edf1667e013433" } +bee-common = { git = "https://github.com/iotaledger/bee.git", branch = "dev" } bee-common-derive = { git = "https://github.com/iotaledger/bee.git", rev = "c42171ff33c80cc2efb183e244dc79b7f58d9ac4" } bee-crypto = { git = "https://github.com/iotaledger/bee.git", rev = "c42171ff33c80cc2efb183e244dc79b7f58d9ac4" } iota-crypto = { git = "https://github.com/iotaledger/crypto.rs", rev = "09ff1a94d6a87838589ccf1b874cfa3283a00f26", features = ["blake2b", "ed25519", "random"] } diff --git a/iota-client/src/client.rs b/iota-client/src/client.rs index d4057e6b0..72a2bc269 100644 --- a/iota-client/src/client.rs +++ b/iota-client/src/client.rs @@ -11,6 +11,7 @@ use crate::{ parse_response, Seed, }; +use bee_common::packable::Packable; use bee_message::prelude::{Bech32Address, Message, MessageBuilder, MessageId, UTXOInput}; use bee_pow::providers::{MinerBuilder, Provider as PowProvider, ProviderBuilder as PowProviderBuilder}; use bee_rest_api::{ @@ -566,6 +567,42 @@ impl Client { let path = "api/v1/messages"; url.set_path(path); + let timeout = if self.get_local_pow() { + self.get_timeout(Api::PostMessage) + } else { + self.get_timeout(Api::PostMessageWithRemotePow) + }; + let resp = self + .client + .post(url) + .timeout(timeout) + .body(message.pack_new()) + .send() + .await?; + #[derive(Debug, Serialize, Deserialize)] + struct MessageIdResponseWrapper { + data: MessageIdWrapper, + } + #[derive(Debug, Serialize, Deserialize)] + struct MessageIdWrapper { + #[serde(rename = "messageId")] + message_id: String, + } + log_request!("POST", path, resp); + parse_response!(resp, 201 => { + let message_id = resp.json::().await?; + let mut message_id_bytes = [0u8; 32]; + hex::decode_to_slice(message_id.data.message_id, &mut message_id_bytes)?; + Ok(MessageId::from(message_id_bytes)) + }) + } + + /// POST JSON to /api/v1/messages endpoint + pub async fn post_message_json(&self, message: &Message) -> Result { + let mut url = self.get_node()?; + let path = "api/v1/messages"; + url.set_path(path); + let timeout = if self.get_local_pow() { self.get_timeout(Api::PostMessage) } else { From 8b40a80c2c1d06a703778b7a3c85924447ecd898 Mon Sep 17 00:00:00 2001 From: zackdilan Date: Thu, 25 Feb 2021 03:24:59 -0800 Subject: [PATCH 08/11] updated README according new updated code --- bindings/python/README.md | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/bindings/python/README.md b/bindings/python/README.md index 750203dfb..df36b0e68 100644 --- a/bindings/python/README.md +++ b/bindings/python/README.md @@ -35,24 +35,24 @@ LOCAL_NODE_URL = "http://0.0.0.0:14265" # USE THIS INSTEAD SEED = os.getenv('MY_IOTA_SEED') -EMPTY_ADDRESS = "iot1qxgamuxntdxq06q4zpmvmdnrerj2f94058ge3flfyx567unw25amvr978uw" +EMPTY_ADDRESS = "atoi1qzt0nhsf38nh6rs4p6zs5knqp6psgha9wsv74uajqgjmwc75ugupx3y7x0r" client = iota_client.Client( node=LOCAL_NODE_URL, node_sync_disabled=True) def main(): print('get_health()') - print(f'health: client.get_health()') + print(f'health: {client.get_health()}') print('get_info()') - print(f'node_info: client.get_info()') + print(f'node_info: {client.get_info()}') print('get_tips()') - print(f'tips: client.get_tips()') + print(f'tips: {client.get_tips()}') print('get_addresses') address_changed_list = client.get_addresses( - seed=SEED, account_index=0, begin=0, end=10, get_all=True) + seed=SEED, account_index=0, input_range_begin=0, input_range_end=10, get_all=True) print(f'address_changed list: {address_changed_list}') # Get the (address, changed ) for the first found address @@ -68,7 +68,7 @@ def main(): print(f'message() 100 tokens to address {EMPTY_ADDRESS}') message_id = client.message( - seed=SEED, outputs=[{'address': EMPTY_ADDRESS, 'amount': 100}]) + seed=SEED, outputs=[{'address': EMPTY_ADDRESS, 'amount': 100}])['message_id'] print(f'Token sent with message_id: {message_id}') print(f'Please check http://127.0.0.1:14265/api/v1/messages/{message_id}') @@ -82,7 +82,10 @@ def main(): print(f'get_message_raw() for message_id {message_id}') message_raw = client.get_message_raw(message_id) - print(f"message_raw: {bytearray(message_raw, 'utf-8')}") + print(f"raw_data = {message_raw.encode('utf-8')}") + print( + f"Note the raw data is exactly the same from http://127.0.0.1:14265/api/v1/messages/{message_id}/raw") + print(', which is not utf-8 format. The utf-8 format here is just for ease of demonstration') print(f'get_message_children() for message_id {message_id}') children = client.get_message_children(message_id) @@ -90,7 +93,16 @@ def main(): print(f'message() Indexation') message_id_indexation = client.message( - index="Hello", data=bytes("Tangle", 'utf-8')) + index="Hello", data=[84, 97, 110, 103, 108, 101]) + print(f'Indexation sent with message_id: {message_id_indexation}') + print( + f'Please check http://127.0.0.1:14265/api/v1/messages/{message_id_indexation}') + + # Note that in rust we need to specify the parameter type explicitly, so if the user wants + # to use the utf-8 string as the data, then the `data_str` field can be used. + print(f'message() Indexation') + message_id_indexation = client.message( + index="Hi", data_str="Tangle") print(f'Indexation sent with message_id: {message_id_indexation}') print( f'Please check http://127.0.0.1:14265/api/v1/messages/{message_id_indexation}') @@ -121,6 +133,7 @@ def main(): if __name__ == "__main__": main() + ``` ## API Reference @@ -875,4 +888,4 @@ metrics_dto = { 'sent_heartbeats': int, 'dropped_packets': int, } -``` \ No newline at end of file +``` From 95d098830770c80d19d9d99bcae4093635b768b8 Mon Sep 17 00:00:00 2001 From: Thoralf-M Date: Thu, 25 Feb 2021 17:13:04 +0100 Subject: [PATCH 09/11] fix get_balance and address_index with initial_address_index, add example --- examples/Cargo.toml | 4 ++ examples/send_all.rs | 9 ++-- examples/split_all.rs | 70 ++++++++++++++++++++++++++ iota-client/Cargo.toml | 6 +-- iota-client/src/api/balance.rs | 19 +++---- iota-client/src/api/message_builder.rs | 2 +- iota-core/Cargo.toml | 4 +- 7 files changed, 96 insertions(+), 18 deletions(-) create mode 100644 examples/split_all.rs diff --git a/examples/Cargo.toml b/examples/Cargo.toml index be6a88244..955713f8e 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -78,3 +78,7 @@ path = "message_time.rs" [[example]] name = "send_all" path = "send_all.rs" + +[[example]] +name = "split_all" +path = "split_all.rs" diff --git a/examples/send_all.rs b/examples/send_all.rs index 494d99d1a..6c7ec1c16 100644 --- a/examples/send_all.rs +++ b/examples/send_all.rs @@ -10,6 +10,7 @@ use dotenv::dotenv; use std::env; /// In this example, we get the balance of the first account of the seed and send everything +// Todo: automatically detect amount of inputs and if > 127 create multiple transactions #[tokio::main] async fn main() -> Result<()> { @@ -21,16 +22,18 @@ async fn main() -> Result<()> { // Insert your seed in the .env. Since the output amount cannot be zero. The seed must contain non-zero balance. println!("This example uses dotenv, which is not safe for use in production."); dotenv().ok(); - let seed_1 = Seed::from_bytes(&hex::decode(env::var("NONSECURE_USE_OF_DEVELOPMENT_SEED_1").unwrap())?)?; + let seed_1 = Seed::from_bytes(&hex::decode(env::var("NONSECURE_USE_OF_DEVELOPMENT_SEED_2").unwrap())?)?; - let total_balance = iota.get_balance(&seed_1).finish().await?; + let total_balance = iota.get_balance(&seed_1).with_initial_address_index(0).finish().await?; + println!("total_balance {}", total_balance); let message = iota .message() .with_seed(&seed_1) .with_output( - &"atoi1qrk69lxuxljdgeqt7tucvtdfk3hrvrly7rzz65w57te6drf3expsj3gqrf9".into(), + &"atoi1qzt0nhsf38nh6rs4p6zs5knqp6psgha9wsv74uajqgjmwc75ugupx3y7x0r".into(), total_balance, )? + .with_initial_address_index(0) .finish() .await?; println!( diff --git a/examples/split_all.rs b/examples/split_all.rs new file mode 100644 index 000000000..1a4618c94 --- /dev/null +++ b/examples/split_all.rs @@ -0,0 +1,70 @@ +// Copyright 2021 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +//! cargo run --example split_all --release +use iota::{client::Result, Client, MessageId, Seed}; +use std::time::Duration; +use tokio::time::sleep; +extern crate dotenv; +use dotenv::dotenv; +use std::env; + +/// In this example, we get the balance of the first account of the seed and send everything splitted to the second seed + +#[tokio::main] +async fn main() -> Result<()> { + let iota = Client::builder() // Crate a client instance builder + .with_node("http://api.lb-0.testnet.chrysalis2.com")? + .finish() + .await?; + + // Insert your seed in the .env. Since the output amount cannot be zero. The seed must contain non-zero balance. + println!("This example uses dotenv, which is not safe for use in production."); + dotenv().ok(); + let seed_1 = Seed::from_bytes(&hex::decode(env::var("NONSECURE_USE_OF_DEVELOPMENT_SEED_1").unwrap())?)?; + let seed_2 = Seed::from_bytes(&hex::decode(env::var("NONSECURE_USE_OF_DEVELOPMENT_SEED_2").unwrap())?)?; + + let total_balance = iota.get_balance(&seed_1).finish().await?; + let mut available = total_balance.clone(); + println!("total_balance {}", total_balance); + let addresses_from_seed_2 = iota + .get_addresses(&seed_2) + .with_range(0..available as usize / 1_000_000) + .finish() + .await?; + let mut message_builder = iota.message().with_seed(&seed_1); + for i in 0..total_balance / 1_000_000 { + let mut amount = 1_000_000; + // Don't add more than we have or is allowed; 1 less here for remaining iotas + if available <= 0 || i > 125 { + break; + } + available -= amount; + // Add last amount so we don't create dust + if available < amount { + amount += available; + available = 0; + } + message_builder = message_builder.with_output(&addresses_from_seed_2[i as usize], amount)?; + } + + let message = message_builder.finish().await?; + println!( + "Transaction sent: https://explorer.iota.org/chrysalis/message/{}", + message.id().0 + ); + reattach_promote_until_confirmed(message.id().0, &iota).await; + Ok(()) +} + +async fn reattach_promote_until_confirmed(message_id: MessageId, iota: &Client) { + while let Ok(metadata) = iota.get_message().metadata(&message_id).await { + if let Some(state) = metadata.ledger_inclusion_state { + println!("Leder inclusion state: {:?}", state); + break; + } else if let Ok(msg_id) = iota.reattach(&message_id).await { + println!("Reattached or promoted {}", msg_id.0); + } + sleep(Duration::from_secs(5)).await; + } +} diff --git a/iota-client/Cargo.toml b/iota-client/Cargo.toml index 4e8053932..9a967ca0c 100644 --- a/iota-client/Cargo.toml +++ b/iota-client/Cargo.toml @@ -18,9 +18,9 @@ name = "iota_client" # bee-pow = { git = "https://github.com/iotaledger/bee.git", branch = "chrysalis-pt-2" } # bee-common-derive = { git = "https://github.com/iotaledger/bee.git", branch = "dev" } # bee-crypto = { git = "https://github.com/iotaledger/bee.git", branch = "dev" } -bee-rest-api = { git = "https://github.com/iotaledger/bee.git", rev = "8baba875c0f07e62f159f264e8edf1667e013433" } -bee-message = { git = "https://github.com/iotaledger/bee.git", rev = "8baba875c0f07e62f159f264e8edf1667e013433" } -bee-pow = { git = "https://github.com/iotaledger/bee.git", rev = "8baba875c0f07e62f159f264e8edf1667e013433" } +bee-rest-api = { git = "https://github.com/iotaledger/bee.git", rev = "ce3bd4e1b1ba423c8268e435dcc98c90c397379e" } +bee-message = { git = "https://github.com/iotaledger/bee.git", rev = "ce3bd4e1b1ba423c8268e435dcc98c90c397379e" } +bee-pow = { git = "https://github.com/iotaledger/bee.git", rev = "ce3bd4e1b1ba423c8268e435dcc98c90c397379e" } bee-common = { git = "https://github.com/iotaledger/bee.git", branch = "dev" } bee-common-derive = { git = "https://github.com/iotaledger/bee.git", rev = "c42171ff33c80cc2efb183e244dc79b7f58d9ac4" } bee-crypto = { git = "https://github.com/iotaledger/bee.git", rev = "c42171ff33c80cc2efb183e244dc79b7f58d9ac4" } diff --git a/iota-client/src/api/balance.rs b/iota-client/src/api/balance.rs index 04b49b551..e10d0a5f2 100644 --- a/iota-client/src/api/balance.rs +++ b/iota-client/src/api/balance.rs @@ -42,6 +42,8 @@ impl<'a> GetBalanceBuilder<'a> { // get account balance and check with value let mut balance = 0; + // Count addresses with zero balances in a row + let mut found_zero_balance = 0; loop { let addresses = self .client @@ -51,23 +53,22 @@ impl<'a> GetBalanceBuilder<'a> { .get_all() .await?; - // TODO we assume all addresses are unspent and valid if balance > 0 - let mut found_zero_balance = false; for (address, _) in addresses { let address_balance = self.client.get_address().balance(&address).await?; match address_balance.balance { - 0 => { - found_zero_balance = true; - break; + 0 => found_zero_balance += 1, + _ => { + balance += address_balance.balance; + // reset + found_zero_balance = 0; } - _ => balance += address_balance.balance, } } - match found_zero_balance { - true => break, - false => index += 20, + if found_zero_balance >= 20 { + break; } + index += 20; } Ok(balance) diff --git a/iota-client/src/api/message_builder.rs b/iota-client/src/api/message_builder.rs index 087173321..43446e379 100644 --- a/iota-client/src/api/message_builder.rs +++ b/iota-client/src/api/message_builder.rs @@ -286,7 +286,7 @@ impl<'a> ClientMessageBuilder<'a> { .get_all() .await?; // For each address, get the address outputs - let mut address_index = 0; + let mut address_index = index; for (index, (address, internal)) in addresses.iter().enumerate() { let address_outputs = self.client.get_address().outputs(&address).await?; let mut outputs = vec![]; diff --git a/iota-core/Cargo.toml b/iota-core/Cargo.toml index 4954bdc0b..5b5285a15 100644 --- a/iota-core/Cargo.toml +++ b/iota-core/Cargo.toml @@ -12,8 +12,8 @@ homepage = "https://iota.org" name = "iota" [dependencies] -bee-message = { git = "https://github.com/iotaledger/bee.git", rev = "8baba875c0f07e62f159f264e8edf1667e013433" } -bee-pow = { git = "https://github.com/iotaledger/bee.git", rev = "8baba875c0f07e62f159f264e8edf1667e013433" } +bee-message = { git = "https://github.com/iotaledger/bee.git", rev = "ce3bd4e1b1ba423c8268e435dcc98c90c397379e" } +bee-pow = { git = "https://github.com/iotaledger/bee.git", rev = "ce3bd4e1b1ba423c8268e435dcc98c90c397379e" } bee-common = { git = "https://github.com/iotaledger/bee.git", rev = "c42171ff33c80cc2efb183e244dc79b7f58d9ac4" } # bee-common = { git = "https://github.com/iotaledger/bee.git", branch = "dev" } # bee-message = { git = "https://github.com/iotaledger/bee.git", branch = "chrysalis-pt-2" } From 0202f8b33dcfcf52f5b4f4ee92c53bbbe4e2a57f Mon Sep 17 00:00:00 2001 From: Thoralf-M Date: Thu, 25 Feb 2021 17:20:48 +0100 Subject: [PATCH 10/11] fix python windows instructions --- bindings/python/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/python/README.md b/bindings/python/README.md index df36b0e68..47633c8fd 100644 --- a/bindings/python/README.md +++ b/bindings/python/README.md @@ -16,7 +16,7 @@ - Go to `bindings/python/native` - `$ cargo build --release` - The built library is located in `target/release/` -- On MacOS, rename `libiota_client.dylib` to `iota_client.so`, on Windows, use `iota_client.dll` directly, and on Linux `libiota_client.so` to `iota_client.so`. +- On MacOS, rename `libiota_client.dylib` to `iota_client.so`, on Windows, rename `iota_client.dll` to `iota_client.pyd`, and on Linux `libiota_client.so` to `iota_client.so`. - Copy your renamed library to `bindings/python/examples/` - Go to `bindings/python/examples` - `$ python example.py` From f8326ff72f2e2242a4de736ec3d04d87da25b5b0 Mon Sep 17 00:00:00 2001 From: Thoralf-M Date: Thu, 25 Feb 2021 17:24:29 +0100 Subject: [PATCH 11/11] clippy --- examples/split_all.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/split_all.rs b/examples/split_all.rs index 1a4618c94..e291eb5b4 100644 --- a/examples/split_all.rs +++ b/examples/split_all.rs @@ -25,7 +25,7 @@ async fn main() -> Result<()> { let seed_2 = Seed::from_bytes(&hex::decode(env::var("NONSECURE_USE_OF_DEVELOPMENT_SEED_2").unwrap())?)?; let total_balance = iota.get_balance(&seed_1).finish().await?; - let mut available = total_balance.clone(); + let mut available = total_balance; println!("total_balance {}", total_balance); let addresses_from_seed_2 = iota .get_addresses(&seed_2) @@ -36,7 +36,7 @@ async fn main() -> Result<()> { for i in 0..total_balance / 1_000_000 { let mut amount = 1_000_000; // Don't add more than we have or is allowed; 1 less here for remaining iotas - if available <= 0 || i > 125 { + if available == 0 || i > 125 { break; } available -= amount;