From ac78730597edba3ae6a2db81dc24537f298fcb04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thoralf=20M=C3=BCller?= Date: Wed, 20 Mar 2024 12:17:25 +0100 Subject: [PATCH 1/4] Add implicit account examples and fix some Python types --- .../implicit-account-creation.ts | 43 ++++++++++++ .../implicit-account-transition.ts | 70 +++++++++++++++++++ .../implicit_account_transition.py | 30 ++++++++ bindings/python/iota_sdk/types/address.py | 19 +---- bindings/python/iota_sdk/types/output_data.py | 8 +-- .../types/transaction_with_metadata.py | 14 ++-- bindings/python/iota_sdk/wallet/wallet.py | 2 +- 7 files changed, 155 insertions(+), 31 deletions(-) create mode 100644 bindings/nodejs/examples/how_tos/account_output/implicit-account-creation.ts create mode 100644 bindings/nodejs/examples/how_tos/account_output/implicit-account-transition.ts create mode 100644 bindings/python/examples/how_tos/account_output/implicit_account_transition.py diff --git a/bindings/nodejs/examples/how_tos/account_output/implicit-account-creation.ts b/bindings/nodejs/examples/how_tos/account_output/implicit-account-creation.ts new file mode 100644 index 0000000000..fa99b4acb2 --- /dev/null +++ b/bindings/nodejs/examples/how_tos/account_output/implicit-account-creation.ts @@ -0,0 +1,43 @@ +// Copyright 2024 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +import { Wallet, initLogger } from '@iota/sdk'; + +// This example uses secrets in environment variables for simplicity which should not be done in production. +// +// Make sure that `example.stronghold` and `example.walletdb` already exist by +// running the `how_tos/wallet/create-wallet` example! +// +require('dotenv').config({ path: '.env' }); + +// Run with command: +// yarn run-example ./how_tos/account_output/implicit-account-creation.ts + +// In this example we create an implicit account creation address. +async function run() { + initLogger(); + for (const envVar of ['WALLET_DB_PATH']) { + if (!(envVar in process.env)) { + throw new Error(`.env ${envVar} is undefined, see .env.example`); + } + } + + try { + // Create the wallet + const wallet = await Wallet.create({ + storagePath: process.env.WALLET_DB_PATH, + }); + + // Get the implicit account address. + const implicitAccountCreationAddress = + await wallet.implicitAccountCreationAddress(); + console.log( + `Implicit account creation address: ${implicitAccountCreationAddress}`, + ); + } catch (error) { + console.log('Error: ', error); + } + process.exit(0); +} + +void run().then(() => process.exit()); diff --git a/bindings/nodejs/examples/how_tos/account_output/implicit-account-transition.ts b/bindings/nodejs/examples/how_tos/account_output/implicit-account-transition.ts new file mode 100644 index 0000000000..6fd4f0a637 --- /dev/null +++ b/bindings/nodejs/examples/how_tos/account_output/implicit-account-transition.ts @@ -0,0 +1,70 @@ +// Copyright 2024 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +import { Wallet, initLogger } from '@iota/sdk'; + +// This example uses secrets in environment variables for simplicity which should not be done in production. +// +// Make sure that `example.stronghold` and `example.walletdb` already exist by +// running the `how_tos/wallet/create-wallet` example! +// +require('dotenv').config({ path: '.env' }); + +// Run with command: +// yarn run-example ./how_tos/account_output/implicit-account-transition.ts + +// In this example we transition an implicit account to an account. +async function run() { + initLogger(); + for (const envVar of [ + 'WALLET_DB_PATH', + 'STRONGHOLD_PASSWORD', + 'EXPLORER_URL', + ]) { + if (!(envVar in process.env)) { + throw new Error(`.env ${envVar} is undefined, see .env.example`); + } + } + + try { + // Create the wallet + const wallet = await Wallet.create({ + storagePath: process.env.WALLET_DB_PATH, + }); + + // Need to sync the wallet with implicit accounts option enabled. + let balance = await wallet.sync({ syncImplicitAccounts: true }); + + let implicitAccounts = await wallet.implicitAccounts(); + if (implicitAccounts.length == 0) { + throw new Error(`No implicit account available`); + } + + // To sign a transaction we need to unlock stronghold. + await wallet.setStrongholdPassword( + process.env.STRONGHOLD_PASSWORD as string, + ); + + console.log('Sending the transition transaction...'); + + // Transition to the account output. + const transaction = await wallet.implicitAccountTransition( + implicitAccounts[0].outputId, + ); + + console.log(`Transaction sent: ${transaction.transactionId}`); + + await wallet.waitForTransactionAcceptance(transaction.transactionId); + console.log( + `Tx accepted: ${process.env.EXPLORER_URL}/transactions/${transaction.transactionId}`, + ); + + balance = await wallet.sync(); + console.log(`Accounts:\n`, balance.accounts); + } catch (error) { + console.log('Error: ', error); + } + process.exit(0); +} + +void run().then(() => process.exit()); diff --git a/bindings/python/examples/how_tos/account_output/implicit_account_transition.py b/bindings/python/examples/how_tos/account_output/implicit_account_transition.py new file mode 100644 index 0000000000..94fcb0d706 --- /dev/null +++ b/bindings/python/examples/how_tos/account_output/implicit_account_transition.py @@ -0,0 +1,30 @@ +import os + +from dotenv import load_dotenv +from iota_sdk import Wallet, WalletOptions, SyncOptions + +# In this example we transition an implicit account to an account. + +load_dotenv() + +for env_var in ['WALLET_DB_PATH', 'STRONGHOLD_PASSWORD', 'EXPLORER_URL']: + if env_var not in os.environ: + raise Exception(f".env {env_var} is undefined, see .env.example") + +# Need to sync the wallet with implicit accounts option enabled. +wallet = Wallet(WalletOptions(storage_path=os.environ.get('WALLET_DB_PATH'))) + +wallet.sync(SyncOptions(sync_implicit_accounts=True)) + +implicit_accounts = wallet.implicit_accounts() + +wallet.set_stronghold_password(os.environ["STRONGHOLD_PASSWORD"]) + +# Transition to the account output. +transaction = wallet.implicit_account_transition( + implicit_accounts[0].output_id) +print(f'Transaction sent: {transaction.transaction_id}') + +wallet.wait_for_transaction_acceptance(transaction.transaction_id) +print( + f'Tx accepted: {os.environ["EXPLORER_URL"]}/transactions/{transaction.transaction_id}') diff --git a/bindings/python/iota_sdk/types/address.py b/bindings/python/iota_sdk/types/address.py index 1bb1eeb958..945080e314 100644 --- a/bindings/python/iota_sdk/types/address.py +++ b/bindings/python/iota_sdk/types/address.py @@ -91,24 +91,7 @@ class ImplicitAccountCreationAddress: """ type: int = field(default_factory=lambda: int( AddressType.IMPLICIT_ACCOUNT_CREATION), init=False) - address: Ed25519Address - - def to_dict(self) -> dict: - """Converts an implicit account creation address to the dictionary representation. - """ - - return { - "type": self.type, - "pubKeyHash": self.address.pub_key_hash - } - - @staticmethod - def from_dict(addr_dict: dict): - """Creates an implicit account creation address from a dictionary representation. - """ - - return ImplicitAccountCreationAddress( - Ed25519Address(addr_dict['pubKeyHash'])) + pub_key_hash: HexStr @json diff --git a/bindings/python/iota_sdk/types/output_data.py b/bindings/python/iota_sdk/types/output_data.py index f750f8cd78..9615c649a0 100644 --- a/bindings/python/iota_sdk/types/output_data.py +++ b/bindings/python/iota_sdk/types/output_data.py @@ -3,13 +3,11 @@ from __future__ import annotations from dataclasses import dataclass -from typing import Optional -from iota_sdk.types.address import Address from iota_sdk.types.common import json from iota_sdk.types.output import Output from iota_sdk.types.output_id import OutputId +from iota_sdk.types.output_id_proof import OutputIdProof from iota_sdk.types.output_metadata import OutputMetadata -from iota_sdk.types.signature import Bip44 @json @@ -21,6 +19,7 @@ class OutputData: output_id: With the output data corresponding output ID. metadata: With the output corresponding metadata. output: The output object itself. + output_id_proof: The output ID proof. address: The address associated with the output. network_id: The network ID the output belongs to. remainder: Whether the output represents a remainder amount. @@ -29,7 +28,6 @@ class OutputData: output_id: OutputId metadata: OutputMetadata output: Output - address: Address + output_id_proof: OutputIdProof network_id: str remainder: bool - chain: Optional[Bip44] = None diff --git a/bindings/python/iota_sdk/types/transaction_with_metadata.py b/bindings/python/iota_sdk/types/transaction_with_metadata.py index 625ed55c80..68df84391d 100644 --- a/bindings/python/iota_sdk/types/transaction_with_metadata.py +++ b/bindings/python/iota_sdk/types/transaction_with_metadata.py @@ -23,12 +23,12 @@ class InclusionState(str, Enum): Conflicting: The transaction is conflicting. UnknownPruned: The transaction is unknown or already pruned. """ - Pending = 'pending' - Accepted = 'accepted' - Confirmed = 'confirmed' - Finalized = 'finalized' - Conflicting = 'conflicting' - UnknownPruned = 'unknownPruned' + Pending = 'Pending' + Accepted = 'Accepted' + Confirmed = 'Confirmed' + Finalized = 'Finalized' + Conflicting = 'Conflicting' + UnknownPruned = 'UnknownPruned' @json @@ -53,7 +53,7 @@ class TransactionWithMetadata: transaction_id: TransactionId network_id: int incoming: bool - inputs = List[OutputWithMetadata] + inputs: List[OutputWithMetadata] note: Optional[str] = None block_id: Optional[BlockId] = None diff --git a/bindings/python/iota_sdk/wallet/wallet.py b/bindings/python/iota_sdk/wallet/wallet.py index f9e666197c..6e95c64bd6 100644 --- a/bindings/python/iota_sdk/wallet/wallet.py +++ b/bindings/python/iota_sdk/wallet/wallet.py @@ -478,7 +478,7 @@ def prepare_implicit_account_transition( """Prepares to transition an implicit account to an account. """ prepared = PreparedTransactionData.from_dict(self._call_method( - 'implicitAccountTransition', { + 'prepareImplicitAccountTransition', { 'outputId': output_id } )) From 53f42d1a9ea29f6ee54092528e6f07c6ad0b6c46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thoralf=20M=C3=BCller?= Date: Wed, 20 Mar 2024 12:23:57 +0100 Subject: [PATCH 2/4] Use const --- .../how_tos/account_output/implicit-account-transition.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/nodejs/examples/how_tos/account_output/implicit-account-transition.ts b/bindings/nodejs/examples/how_tos/account_output/implicit-account-transition.ts index 6fd4f0a637..0fd9ec3e7d 100644 --- a/bindings/nodejs/examples/how_tos/account_output/implicit-account-transition.ts +++ b/bindings/nodejs/examples/how_tos/account_output/implicit-account-transition.ts @@ -35,7 +35,7 @@ async function run() { // Need to sync the wallet with implicit accounts option enabled. let balance = await wallet.sync({ syncImplicitAccounts: true }); - let implicitAccounts = await wallet.implicitAccounts(); + const implicitAccounts = await wallet.implicitAccounts(); if (implicitAccounts.length == 0) { throw new Error(`No implicit account available`); } From 3631be7ac34228fb6ae831e22ba8b4b3b532dcae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thoralf=20M=C3=BCller?= Date: Thu, 21 Mar 2024 10:13:21 +0100 Subject: [PATCH 3/4] Clean docs --- bindings/python/iota_sdk/types/output_data.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/bindings/python/iota_sdk/types/output_data.py b/bindings/python/iota_sdk/types/output_data.py index 9615c649a0..ad23de6b93 100644 --- a/bindings/python/iota_sdk/types/output_data.py +++ b/bindings/python/iota_sdk/types/output_data.py @@ -20,10 +20,8 @@ class OutputData: metadata: With the output corresponding metadata. output: The output object itself. output_id_proof: The output ID proof. - address: The address associated with the output. network_id: The network ID the output belongs to. remainder: Whether the output represents a remainder amount. - chain: A list of chain state indexes. """ output_id: OutputId metadata: OutputMetadata From 75f4bf154de1fc6ee0146c2f1d9ee95ed2b63e5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thoralf=20M=C3=BCller?= Date: Thu, 21 Mar 2024 10:14:49 +0100 Subject: [PATCH 4/4] Rename to implicit_account_creation_address --- ...count-creation.ts => implicit-account-creation-address.ts} | 2 +- ...count_creation.py => implicit_account_creation_address.py} | 0 sdk/Cargo.toml | 4 ++-- ...count_creation.rs => implicit_account_creation_address.rs} | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) rename bindings/nodejs/examples/how_tos/account_output/{implicit-account-creation.ts => implicit-account-creation-address.ts} (98%) rename bindings/python/examples/how_tos/account_output/{implicit_account_creation.py => implicit_account_creation_address.py} (100%) rename sdk/examples/how_tos/account_output/{implicit_account_creation.rs => implicit_account_creation_address.rs} (98%) diff --git a/bindings/nodejs/examples/how_tos/account_output/implicit-account-creation.ts b/bindings/nodejs/examples/how_tos/account_output/implicit-account-creation-address.ts similarity index 98% rename from bindings/nodejs/examples/how_tos/account_output/implicit-account-creation.ts rename to bindings/nodejs/examples/how_tos/account_output/implicit-account-creation-address.ts index fa99b4acb2..69649c6c20 100644 --- a/bindings/nodejs/examples/how_tos/account_output/implicit-account-creation.ts +++ b/bindings/nodejs/examples/how_tos/account_output/implicit-account-creation-address.ts @@ -11,7 +11,7 @@ import { Wallet, initLogger } from '@iota/sdk'; require('dotenv').config({ path: '.env' }); // Run with command: -// yarn run-example ./how_tos/account_output/implicit-account-creation.ts +// yarn run-example ./how_tos/account_output/implicit-account-creation-address.ts // In this example we create an implicit account creation address. async function run() { diff --git a/bindings/python/examples/how_tos/account_output/implicit_account_creation.py b/bindings/python/examples/how_tos/account_output/implicit_account_creation_address.py similarity index 100% rename from bindings/python/examples/how_tos/account_output/implicit_account_creation.py rename to bindings/python/examples/how_tos/account_output/implicit_account_creation_address.py diff --git a/sdk/Cargo.toml b/sdk/Cargo.toml index e66e4a34d1..cc78ecb5d6 100644 --- a/sdk/Cargo.toml +++ b/sdk/Cargo.toml @@ -348,8 +348,8 @@ path = "examples/how_tos/account_output/destroy.rs" required-features = ["wallet", "stronghold"] [[example]] -name = "implicit_account_creation" -path = "examples/how_tos/account_output/implicit_account_creation.rs" +name = "implicit_account_creation_address" +path = "examples/how_tos/account_output/implicit_account_creation_address.rs" required-features = ["wallet", "storage"] # Outputs diff --git a/sdk/examples/how_tos/account_output/implicit_account_creation.rs b/sdk/examples/how_tos/account_output/implicit_account_creation_address.rs similarity index 98% rename from sdk/examples/how_tos/account_output/implicit_account_creation.rs rename to sdk/examples/how_tos/account_output/implicit_account_creation_address.rs index 5c2fe72549..f47afca609 100644 --- a/sdk/examples/how_tos/account_output/implicit_account_creation.rs +++ b/sdk/examples/how_tos/account_output/implicit_account_creation_address.rs @@ -5,7 +5,7 @@ //! //! Rename `.env.example` to `.env` first, then run the command: //! ```sh -//! cargo run --release --all-features --example implicit_account_creation +//! cargo run --release --all-features --example implicit_account_creation_address //! ``` use iota_sdk::{