Skip to content

Commit

Permalink
get account accepts bytes, address or hex
Browse files Browse the repository at this point in the history
  • Loading branch information
janezpodhostnik committed Feb 20, 2023
1 parent 467bf87 commit 690f0b2
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 32 deletions.
52 changes: 27 additions & 25 deletions examples/get_account_examples.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ async def run(self, ctx: Config):
host=ctx.access_node_host, port=ctx.access_node_port
) as client:
account = await client.get_account(
address=ctx.service_account_address.bytes
# pass address as cadence.Address object
address=ctx.service_account_address
)
self.log.info(f"Account Address: {account.address.hex()}")
self.log.info(f"Account Balance: {account.balance}")
Expand All @@ -42,7 +43,8 @@ async def run(self, ctx: Config):
) as client:
_, _, _ = await random_account(client=client, ctx=ctx)
account = await client.get_account_at_latest_block(
address=ctx.service_account_address.bytes
# pass address as hex string
address=ctx.service_account_address.hex()
)
self.log.info(f"Account Address: {account.address.hex()}")
self.log.info(f"Account Balance: {account.balance}")
Expand All @@ -53,26 +55,26 @@ async def run(self, ctx: Config):
# -------------------------------------------------------------------------
# Get an account by address at the given block height.
# -------------------------------------------------------------------------
# SKIP DUE TO EMULATOR BUG
# class GetAccountAtBlockHeightExample(Example):
# def __init__(self) -> None:
# super().__init__(
# tag="GA.3.", name="GetAccountAtBlockHeightExample", sort_order=903
# )
#
# async def run(self, ctx: Config):
# # First Step : Create a client to connect to the flow blockchain
# # flow_client function creates a client using the host and port
# async with flow_client(
# host=ctx.access_node_host, port=ctx.access_node_port
# ) as client:
# latest_block = await client.get_latest_block()
# _, _, _ = await random_account(client=client, ctx=ctx)
# account = await client.get_account_at_block_height(
# address=ctx.service_account_address.bytes,
# block_height=latest_block.height,
# )
# print("Account Address: {}".format(account.address.hex()))
# print("Account Balance: {}".format(account.balance))
# print("Account Contracts: {}".format(len(account.contracts)))
# print("Account Keys: {}".format(len(account.keys)))
class GetAccountAtBlockHeightExample(Example):
def __init__(self) -> None:
super().__init__(
tag="GA.3.", name="GetAccountAtBlockHeightExample", sort_order=903
)

async def run(self, ctx: Config):
# First Step : Create a client to connect to the flow blockchain
# flow_client function creates a client using the host and port
async with flow_client(
host=ctx.access_node_host, port=ctx.access_node_port
) as client:
latest_block = await client.get_latest_block()
_, _, _ = await random_account(client=client, ctx=ctx)
account = await client.get_account_at_block_height(
# pass address as bytes
address=ctx.service_account_address.bytes,
block_height=latest_block.height,
)
self.log.info(f"Account Address: {account.address.hex()}")
self.log.info(f"Account Balance: {account.balance}")
self.log.info(f"Account Contracts: {len(account.contracts)}")
self.log.info(f"Account Keys: {len(account.keys)}")
31 changes: 30 additions & 1 deletion flow_py_sdk/cadence/address.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
from __future__ import annotations

from flow_py_sdk.cadence.value import Value
import flow_py_sdk.cadence.constants as c

from flow_py_sdk.exceptions import NotAddressError


class Address(Value):
address_length = 8
Expand Down Expand Up @@ -35,9 +39,34 @@ def encode_value(self) -> dict:
def decode(cls, value) -> "Address":
addr = str(value[c.valueKey])
if addr[:2] != "0x":
raise Exception() # TODO
raise NotAddressError.from_value(addr) # TODO
return Address.from_hex(addr)

@classmethod
def type_str(cls) -> str:
return c.addressTypeStr

@classmethod
def convert_to_bytes(cls, address: bytes | Address | str) -> bytes:
"""
Converts an address to bytes if it is not already bytes.
Parameters
----------
address : bytes | Address | str
The address to convert to bytes
Can be bytes, Address, or hex string
Returns
-------
bytes
The address as bytes
"""
if isinstance(address, bytes):
return address
elif isinstance(address, Address):
return address.bytes
elif isinstance(address, str):
return Address.from_hex(address).bytes
else:
raise NotAddressError.from_value(address)
21 changes: 15 additions & 6 deletions flow_py_sdk/client/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from grpclib.encoding.base import CodecBase, StatusDetailsCodecBase
from grpclib.metadata import Deadline

from flow_py_sdk import cadence
from flow_py_sdk.cadence import Value, cadence_object_hook, encode_arguments
from flow_py_sdk.client import entities
from flow_py_sdk.proto.flow.access import (
Expand Down Expand Up @@ -194,54 +195,61 @@ async def get_transaction(self, *, id: bytes = b"") -> entities.Transaction:
response = await super().get_transaction(id=id)
return entities.Transaction.from_proto(response.transaction)

async def get_account(self, *, address: bytes = b"") -> entities.Account:
async def get_account(
self, *, address: bytes | cadence.Address | str = b""
) -> entities.Account:
"""
Get an account using its address.
Parameters
----------
address : bytes
address : bytes | cadence.Address | str
Address of requested account.
Can be a bytes, cadence.Address or hex str.
Returns
-------
entities.Account
Return requested account.
"""
address = cadence.Address.convert_to_bytes(address)
response = await super().get_account(address=address)
return entities.Account.from_proto(response.account)

async def get_account_at_latest_block(
self, *, address: bytes = b""
self, *, address: bytes | cadence.Address | str = b""
) -> entities.Account:
"""
Get an account by address at the latest sealed block.
Parameters
----------
address : bytes
address : bytes | cadence.Address | str
Address of requested account.
Can be a bytes, cadence.Address or hex str.
Returns
-------
entities.Account
Return requested account.
"""
address = cadence.Address.convert_to_bytes(address)
response = await super().get_account_at_latest_block(address=address)
return entities.Account.from_proto(response.account)

async def get_account_at_block_height(
self, *, address: bytes = b"", block_height: int = 0
self, *, address: bytes | cadence.Address | str = b"", block_height: int = 0
) -> entities.Account:
"""
Get an account by address at the given block height.
Parameters
----------
address : bytes
address : bytes | cadence.Address | str
Address of requested account.
Can be a bytes, cadence.Address or hex str.
block_height : int
Desired block height.
Expand All @@ -251,6 +259,7 @@ async def get_account_at_block_height(
Return requested account.
"""
address = cadence.Address.convert_to_bytes(address)
response = await super().get_account_at_block_height(
address=address, block_height=block_height
)
Expand Down
6 changes: 6 additions & 0 deletions flow_py_sdk/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,9 @@ class CadenceEncodingError(PySDKError):

class CadenceIncorrectTypeError(PySDKError):
pass


class NotAddressError(PySDKError):
@classmethod
def from_value(cls, value) -> "NotAddressError":
return NotAddressError(f"Value {value} is not a cadence address.")
23 changes: 23 additions & 0 deletions tests/test_address.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
from unittest import TestCase

from flow_py_sdk.cadence import Address
from flow_py_sdk.exceptions import NotAddressError


class TestAddress(TestCase):
def test_convert_to_bytes(self):
with self.subTest(msg="Pass address as bytes"):
address = Address.from_hex("0x01")
self.assertEqual(address.bytes, Address.convert_to_bytes(address.bytes))

with self.subTest(msg="Pass address as Address"):
address = Address.from_hex("0x01")
self.assertEqual(address.bytes, Address.convert_to_bytes(address))

with self.subTest(msg="Pass address as hex string"):
address = Address.from_hex("0x01")
self.assertEqual(address.bytes, Address.convert_to_bytes(address.hex()))

with self.subTest(msg="Pass address as unknown"):
with self.assertRaises(NotAddressError):
Address.convert_to_bytes(1)

0 comments on commit 690f0b2

Please sign in to comment.