Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

python: block types and wrapper #1346

Merged
merged 31 commits into from
Oct 4, 2023
Merged
Show file tree
Hide file tree
Changes from 29 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
2e3a55e
block types and wrapper
Alex6323 Sep 28, 2023
ac62da5
format
Alex6323 Sep 28, 2023
b1869e7
fix examples
Alex6323 Sep 28, 2023
4d6f7e8
nit
Alex6323 Sep 28, 2023
5b160f8
review 1
Alex6323 Sep 28, 2023
d0cc109
review 2
Alex6323 Sep 29, 2023
c2aeaad
review 3
Alex6323 Sep 29, 2023
ebc15e8
Merge branch '2.0' into python/block-changes
Alex6323 Sep 29, 2023
0d04825
fix wrapper deserialization, temp. disable some tests
Alex6323 Sep 29, 2023
501d60f
Merge branch '2.0' into python/block-changes
Alex6323 Sep 29, 2023
3fc8393
update BlockMetadata type
Alex6323 Sep 29, 2023
8a4fc2d
fix some tests
Alex6323 Sep 29, 2023
0220d4e
test nits
Alex6323 Sep 29, 2023
b0ccc9f
remove union for sig
Alex6323 Sep 29, 2023
20aa2f0
doc fix
Alex6323 Sep 29, 2023
a044634
lint sdk
Alex6323 Sep 29, 2023
29d9f6d
full circle
Alex6323 Sep 29, 2023
0f2b64a
review 4
Alex6323 Sep 29, 2023
15f7168
review 5
Alex6323 Sep 29, 2023
7afa497
review 6
Alex6323 Sep 29, 2023
9c76bb4
Merge branch '2.0' into python/block-changes
Alex6323 Oct 2, 2023
e3c6cf0
review 7
Alex6323 Oct 2, 2023
573eae9
did I mess up?
Alex6323 Oct 2, 2023
0cb5955
not ignore some tests
Alex6323 Oct 3, 2023
3dffaa6
Merge branch '2.0' into python/block-changes
Alex6323 Oct 3, 2023
177f07c
remove import
Alex6323 Oct 3, 2023
fc249b7
fix block tests
Alex6323 Oct 3, 2023
9a9f7fe
refer to issue in ignored tests
Alex6323 Oct 3, 2023
5e543cd
fix ci
Alex6323 Oct 4, 2023
55ce115
re-enable python tests in CI
Alex6323 Oct 4, 2023
09cfa59
long live the union (type alias)
Alex6323 Oct 4, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,5 @@
print(f'Block metadata: {json.dumps(asdict(metadata), indent=4)}')

# Request the block by its id
block = client.get_block_data(block_ids[0])
block = client.get_block(block_ids[0])
print(f'Block: {json.dumps(asdict(block), indent=4)}')
22 changes: 13 additions & 9 deletions bindings/python/examples/client/08_data_block.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import os
from dataclasses import asdict
from dotenv import load_dotenv
from iota_sdk import Client, utf8_to_hex, hex_to_utf8, TaggedDataPayload
from iota_sdk import BasicBlock, Client, utf8_to_hex, hex_to_utf8, TaggedDataPayload

load_dotenv()

Expand All @@ -13,17 +13,21 @@
client = Client(nodes=[node_url])

# Create and post a block with a tagged data payload
block = client.submit_payload(
block_id = client.submit_payload(
TaggedDataPayload(
utf8_to_hex("tag"),
utf8_to_hex("data")))
utf8_to_hex("data")))[0]

print(f'Data block sent: {os.environ["EXPLORER_URL"]}/block/{block[0]}')
print(f'Data block sent: {os.environ["EXPLORER_URL"]}/block/{block_id}')

block = client.get_block_data(block[0])
print(f'Block data: {json.dumps(asdict(block), indent=4)}')
block = client.get_block(block_id).block

payload = block.payload
if isinstance(block, BasicBlock):
print(f'Block data: {json.dumps(asdict(block), indent=4)}')

if payload and 'data' in payload and payload['data']:
print(f'Decoded data: { hex_to_utf8(payload["data"]) }')
payload = block.payload

if payload and 'data' in payload and payload['data']:
print(f'Decoded data: { hex_to_utf8(payload["data"]) }')
else:
raise ValueError("block must be an instance of BasicBlock")
23 changes: 13 additions & 10 deletions bindings/python/examples/client/submit_and_read_block.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
# Make sure you have first installed it with `pip install iota_sdk`
import os
from dotenv import load_dotenv
from iota_sdk import Client, hex_to_utf8, utf8_to_hex, TaggedDataPayload
from iota_sdk import BasicBlock, Client, hex_to_utf8, utf8_to_hex, TaggedDataPayload

load_dotenv()

Expand Down Expand Up @@ -82,15 +82,18 @@
metadata = client.get_block_metadata(block_id)

# Get the whole block
block = client.get_block_data(block_id)
payload_out = block.payload
tag_hex_out = block.payload.tag
message_hex_out = block.payload.data

# Unpackage the payload (from hex to text)
message_out = hex_to_utf8(message_hex_out)
print('\nYour message, read from the Shimmer network:')
print(f' {message_out}')
block = client.get_block(block_id).block
if isinstance(block, BasicBlock):
payload_out = block.payload
tag_hex_out = block.payload.tag
message_hex_out = block.payload.data

# Unpackage the payload (from hex to text)
message_out = hex_to_utf8(message_hex_out)
print('\nYour message, read from the Shimmer network:')
print(f' {message_out}')
else:
raise ValueError("block must be an instance of BasicBlock")

# Or see the message online, with the testnet explorer.
print(
Expand Down
6 changes: 5 additions & 1 deletion bindings/python/iota_sdk/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@
from .prefix_hex import *
from .types.address import *
from .types.balance import *
from .types.block import *
from .types.block.basic import *
from .types.block.block import *
from .types.block.metadata import *
from .types.block.wrapper import *
from .types.block.validation import *
from .types.block_builder_options import *
from .types.burn import *
from .types.client_options import *
Expand Down
6 changes: 3 additions & 3 deletions bindings/python/iota_sdk/client/_high_level_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from typing import List, Optional
from dataclasses import dataclass
from abc import ABCMeta, abstractmethod
from iota_sdk.types.block import Block
from iota_sdk.types.block.wrapper import BlockWrapper
from iota_sdk.types.common import CoinType, HexStr, json
from iota_sdk.types.output_metadata import OutputWithMetadata
from iota_sdk.types.output_id import OutputId
Expand Down Expand Up @@ -94,7 +94,7 @@ def get_outputs_ignore_errors(
})
return [OutputWithMetadata.from_dict(o) for o in outputs]

def find_blocks(self, block_ids: List[HexStr]) -> List[Block]:
def find_blocks(self, block_ids: List[HexStr]) -> List[BlockWrapper]:
"""Find all blocks by provided block IDs.

Args:
Expand All @@ -106,7 +106,7 @@ def find_blocks(self, block_ids: List[HexStr]) -> List[Block]:
blocks = self._call_method('findBlocks', {
'blockIds': block_ids
})
return [Block.from_dict(block) for block in blocks]
return [BlockWrapper.from_dict(block) for block in blocks]

def find_inputs(self, addresses: List[str], amount: int):
"""Function to find inputs from addresses for a provided amount(useful for offline signing).
Expand Down
13 changes: 7 additions & 6 deletions bindings/python/iota_sdk/client/_node_core_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
from abc import ABCMeta, abstractmethod
from dacite import from_dict

from iota_sdk.types.block import Block, BlockMetadata
from iota_sdk.types.block.wrapper import BlockWrapper
from iota_sdk.types.block.metadata import BlockMetadata
from iota_sdk.types.common import HexStr
from iota_sdk.types.node_info import NodeInfo, NodeInfoWrapper
from iota_sdk.types.output_metadata import OutputWithMetadata, OutputMetadata
Expand Down Expand Up @@ -57,7 +58,7 @@ def get_tips(self) -> List[HexStr]:
"""
return self._call_method('getTips')

def post_block(self, block: Block) -> HexStr:
def post_block(self, block: BlockWrapper) -> HexStr:
"""Post a block.

Args:
Expand All @@ -70,10 +71,10 @@ def post_block(self, block: Block) -> HexStr:
'block': block.__dict__
})

def get_block_data(self, block_id: HexStr) -> Block:
def get_block(self, block_id: HexStr) -> BlockWrapper:
"""Get the block corresponding to the given block id.
"""
return Block.from_dict(self._call_method('getBlock', {
return BlockWrapper.from_dict(self._call_method('getBlock', {
'blockId': block_id
}))

Expand Down Expand Up @@ -127,13 +128,13 @@ def get_output_metadata(
'outputId': output_id_str
}))

def get_included_block(self, transaction_id: HexStr) -> Block:
def get_included_block(self, transaction_id: HexStr) -> BlockWrapper:
"""Returns the included block of the given transaction.

Returns:
The included block.
"""
return Block.from_dict(self._call_method('getIncludedBlock', {
return BlockWrapper.from_dict(self._call_method('getIncludedBlock', {
'transactionId': transaction_id
}))

Expand Down
7 changes: 4 additions & 3 deletions bindings/python/iota_sdk/client/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
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 import Block
from iota_sdk.types.block.wrapper import BlockWrapper
from iota_sdk.types.common import HexStr, Node
from iota_sdk.types.feature import Feature
from iota_sdk.types.native_token import NativeToken
Expand Down Expand Up @@ -394,7 +394,8 @@ def sign_transaction(
'preparedTransactionData': prepared_transaction_data
}))

def submit_payload(self, payload: Payload) -> List[Union[HexStr, Block]]:
def submit_payload(
self, payload: Payload) -> List[Union[HexStr, BlockWrapper]]:
"""Submit a payload in a block.

Args:
Expand All @@ -406,7 +407,7 @@ def submit_payload(self, payload: Payload) -> List[Union[HexStr, Block]]:
result = self._call_method('postBlockPayload', {
'payload': payload.to_dict()
})
result[1] = Block.from_dict(result[1])
result[1] = BlockWrapper.from_dict(result[1])
return result

def listen_mqtt(self, topics: List[str], handler):
Expand Down
33 changes: 33 additions & 0 deletions bindings/python/iota_sdk/types/block/basic.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Copyright 2023 IOTA Stiftung
# SPDX-License-Identifier: Apache-2.0

from __future__ import annotations
from dataclasses import dataclass, field
from typing import List, Optional, Union
from iota_sdk.types.block.block import Block, BlockType
from iota_sdk.types.common import HexStr, json
from iota_sdk.types.payload import TaggedDataPayload, TransactionPayload


@json
@dataclass
class BasicBlock(Block):
"""A `BasicBlock` is the most common type of block used to issue various kinds of payloads such as transactions
at the cost of burning Mana.
thibault-martinez marked this conversation as resolved.
Show resolved Hide resolved

Attributes:
strong_parents: Blocks that are strongly directly approved.
weak_parents: Blocks that are weakly directly approved.
shallow_like_parents: Blocks that are directly referenced to adjust opinion.
max_burned_mana: The amount of Mana the Account identified by the IssuerId is at most willing to burn for this block.
payload: The optional payload of this block.
"""
strong_parents: List[HexStr]
weak_parents: List[HexStr]
shallow_like_parents: List[HexStr]
max_burned_mana: str
payload: Optional[Union[TaggedDataPayload,
TransactionPayload]] = None
thibault-martinez marked this conversation as resolved.
Show resolved Hide resolved
type: int = field(
default_factory=lambda: BlockType.Basic,
init=False)
26 changes: 26 additions & 0 deletions bindings/python/iota_sdk/types/block/block.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Copyright 2023 IOTA Stiftung
# SPDX-License-Identifier: Apache-2.0

from __future__ import annotations
from enum import IntEnum
from dataclasses import dataclass
from iota_sdk.types.common import json


class BlockType(IntEnum):
"""Block types.

Attributes:
Basic (0): A Basic Block.
Validation (1): A Validation Block.
"""
Basic = 0
Validation = 1


@json
@dataclass
class Block:
"""Base class for blocks.
"""
type: int
Loading
Loading