From e520757abbc590fafd36164d46e652fbb6962369 Mon Sep 17 00:00:00 2001 From: Alex Coats Date: Wed, 1 Nov 2023 11:24:01 -0400 Subject: [PATCH 1/4] Remove essence from python --- bindings/core/src/method/secret_manager.rs | 8 +- .../nft_collection/00_mint_issuer_nft.py | 10 +-- .../offline_signing/2_sign_transaction.py | 2 +- bindings/python/iota_sdk/__init__.py | 1 + bindings/python/iota_sdk/client/client.py | 20 +---- .../iota_sdk/secret_manager/secret_manager.py | 6 +- bindings/python/iota_sdk/types/essence.py | 68 --------------- bindings/python/iota_sdk/types/payload.py | 22 ++--- bindings/python/iota_sdk/types/transaction.py | 72 ++++++++-------- .../python/iota_sdk/types/transaction_data.py | 12 +-- .../types/transaction_with_metadata.py | 52 ++++++++++++ bindings/python/iota_sdk/utils.py | 12 +-- bindings/python/iota_sdk/wallet/account.py | 66 +++++++------- .../iota_sdk/wallet/prepared_transaction.py | 12 +-- bindings/python/tests/test_block.py | 85 +++++++++---------- 15 files changed, 206 insertions(+), 242 deletions(-) delete mode 100644 bindings/python/iota_sdk/types/essence.py create mode 100644 bindings/python/iota_sdk/types/transaction_with_metadata.py diff --git a/bindings/core/src/method/secret_manager.rs b/bindings/core/src/method/secret_manager.rs index c538f3aec2..b70c10db53 100644 --- a/bindings/core/src/method/secret_manager.rs +++ b/bindings/core/src/method/secret_manager.rs @@ -36,7 +36,7 @@ pub enum SecretManagerMethod { SignatureUnlock { /// Transaction signing hash transaction_signing_hash: String, - /// Chain to sign the hash with + /// Chain used to sign the hash #[serde(with = "Bip44Def")] chain: Bip44, }, @@ -44,7 +44,7 @@ pub enum SecretManagerMethod { SignEd25519 { /// The message to sign, hex encoded String message: String, - /// Chain to sign the message with + /// Chain used to sign the message #[serde(with = "Bip44Def")] chain: Bip44, }, @@ -52,7 +52,7 @@ pub enum SecretManagerMethod { SignSecp256k1Ecdsa { /// The message to sign, hex encoded String message: String, - /// Chain to sign the message with + /// Chain used to sign the message #[serde(with = "Bip44Def")] chain: Bip44, }, @@ -66,7 +66,7 @@ pub enum SecretManagerMethod { #[serde(rename_all = "camelCase")] SignBlock { unsigned_block: UnsignedBlockDto, - /// Chain to sign the essence hash with + /// Chain used to sign the block #[serde(with = "Bip44Def")] chain: Bip44, }, diff --git a/bindings/python/examples/how_tos/nft_collection/00_mint_issuer_nft.py b/bindings/python/examples/how_tos/nft_collection/00_mint_issuer_nft.py index 3d47fada8f..159217f0ae 100644 --- a/bindings/python/examples/how_tos/nft_collection/00_mint_issuer_nft.py +++ b/bindings/python/examples/how_tos/nft_collection/00_mint_issuer_nft.py @@ -28,21 +28,21 @@ ) -transaction = account.mint_nfts([params]) +tx = account.mint_nfts([params]) # Wait for transaction to get included block_id = account.reissue_transaction_until_included( - transaction.transaction_id) + tx.transaction_id) print( f'Block sent: {os.environ["EXPLORER_URL"]}/block/{block_id}') -essence = transaction.payload["essence"] +transaction = tx.payload.transaction -for outputIndex, output in enumerate(essence["outputs"]): +for outputIndex, output in enumerate(transaction["outputs"]): # New minted NFT id is empty in the output if output["type"] == 6 and output["nftId"] == '0x0000000000000000000000000000000000000000000000000000000000000000': outputId = Utils.compute_output_id( - transaction.transaction_id, outputIndex) + tx.transaction_id, outputIndex) nftId = Utils.compute_nft_id(outputId) print(f'New minted NFT id: {nftId}') diff --git a/bindings/python/examples/wallet/offline_signing/2_sign_transaction.py b/bindings/python/examples/wallet/offline_signing/2_sign_transaction.py index 12c74dfe07..6bbfb52dc6 100644 --- a/bindings/python/examples/wallet/offline_signing/2_sign_transaction.py +++ b/bindings/python/examples/wallet/offline_signing/2_sign_transaction.py @@ -34,7 +34,7 @@ wallet.set_stronghold_password(os.environ["STRONGHOLD_PASSWORD"]) # Signs prepared transaction offline. -signed_transaction_data = account.sign_transaction_essence( +signed_transaction_data = account.sign_transaction( prepared_transaction_data) print("Signed transaction.") diff --git a/bindings/python/iota_sdk/__init__.py b/bindings/python/iota_sdk/__init__.py index 7b244a3be0..a08515c175 100644 --- a/bindings/python/iota_sdk/__init__.py +++ b/bindings/python/iota_sdk/__init__.py @@ -41,6 +41,7 @@ from .types.send_params import * from .types.token_scheme import * from .types.transaction import * +from .types.transaction_with_metadata import * from .types.transaction_data import * from .types.transaction_options import * from .types.unlock import * diff --git a/bindings/python/iota_sdk/client/client.py b/bindings/python/iota_sdk/client/client.py index 79736ad1f8..fbcd621509 100644 --- a/bindings/python/iota_sdk/client/client.py +++ b/bindings/python/iota_sdk/client/client.py @@ -5,24 +5,21 @@ from datetime import timedelta from typing import Any, Dict, List, Optional, Union import humps -from dacite import from_dict from iota_sdk.external import create_client, call_client_method, listen_mqtt from iota_sdk.client._node_core_api import NodeCoreAPI from iota_sdk.client._node_indexer_api import NodeIndexerAPI from iota_sdk.client._high_level_api import HighLevelAPI from iota_sdk.client._utils import ClientUtils -from iota_sdk.secret_manager.secret_manager import LedgerNanoSecretManager, MnemonicSecretManager, StrongholdSecretManager, SeedSecretManager from iota_sdk.types.block.signed_block import UnsignedBlock from iota_sdk.types.common import HexStr, Node from iota_sdk.types.feature import Feature from iota_sdk.types.native_token import NativeToken from iota_sdk.types.network_info import NetworkInfo from iota_sdk.types.output import AccountOutput, BasicOutput, FoundryOutput, NftOutput, deserialize_output -from iota_sdk.types.payload import Payload, TransactionPayload +from iota_sdk.types.payload import Payload from iota_sdk.types.token_scheme import SimpleTokenScheme from iota_sdk.types.unlock_condition import UnlockCondition -from iota_sdk.types.transaction_data import PreparedTransactionData class ClientError(Exception): @@ -373,21 +370,6 @@ def unhealthy_nodes(self) -> List[Dict[str, Any]]: """ return self._call_method('unhealthyNodes') - def sign_transaction( - self, - secret_manager: Union[LedgerNanoSecretManager, MnemonicSecretManager, SeedSecretManager, StrongholdSecretManager], - prepared_transaction_data: PreparedTransactionData) -> TransactionPayload: - """Sign a transaction. - - Args: - secret_manager: One of the supported secret managers. - prepared_transaction_data: a prepared transaction to sign. - """ - return from_dict(TransactionPayload, self._call_method('signTransaction', { - 'secretManager': secret_manager, - 'preparedTransactionData': prepared_transaction_data - })) - def build_basic_block( self, issuer_id: HexStr, diff --git a/bindings/python/iota_sdk/secret_manager/secret_manager.py b/bindings/python/iota_sdk/secret_manager/secret_manager.py index 97c9fec4cc..1aa65e9886 100644 --- a/bindings/python/iota_sdk/secret_manager/secret_manager.py +++ b/bindings/python/iota_sdk/secret_manager/secret_manager.py @@ -11,7 +11,7 @@ from iota_sdk.types.common import HexStr from iota_sdk.types.signature import Ed25519Signature, Bip44 from iota_sdk.types.transaction_data import PreparedTransactionData -from iota_sdk.types.payload import TransactionPayload +from iota_sdk.types.payload import SignedTransactionPayload class LedgerNanoSecretManager(dict): @@ -268,13 +268,13 @@ def sign_secp256k1_ecdsa(self, message: HexStr, chain: Bip44): }) def sign_transaction( - self, prepared_transaction_data: PreparedTransactionData) -> TransactionPayload: + self, prepared_transaction_data: PreparedTransactionData) -> SignedTransactionPayload: """Sign a transaction. Args: prepare_transaction_data: The prepared transaction data that needs to be signed. """ - return from_dict(TransactionPayload, self._call_method('signTransaction', { + return from_dict(SignedTransactionPayload, self._call_method('signTransaction', { 'preparedTransactionData': prepared_transaction_data.to_dict() })) diff --git a/bindings/python/iota_sdk/types/essence.py b/bindings/python/iota_sdk/types/essence.py deleted file mode 100644 index 32df2042e6..0000000000 --- a/bindings/python/iota_sdk/types/essence.py +++ /dev/null @@ -1,68 +0,0 @@ -# Copyright 2023 IOTA Stiftung -# SPDX-License-Identifier: Apache-2.0 - -from __future__ import annotations -from enum import IntEnum -from typing import TYPE_CHECKING, Optional, List, TypeAlias - -from dataclasses import dataclass, field - -from iota_sdk.types.common import HexStr, json, SlotIndex -from iota_sdk.types.mana import ManaAllotment -from iota_sdk.types.input import UtxoInput -from iota_sdk.types.context_input import ContextInput -from iota_sdk.types.output import Output - -# Required to prevent circular import -if TYPE_CHECKING: - from iota_sdk.types.payload import Payload - - -class EssenceType(IntEnum): - """Block payload types. - - Attributes: - RegularTransactionEssence (2): A Regular Transaction Essence. - """ - RegularTransactionEssence = 2 - - -@json -@dataclass -class RegularTransactionEssence: - """Describes the essence data making up a transaction by defining its inputs, outputs, and an optional payload. - - Attributes: - network_id: The unique value denoting whether the block was meant for mainnet, shimmer, testnet, or a private network. - It consists of the first 8 bytes of the BLAKE2b-256 hash of the network name. - creation_slot: The slot index in which the transaction was created. - inputs: The inputs to consume in order to fund the outputs of the Transaction Payload. - inputs_commitment: BLAKE2b-256 hash serving as a commitment to the serialized outputs referenced by Inputs. - outputs: The outputs that are created by the Transaction Payload - context_inputs: The inputs that provide additional contextual information for the execution of a transaction. - allotments: The allotments of Mana which which will be added upon commitment of the slot. - capabilities: The capability bitflags of the transaction. - payload: An optional tagged data payload - """ - network_id: str - creation_slot: SlotIndex - inputs: List[UtxoInput] - inputs_commitment: HexStr - outputs: List[Output] - context_inputs: Optional[List[ContextInput]] = None - allotments: Optional[List[ManaAllotment]] = None - capabilities: HexStr = field(default='0x', init=False) - payload: Optional[Payload] = None - type: int = field( - default_factory=lambda: EssenceType.RegularTransactionEssence, - init=False) - - def with_capabilities(self, capabilities: bytes): - """Sets the transaction capabilities from a byte array. - Attributes: - capabilities: The transaction capabilities bitflags. - """ - self.capabilities = '0x' + capabilities.hex() - - -TransactionEssence: TypeAlias = RegularTransactionEssence diff --git a/bindings/python/iota_sdk/types/payload.py b/bindings/python/iota_sdk/types/payload.py index 9685c504d1..245edb9409 100644 --- a/bindings/python/iota_sdk/types/payload.py +++ b/bindings/python/iota_sdk/types/payload.py @@ -6,7 +6,7 @@ from typing import Any, Dict, List, TypeAlias, Union from dataclasses import dataclass, field from iota_sdk.types.common import HexStr, json -from iota_sdk.types.essence import TransactionEssence +from bindings.python.iota_sdk.types.transaction import Transaction from iota_sdk.types.unlock import SignatureUnlock, ReferenceUnlock @@ -15,11 +15,11 @@ class PayloadType(IntEnum): Attributes: TaggedData (0): A tagged data payload. - Transaction (1): A transaction payload. + SignedTransaction (1): A signed transaction payload. CandidacyAnnouncement (2): A candidacy announcement payload. """ TaggedData = 0 - Transaction = 1 + SignedTransaction = 1 CandidacyAnnouncement = 2 @@ -42,18 +42,18 @@ class TaggedDataPayload: @json @dataclass -class TransactionPayload: - """A transaction payload. +class SignedTransactionPayload: + """A signed transaction payload. Attributes: - essence: The transaction essence. + transaction: The transaction. unlocks: The unlocks of the transaction. """ - essence: TransactionEssence + transaction: Transaction unlocks: List[Union[SignatureUnlock, ReferenceUnlock]] type: int = field( default_factory=lambda: int( - PayloadType.Transaction), + PayloadType.SignedTransaction), init=False) @@ -69,7 +69,7 @@ class CandidacyAnnouncementPayload: Payload: TypeAlias = Union[TaggedDataPayload, - TransactionPayload, CandidacyAnnouncementPayload] + SignedTransactionPayload, CandidacyAnnouncementPayload] def deserialize_payload(d: Dict[str, Any]) -> Payload: @@ -82,8 +82,8 @@ def deserialize_payload(d: Dict[str, Any]) -> Payload: payload_type = d['type'] if payload_type == PayloadType.TaggedData: return TaggedDataPayload.from_dict(d) - if payload_type == PayloadType.Transaction: - return TransactionPayload.from_dict(d) + if payload_type == PayloadType.SignedTransaction: + return SignedTransactionPayload.from_dict(d) if payload_type == PayloadType.CandidacyAnnouncement: return CandidacyAnnouncementPayload.from_dict(d) raise Exception(f'invalid payload type: {payload_type}') diff --git a/bindings/python/iota_sdk/types/transaction.py b/bindings/python/iota_sdk/types/transaction.py index 7ae9266109..79a6fd11a5 100644 --- a/bindings/python/iota_sdk/types/transaction.py +++ b/bindings/python/iota_sdk/types/transaction.py @@ -2,51 +2,49 @@ # SPDX-License-Identifier: Apache-2.0 from __future__ import annotations -from dataclasses import dataclass -from typing import List, Optional -from enum import Enum -from iota_sdk.types.common import HexStr, json -from iota_sdk.types.output_metadata import OutputWithMetadata -from iota_sdk.types.payload import TransactionPayload +from typing import TYPE_CHECKING, Optional, List +from dataclasses import dataclass, field -class InclusionState(str, Enum): - """Inclusion state variants of a transaction. +from iota_sdk.types.common import HexStr, json, SlotIndex +from iota_sdk.types.mana import ManaAllotment +from iota_sdk.types.input import UtxoInput +from iota_sdk.types.context_input import ContextInput +from iota_sdk.types.output import Output - Attributes: - Pending: The transaction is pending. - Confirmed: The transaction is confirmed. - Conflicting: The transaction is conflicting. - UnknownPruned: The transaction is unknown or already pruned. - """ - Pending = 'pending' - Confirmed = 'confirmed' - Conflicting = 'conflicting' - UnknownPruned = 'unknownPruned' +# Required to prevent circular import +if TYPE_CHECKING: + from iota_sdk.types.payload import Payload @json @dataclass class Transaction: - """A transaction with some metadata. + """A transaction consuming inputs, creating outputs and carrying an optional payload. Attributes: - payload: The transaction payload. - inclusion_state: The inclusion state of the transaction. - timestamp: The timestamp of the transaction. - transaction_id: The ID of the corresponding transaction. - network_id: The ID of the network this transaction was issued in. - incoming: Indicates whether the transaction was created by the wallet or whether it was sent by someone else and is incoming. - inputs: The inputs of the transaction. - note: A note attached to the transaction. - block_id: The ID of the block that holds the transaction. + network_id: The unique value denoting whether the block was meant for mainnet, shimmer, testnet, or a private network. + It consists of the first 8 bytes of the BLAKE2b-256 hash of the network name. + creation_slot: The slot index in which the transaction was created. + context_inputs: The inputs that provide additional contextual information for the execution of a transaction. + inputs: The inputs to consume in order to fund the outputs of the Transaction Payload. + allotments: The allotments of Mana which which will be added upon commitment of the slot. + capabilities: The capability bitflags of the transaction. + payload: An optional tagged data payload + outputs: The outputs that are created by the Transaction Payload """ - payload: TransactionPayload - inclusion_state: InclusionState - timestamp: int - transaction_id: HexStr - network_id: int - incoming: bool - inputs = List[OutputWithMetadata] - note: Optional[str] = None - block_id: Optional[HexStr] = None + network_id: str + creation_slot: SlotIndex + context_inputs: List[ContextInput] + inputs: List[UtxoInput] + allotments: List[ManaAllotment] + capabilities: HexStr = field(default='0x', init=False) + payload: Optional[Payload] = None + outputs: List[Output] + + def with_capabilities(self, capabilities: bytes): + """Sets the transaction capabilities from a byte array. + Attributes: + capabilities: The transaction capabilities bitflags. + """ + self.capabilities = '0x' + capabilities.hex() diff --git a/bindings/python/iota_sdk/types/transaction_data.py b/bindings/python/iota_sdk/types/transaction_data.py index e7ab0f5092..5aa4687444 100644 --- a/bindings/python/iota_sdk/types/transaction_data.py +++ b/bindings/python/iota_sdk/types/transaction_data.py @@ -7,8 +7,8 @@ from iota_sdk.types.address import Address from iota_sdk.types.output import Output from iota_sdk.types.output_metadata import OutputMetadata -from iota_sdk.types.essence import TransactionEssence -from iota_sdk.types.payload import TransactionPayload +from bindings.python.iota_sdk.types.transaction import Transaction +from iota_sdk.types.payload import SignedTransactionPayload from iota_sdk.types.signature import Bip44 from iota_sdk.types.common import json @@ -49,11 +49,11 @@ class PreparedTransactionData: """Helper class for offline signing. Attributes: - essence: The transaction essence. + transaction: The transaction. inputs_data: Data about the inputs which is required for signing. remainder: Data about a remainder. """ - essence: TransactionEssence + transaction: Transaction inputs_data: List[InputSigningData] remainder: Optional[RemainderData] = None @@ -64,8 +64,8 @@ class SignedTransactionData: """Helper class for offline signing. Attributes: - transaction_payload: The transaction payload. + payload: The transaction payload. inputs_data: Data about the inputs consumed in the transaction. """ - transaction_payload: TransactionPayload + payload: SignedTransactionPayload inputs_data: List[InputSigningData] diff --git a/bindings/python/iota_sdk/types/transaction_with_metadata.py b/bindings/python/iota_sdk/types/transaction_with_metadata.py new file mode 100644 index 0000000000..7dee2854fa --- /dev/null +++ b/bindings/python/iota_sdk/types/transaction_with_metadata.py @@ -0,0 +1,52 @@ +# Copyright 2023 IOTA Stiftung +# SPDX-License-Identifier: Apache-2.0 + +from __future__ import annotations +from dataclasses import dataclass +from typing import List, Optional +from enum import Enum +from iota_sdk.types.common import HexStr, json +from iota_sdk.types.output_metadata import OutputWithMetadata +from iota_sdk.types.payload import SignedTransactionPayload + + +class InclusionState(str, Enum): + """Inclusion state variants of a transaction. + + Attributes: + Pending: The transaction is pending. + Confirmed: The transaction is confirmed. + Conflicting: The transaction is conflicting. + UnknownPruned: The transaction is unknown or already pruned. + """ + Pending = 'pending' + Confirmed = 'confirmed' + Conflicting = 'conflicting' + UnknownPruned = 'unknownPruned' + + +@json +@dataclass +class TransactionWithMetadata: + """A transaction with some metadata. + + Attributes: + payload: The transaction payload. + block_id: The ID of the block that holds the transaction. + inclusion_state: The inclusion state of the transaction. + timestamp: The timestamp of the transaction. + transaction_id: The ID of the corresponding transaction. + network_id: The ID of the network this transaction was issued in. + incoming: Indicates whether the transaction was created by the wallet or whether it was sent by someone else and is incoming. + note: A note attached to the transaction. + inputs: The inputs of the transaction. + """ + payload: SignedTransactionPayload + block_id: Optional[HexStr] = None + inclusion_state: InclusionState + timestamp: int + transaction_id: HexStr + network_id: int + incoming: bool + note: Optional[str] = None + inputs = List[OutputWithMetadata] diff --git a/bindings/python/iota_sdk/utils.py b/bindings/python/iota_sdk/utils.py index e889f74cfb..0cb6a0b68b 100644 --- a/bindings/python/iota_sdk/utils.py +++ b/bindings/python/iota_sdk/utils.py @@ -8,12 +8,12 @@ from iota_sdk.types.signature import Ed25519Signature from iota_sdk.types.address import Address, deserialize_address from iota_sdk.types.common import HexStr -from iota_sdk.types.essence import TransactionEssence +from bindings.python.iota_sdk.types.transaction import Transaction from iota_sdk.types.node_info import ProtocolParameters from iota_sdk.types.output_id import OutputId from iota_sdk.types.output import Output from iota_sdk.external import call_utils_method -from iota_sdk.types.payload import TransactionPayload +from iota_sdk.types.payload import SignedTransactionPayload # Required to prevent circular import if TYPE_CHECKING: @@ -177,19 +177,19 @@ def block_id(block: SignedBlock, params: ProtocolParameters) -> HexStr: }) @staticmethod - def transaction_id(transaction_payload: TransactionPayload) -> HexStr: + def transaction_id(payload: SignedTransactionPayload) -> HexStr: """ Compute the transaction ID (Blake2b256 hash of the provided transaction payload) of a transaction payload. """ return _call_method('transactionId', { - 'payload': transaction_payload.as_dict() + 'payload': payload.as_dict() }) @staticmethod - def transaction_signing_hash(essence: TransactionEssence) -> HexStr: + def transaction_signing_hash(transaction: Transaction) -> HexStr: """ Compute the signing hash of a transaction. """ return _call_method('transactionSigningHash', { - 'essence': essence.to_dict(), + 'transaction': transaction.to_dict(), }) @staticmethod diff --git a/bindings/python/iota_sdk/wallet/account.py b/bindings/python/iota_sdk/wallet/account.py index 4d434ea0cc..9f02809950 100644 --- a/bindings/python/iota_sdk/wallet/account.py +++ b/bindings/python/iota_sdk/wallet/account.py @@ -20,7 +20,7 @@ from iota_sdk.types.output_params import OutputParams from iota_sdk.types.transaction_data import PreparedTransactionData, SignedTransactionData from iota_sdk.types.send_params import CreateAccountOutputParams, CreateNativeTokenParams, MintNftParams, SendNativeTokensParams, SendNftParams, SendParams -from iota_sdk.types.transaction import Transaction +from bindings.python.iota_sdk.types.transaction_with_metadata import TransactionWithMetadata from iota_sdk.types.transaction_options import TransactionOptions from iota_sdk.types.consolidation_params import ConsolidationParams @@ -82,7 +82,7 @@ def get_metadata(self) -> AccountMetadata: self.meta["alias"], self.meta["coinType"], self.meta["index"]) def burn( - self, burn: Burn, options: Optional[TransactionOptions] = None) -> Transaction: + self, burn: Burn, options: Optional[TransactionOptions] = None) -> TransactionWithMetadata: """A generic function that can be used to burn native tokens, nfts, foundries and aliases. """ return self.prepare_burn(burn, options).send() @@ -129,7 +129,7 @@ def prepare_burn_nft(self, return PreparedTransaction(self, prepared) def consolidate_outputs( - self, params: ConsolidationParams) -> Transaction: + self, params: ConsolidationParams) -> TransactionWithMetadata: """Consolidate outputs. """ return self.prepare_consolidate_outputs(params).send() @@ -147,7 +147,7 @@ def prepare_consolidate_outputs( def create_account_output(self, params: Optional[CreateAccountOutputParams] = None, - options: Optional[TransactionOptions] = None) -> Transaction: + options: Optional[TransactionOptions] = None) -> TransactionWithMetadata: """Create an account output. """ return self.prepare_create_account_output(params, options).send() @@ -221,10 +221,10 @@ def get_output(self, output_id: OutputId) -> OutputData: } )) - def get_transaction(self, transaction_id: HexStr) -> Transaction: + def get_transaction(self, transaction_id: HexStr) -> TransactionWithMetadata: """Get transaction. """ - return Transaction.from_dict(self._call_account_method( + return TransactionWithMetadata.from_dict(self._call_account_method( 'getTransaction', { 'transactionId': transaction_id } @@ -270,21 +270,21 @@ def unspent_outputs( ) return [from_dict(OutputData, o) for o in outputs] - def incoming_transactions(self) -> List[Transaction]: + def incoming_transactions(self) -> List[TransactionWithMetadata]: """Returns all incoming transactions of the account. """ transactions = self._call_account_method( 'incomingTransactions' ) - return [Transaction.from_dict(tx) for tx in transactions] + return [TransactionWithMetadata.from_dict(tx) for tx in transactions] - def transactions(self) -> List[Transaction]: + def transactions(self) -> List[TransactionWithMetadata]: """Returns all transaction of the account. """ transactions = self._call_account_method( 'transactions' ) - return [Transaction.from_dict(tx) for tx in transactions] + return [TransactionWithMetadata.from_dict(tx) for tx in transactions] def pending_transactions(self): """Returns all pending transactions of the account. @@ -292,10 +292,10 @@ def pending_transactions(self): transactions = self._call_account_method( 'pendingTransactions' ) - return [Transaction.from_dict(tx) for tx in transactions] + return [TransactionWithMetadata.from_dict(tx) for tx in transactions] def create_native_token(self, params: CreateNativeTokenParams, - options: Optional[TransactionOptions] = None) -> Transaction: + options: Optional[TransactionOptions] = None) -> TransactionWithMetadata: """Create native token. """ return self.prepare_create_native_token(params, options).send() @@ -316,7 +316,7 @@ def prepare_create_native_token(self, params: CreateNativeTokenParams, def melt_native_token(self, token_id: HexStr, melt_amount: int, - options: Optional[TransactionOptions] = None) -> Transaction: + options: Optional[TransactionOptions] = None) -> TransactionWithMetadata: """Melt native tokens. This happens with the foundry output which minted them, by increasing it's `melted_tokens` field. """ @@ -340,7 +340,7 @@ def prepare_melt_native_token(self, return PreparedTransaction(self, prepared) def mint_native_token(self, token_id: HexStr, mint_amount: int, - options: Optional[TransactionOptions] = None) -> Transaction: + options: Optional[TransactionOptions] = None) -> TransactionWithMetadata: """Mint additional native tokens. """ return self.prepare_mint_native_token( @@ -360,7 +360,7 @@ def prepare_mint_native_token(self, token_id: HexStr, mint_amount: int, return PreparedTransaction(self, prepared) def mint_nfts(self, params: List[MintNftParams], - options: Optional[TransactionOptions] = None) -> Transaction: + options: Optional[TransactionOptions] = None) -> TransactionWithMetadata: """Mint NFTs. """ return self.prepare_mint_nfts(params, options).send() @@ -413,7 +413,7 @@ def prepare_send(self, params: List[SendParams], return PreparedTransaction(self, prepared) def send_transaction( - self, outputs: List[Output], options: Optional[TransactionOptions] = None) -> Transaction: + self, outputs: List[Output], options: Optional[TransactionOptions] = None) -> TransactionWithMetadata: """Send a transaction. """ return self.prepare_transaction(outputs, options).send() @@ -455,10 +455,10 @@ def sync(self, options: Optional[SyncOptions] = None) -> Balance: )) def send(self, amount: int, address: str, - options: Optional[TransactionOptions] = None) -> Transaction: + options: Optional[TransactionOptions] = None) -> TransactionWithMetadata: """Send base coins. """ - return Transaction.from_dict(self._call_account_method( + return TransactionWithMetadata.from_dict(self._call_account_method( 'send', { 'amount': str(amount), 'address': address, @@ -467,10 +467,10 @@ def send(self, amount: int, address: str, )) def send_with_params( - self, params: List[SendParams], options: Optional[TransactionOptions] = None) -> Transaction: + self, params: List[SendParams], options: Optional[TransactionOptions] = None) -> TransactionWithMetadata: """Send base coins to multiple addresses or with additional parameters. """ - return Transaction.from_dict(self._call_account_method( + return TransactionWithMetadata.from_dict(self._call_account_method( 'sendWithParams', { 'params': [param.to_dict() for param in params], 'options': options @@ -478,7 +478,7 @@ def send_with_params( )) def send_native_tokens( - self, params: List[SendNativeTokensParams], options: Optional[TransactionOptions] = None) -> Transaction: + self, params: List[SendNativeTokensParams], options: Optional[TransactionOptions] = None) -> TransactionWithMetadata: """Send native tokens. """ return self.prepare_send_native_tokens(params, options).send() @@ -498,7 +498,7 @@ def prepare_send_native_tokens( return PreparedTransaction(self, prepared) def send_nft(self, params: List[SendNftParams], - options: Optional[TransactionOptions] = None) -> Transaction: + options: Optional[TransactionOptions] = None) -> TransactionWithMetadata: """Send nft. """ return self.prepare_send_nft(params, options).send() @@ -534,51 +534,51 @@ def set_default_sync_options(self, options: SyncOptions): } ) - def sign_transaction_essence( + def sign_transaction( self, prepared_transaction_data: PreparedTransactionData) -> SignedTransactionData: - """Sign a transaction essence. + """Sign a transaction. """ return SignedTransactionData.from_dict(self._call_account_method( - 'signTransactionEssence', { + 'signTransaction', { 'preparedTransactionData': prepared_transaction_data } )) def sign_and_submit_transaction( - self, prepared_transaction_data: PreparedTransactionData) -> Transaction: + self, prepared_transaction_data: PreparedTransactionData) -> TransactionWithMetadata: """Validate the transaction, sign it, submit it to a node and store it in the account. """ - return Transaction.from_dict(self._call_account_method( + return TransactionWithMetadata.from_dict(self._call_account_method( 'signAndSubmitTransaction', { 'preparedTransactionData': prepared_transaction_data } )) def submit_and_store_transaction( - self, signed_transaction_data: SignedTransactionData) -> Transaction: + self, signed_transaction_data: SignedTransactionData) -> TransactionWithMetadata: """Submit and store transaction. """ - return Transaction.from_dict(self._call_account_method( + return TransactionWithMetadata.from_dict(self._call_account_method( 'submitAndStoreTransaction', { 'signedTransactionData': signed_transaction_data } )) def claim_outputs( - self, output_ids_to_claim: List[OutputId]) -> Transaction: + self, output_ids_to_claim: List[OutputId]) -> TransactionWithMetadata: """Claim outputs. """ - return Transaction.from_dict(self._call_account_method( + return TransactionWithMetadata.from_dict(self._call_account_method( 'claimOutputs', { 'outputIdsToClaim': output_ids_to_claim } )) def send_outputs( - self, outputs: List[Output], options: Optional[TransactionOptions] = None) -> Transaction: + self, outputs: List[Output], options: Optional[TransactionOptions] = None) -> TransactionWithMetadata: """Send outputs in a transaction. """ - return Transaction.from_dict(self._call_account_method( + return TransactionWithMetadata.from_dict(self._call_account_method( 'sendOutputs', { 'outputs': outputs, 'options': options, diff --git a/bindings/python/iota_sdk/wallet/prepared_transaction.py b/bindings/python/iota_sdk/wallet/prepared_transaction.py index c2a9e0b802..3620e44692 100644 --- a/bindings/python/iota_sdk/wallet/prepared_transaction.py +++ b/bindings/python/iota_sdk/wallet/prepared_transaction.py @@ -6,7 +6,7 @@ from typing import TYPE_CHECKING, Dict, Union from dacite import from_dict -from iota_sdk.types.transaction import Transaction +from bindings.python.iota_sdk.types.transaction_with_metadata import TransactionWithMetadata from iota_sdk.types.transaction_data import PreparedTransactionData # Required to prevent circular import @@ -42,7 +42,7 @@ def prepared_transaction_data(self) -> PreparedTransactionData: self.prepared_transaction_data_dto, PreparedTransactionData) else from_dict( PreparedTransactionData, self.prepared_transaction_data_dto) - def send(self) -> Transaction: + def send(self) -> TransactionWithMetadata: """Send a transaction. Internally just calls `sign_and_submit_transaction`. Returns: @@ -51,13 +51,13 @@ def send(self) -> Transaction: return self.sign_and_submit_transaction() def sign(self): - """Sign a prepared transaction essence using the account's private key and returns - the signed transaction essence. + """Sign a prepared transaction using the account's private key and returns + the signed transaction. """ - return self.account.sign_transaction_essence( + return self.account.sign_transaction( self.prepared_transaction_data()) - def sign_and_submit_transaction(self) -> Transaction: + def sign_and_submit_transaction(self) -> TransactionWithMetadata: """Sign and submit a transaction using prepared transaction data. Returns: diff --git a/bindings/python/tests/test_block.py b/bindings/python/tests/test_block.py index 222af92562..8a76a91b87 100644 --- a/bindings/python/tests/test_block.py +++ b/bindings/python/tests/test_block.py @@ -85,22 +85,21 @@ def test_basic_block_with_tx_payload(): "shallowLikeParents": [], "maxBurnedMana": "180500", "payload": {"type": 1, - "essence": {"type": 1, - "networkId": "1856588631910923207", - "inputs": [{"type": 0, - "transactionId": "0xc6765035e75e319e9cd55ab16e7619f6cd658e7f421c71d9fe276c77fdf3f5b3", - "transactionOutputIndex": 1}], - "inputsCommitment": "0x2468f946993ac949c890d7f895797c6b86075dc1e1556f04f3772903eaf51932", - "outputs": [{"type": 3, - "amount": "1000000", - "unlockConditions": [{"type": 0, - "address": {"type": 0, - "pubKeyHash": "0xa119005b26d46fc74cf9188b3cef8d01623e68146741ee698cabefd425dc01be"}}]}, - {"type": 3, - "amount": "995000000", - "unlockConditions": [{"type": 0, - "address": {"type": 0, - "pubKeyHash": "0xa119005b26d46fc74cf9188b3cef8d01623e68146741ee698cabefd425dc01be"}}]}]}, + "transaction": { + "networkId": "1856588631910923207", + "inputs": [{"type": 0, + "transactionId": "0xc6765035e75e319e9cd55ab16e7619f6cd658e7f421c71d9fe276c77fdf3f5b3", + "transactionOutputIndex": 1}], + "outputs": [{"type": 3, + "amount": "1000000", + "unlockConditions": [{"type": 0, + "address": {"type": 0, + "pubKeyHash": "0xa119005b26d46fc74cf9188b3cef8d01623e68146741ee698cabefd425dc01be"}}]}, + {"type": 3, + "amount": "995000000", + "unlockConditions": [{"type": 0, + "address": {"type": 0, + "pubKeyHash": "0xa119005b26d46fc74cf9188b3cef8d01623e68146741ee698cabefd425dc01be"}}]}]}, "unlocks": [{"type": 0, "signature": {"type": 0, "publicKey": "0xa7af600976f440ec97d7bddbf17eacf0bfbf710e8cfb4ae3eae475d4ae8e1b16", @@ -108,7 +107,7 @@ def test_basic_block_with_tx_payload(): block = BasicBlock.from_dict(block_dict) assert block.to_dict() == block_dict assert isinstance(block.payload, get_args(Payload)) - assert block.payload.type == PayloadType.Transaction + assert block.payload.type == PayloadType.SignedTransaction @pytest.mark.skip(reason="https://github.com/iotaledger/iota-sdk/issues/1387") @@ -117,8 +116,8 @@ def test_basic_block_with_tx_payload_all_output_types(): "type": 0, "strongParents": [ "0x053296e7434e8a4d602f8db30a5aaf16c01140212fe79d8132137cda1c38a60a", "0x559ec1d9a31c55bd27588ada2ade70fb5b13764ddd600e29c3b018761ba30e15", "0xe78e8cdbbeda89e3408eed51b77e0db5ba035f5f3bf79a8365435bba40697693", "0xee9d6e45dbc080694e6c827fecbc31ad9f654cf57404bc98f4cbca033f8e3139"], "weakParents": [], "shallowLikeParents": [], "payload": { - "type": 1, "essence": { - "type": 1, "networkId": "1856588631910923207", "inputs": [ + "type": 1, "transaction": { + "networkId": "1856588631910923207", "inputs": [ { "type": 0, "transactionId": "0xa49f5a764c3fe22f702b5b238a75a648faae1863f61c14fac51ba58d26acb823", "transactionOutputIndex": 9}, { "type": 0, "transactionId": "0x6f23b39ebe433f8b522d2e4360186cd3e6b21baf46c0a591c801161e505330b4", "transactionOutputIndex": 0}, { @@ -249,7 +248,7 @@ def test_basic_block_with_tx_payload_all_output_types(): block = BasicBlock.from_dict(block_dict) assert block.to_dict() == block_dict assert isinstance(block.payload, get_args(Payload)) - assert block.payload.type == PayloadType.Transaction + assert block.payload.type == PayloadType.SignedTransaction @pytest.mark.skip(reason="https://github.com/iotaledger/iota-sdk/issues/1387") @@ -264,28 +263,28 @@ def test_basic_block_with_tx_payload_with_tagged_data_payload(): "shallowLikeParents": [], "maxBurnedMana": "180500", "payload": {"type": 1, - "essence": {"type": 1, - "networkId": "1856588631910923207", - "inputs": [{"type": 0, - "transactionId": "0xeccfbdb73c0a4c9c0301b53a17e5aa301fbf0b079db9e88ff0e32e9e64214b28", - "transactionOutputIndex": 5}, - {"type": 0, - "transactionId": "0xf8052938858750c9c69b92b615a685fa2bb5833912b264142fc724e9510b0d0e", - "transactionOutputIndex": 0}], - "inputsCommitment": "0x9702f2a625db14db2f67289828a9fdbe342477393572b9165b19964b2449061a", - "outputs": [{"type": 3, - "amount": "1000000", - "unlockConditions": [{"type": 0, - "address": {"type": 0, - "pubKeyHash": "0x60200bad8137a704216e84f8f9acfe65b972d9f4155becb4815282b03cef99fe"}}]}, - {"type": 3, - "amount": "50600", - "unlockConditions": [{"type": 0, - "address": {"type": 0, - "pubKeyHash": "0x74e8b1f10396eb5e8aeb16d666416802722436a88b5dd1a88e59c170b724c9cc"}}]}], - "payload": {"type": 5, - "tag": "0x746167", - "data": "0x64617461"}}, + "transaction": { + "networkId": "1856588631910923207", + "inputs": [{"type": 0, + "transactionId": "0xeccfbdb73c0a4c9c0301b53a17e5aa301fbf0b079db9e88ff0e32e9e64214b28", + "transactionOutputIndex": 5}, + {"type": 0, + "transactionId": "0xf8052938858750c9c69b92b615a685fa2bb5833912b264142fc724e9510b0d0e", + "transactionOutputIndex": 0}], + "inputsCommitment": "0x9702f2a625db14db2f67289828a9fdbe342477393572b9165b19964b2449061a", + "outputs": [{"type": 3, + "amount": "1000000", + "unlockConditions": [{"type": 0, + "address": {"type": 0, + "pubKeyHash": "0x60200bad8137a704216e84f8f9acfe65b972d9f4155becb4815282b03cef99fe"}}]}, + {"type": 3, + "amount": "50600", + "unlockConditions": [{"type": 0, + "address": {"type": 0, + "pubKeyHash": "0x74e8b1f10396eb5e8aeb16d666416802722436a88b5dd1a88e59c170b724c9cc"}}]}], + "payload": {"type": 5, + "tag": "0x746167", + "data": "0x64617461"}}, "unlocks": [{"type": 0, "signature": {"type": 0, "publicKey": "0x67b7fc3f78763c9394fc4fcdb52cf3a973b6e064bdc3defb40a6cb2c880e6f5c", @@ -295,4 +294,4 @@ def test_basic_block_with_tx_payload_with_tagged_data_payload(): block = BasicBlock.from_dict(block_dict) assert block.to_dict() == block_dict assert isinstance(block.payload, get_args(Payload)) - assert block.payload.type == PayloadType.Transaction + assert block.payload.type == PayloadType.SignedTransaction From 4edd75ebbf689581bc57f75c3c218634a08e7d5d Mon Sep 17 00:00:00 2001 From: Alex Coats Date: Wed, 1 Nov 2023 16:17:53 -0400 Subject: [PATCH 2/4] remove stupid auto imports --- bindings/python/iota_sdk/types/payload.py | 2 +- bindings/python/iota_sdk/types/transaction_data.py | 2 +- bindings/python/iota_sdk/utils.py | 2 +- bindings/python/iota_sdk/wallet/account.py | 2 +- bindings/python/iota_sdk/wallet/prepared_transaction.py | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/bindings/python/iota_sdk/types/payload.py b/bindings/python/iota_sdk/types/payload.py index 245edb9409..dd222b435a 100644 --- a/bindings/python/iota_sdk/types/payload.py +++ b/bindings/python/iota_sdk/types/payload.py @@ -6,7 +6,7 @@ from typing import Any, Dict, List, TypeAlias, Union from dataclasses import dataclass, field from iota_sdk.types.common import HexStr, json -from bindings.python.iota_sdk.types.transaction import Transaction +from iota_sdk.types.transaction import Transaction from iota_sdk.types.unlock import SignatureUnlock, ReferenceUnlock diff --git a/bindings/python/iota_sdk/types/transaction_data.py b/bindings/python/iota_sdk/types/transaction_data.py index 5aa4687444..0f38781bb4 100644 --- a/bindings/python/iota_sdk/types/transaction_data.py +++ b/bindings/python/iota_sdk/types/transaction_data.py @@ -7,7 +7,7 @@ from iota_sdk.types.address import Address from iota_sdk.types.output import Output from iota_sdk.types.output_metadata import OutputMetadata -from bindings.python.iota_sdk.types.transaction import Transaction +from iota_sdk.types.transaction import Transaction from iota_sdk.types.payload import SignedTransactionPayload from iota_sdk.types.signature import Bip44 from iota_sdk.types.common import json diff --git a/bindings/python/iota_sdk/utils.py b/bindings/python/iota_sdk/utils.py index 0cb6a0b68b..687a507d9c 100644 --- a/bindings/python/iota_sdk/utils.py +++ b/bindings/python/iota_sdk/utils.py @@ -8,7 +8,7 @@ from iota_sdk.types.signature import Ed25519Signature from iota_sdk.types.address import Address, deserialize_address from iota_sdk.types.common import HexStr -from bindings.python.iota_sdk.types.transaction import Transaction +from iota_sdk.types.transaction import Transaction from iota_sdk.types.node_info import ProtocolParameters from iota_sdk.types.output_id import OutputId from iota_sdk.types.output import Output diff --git a/bindings/python/iota_sdk/wallet/account.py b/bindings/python/iota_sdk/wallet/account.py index 9f02809950..03feccfe02 100644 --- a/bindings/python/iota_sdk/wallet/account.py +++ b/bindings/python/iota_sdk/wallet/account.py @@ -20,7 +20,7 @@ from iota_sdk.types.output_params import OutputParams from iota_sdk.types.transaction_data import PreparedTransactionData, SignedTransactionData from iota_sdk.types.send_params import CreateAccountOutputParams, CreateNativeTokenParams, MintNftParams, SendNativeTokensParams, SendNftParams, SendParams -from bindings.python.iota_sdk.types.transaction_with_metadata import TransactionWithMetadata +from iota_sdk.types.transaction_with_metadata import TransactionWithMetadata from iota_sdk.types.transaction_options import TransactionOptions from iota_sdk.types.consolidation_params import ConsolidationParams diff --git a/bindings/python/iota_sdk/wallet/prepared_transaction.py b/bindings/python/iota_sdk/wallet/prepared_transaction.py index 3620e44692..80c3fde12e 100644 --- a/bindings/python/iota_sdk/wallet/prepared_transaction.py +++ b/bindings/python/iota_sdk/wallet/prepared_transaction.py @@ -6,7 +6,7 @@ from typing import TYPE_CHECKING, Dict, Union from dacite import from_dict -from bindings.python.iota_sdk.types.transaction_with_metadata import TransactionWithMetadata +from iota_sdk.types.transaction_with_metadata import TransactionWithMetadata from iota_sdk.types.transaction_data import PreparedTransactionData # Required to prevent circular import From e443f9def7e36be9e85d41b707143bc67963a25e Mon Sep 17 00:00:00 2001 From: Alex Coats Date: Wed, 1 Nov 2023 17:28:56 -0400 Subject: [PATCH 3/4] order matters ;-; --- bindings/python/iota_sdk/types/transaction.py | 4 ++-- .../python/iota_sdk/types/transaction_with_metadata.py | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/bindings/python/iota_sdk/types/transaction.py b/bindings/python/iota_sdk/types/transaction.py index 79a6fd11a5..8fa4934843 100644 --- a/bindings/python/iota_sdk/types/transaction.py +++ b/bindings/python/iota_sdk/types/transaction.py @@ -30,8 +30,8 @@ class Transaction: inputs: The inputs to consume in order to fund the outputs of the Transaction Payload. allotments: The allotments of Mana which which will be added upon commitment of the slot. capabilities: The capability bitflags of the transaction. - payload: An optional tagged data payload outputs: The outputs that are created by the Transaction Payload + payload: An optional tagged data payload """ network_id: str creation_slot: SlotIndex @@ -39,8 +39,8 @@ class Transaction: inputs: List[UtxoInput] allotments: List[ManaAllotment] capabilities: HexStr = field(default='0x', init=False) - payload: Optional[Payload] = None outputs: List[Output] + payload: Optional[Payload] = None def with_capabilities(self, capabilities: bytes): """Sets the transaction capabilities from a byte array. diff --git a/bindings/python/iota_sdk/types/transaction_with_metadata.py b/bindings/python/iota_sdk/types/transaction_with_metadata.py index 7dee2854fa..53dba6cd44 100644 --- a/bindings/python/iota_sdk/types/transaction_with_metadata.py +++ b/bindings/python/iota_sdk/types/transaction_with_metadata.py @@ -32,21 +32,21 @@ class TransactionWithMetadata: Attributes: payload: The transaction payload. - block_id: The ID of the block that holds the transaction. inclusion_state: The inclusion state of the transaction. timestamp: The timestamp of the transaction. transaction_id: The ID of the corresponding transaction. network_id: The ID of the network this transaction was issued in. incoming: Indicates whether the transaction was created by the wallet or whether it was sent by someone else and is incoming. - note: A note attached to the transaction. inputs: The inputs of the transaction. + note: A note attached to the transaction. + block_id: The ID of the block that holds the transaction. """ payload: SignedTransactionPayload - block_id: Optional[HexStr] = None inclusion_state: InclusionState timestamp: int transaction_id: HexStr network_id: int incoming: bool - note: Optional[str] = None inputs = List[OutputWithMetadata] + note: Optional[str] = None + block_id: Optional[HexStr] = None From 70575173471380db830e0ace7c12dbfbc6bb4520 Mon Sep 17 00:00:00 2001 From: Alex Coats Date: Thu, 2 Nov 2023 13:51:48 -0400 Subject: [PATCH 4/4] nit --- .../examples/how_tos/nft_collection/00_mint_issuer_nft.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/python/examples/how_tos/nft_collection/00_mint_issuer_nft.py b/bindings/python/examples/how_tos/nft_collection/00_mint_issuer_nft.py index 159217f0ae..36e2897b9e 100644 --- a/bindings/python/examples/how_tos/nft_collection/00_mint_issuer_nft.py +++ b/bindings/python/examples/how_tos/nft_collection/00_mint_issuer_nft.py @@ -39,7 +39,7 @@ transaction = tx.payload.transaction -for outputIndex, output in enumerate(transaction["outputs"]): +for outputIndex, output in enumerate(transaction.outputs): # New minted NFT id is empty in the output if output["type"] == 6 and output["nftId"] == '0x0000000000000000000000000000000000000000000000000000000000000000': outputId = Utils.compute_output_id(