-
Notifications
You must be signed in to change notification settings - Fork 143
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
23 changed files
with
3,198 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
version: 2.1 | ||
jobs: | ||
build: | ||
machine: | ||
image: "ubuntu-2004:202104-01" | ||
steps: | ||
- checkout | ||
- run: | ||
command: | | ||
pip3 install -r requirements.txt | ||
black --check . | ||
set -e | ||
python3 test_unit.py | ||
make docker-test |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,8 @@ | ||
unit: | ||
behave --tags="@unit.offline or @unit.algod or @unit.indexer or @unit.rekey or @unit.tealsign or @unit.dryrun or @unit.applications or @unit.responses or @unit.transactions or @unit.responses.231 or @unit.feetest or @unit.indexer.logs" test -f progress2 | ||
behave --tags="@unit.offline or @unit.algod or @unit.indexer or @unit.rekey or @unit.tealsign or @unit.dryrun or @unit.applications or @unit.responses or @unit.transactions or @unit.transactions.payment or @unit.responses.231 or @unit.feetest or @unit.indexer.logs or @unit.abijson or @unit.atomic_transaction_composer" test -f progress2 | ||
|
||
integration: | ||
behave --tags="@algod or @assets or @auction or @kmd or @send or @template or @indexer or @indexer.applications or @rekey or @compile or @dryrun or @dryrun.testing or @applications or @applications.verified or @indexer.231" test -f progress2 | ||
behave --tags="@algod or @assets or @auction or @kmd or @send or @template or @indexer or @indexer.applications or @rekey or @compile or @dryrun or @dryrun.testing or @applications or @applications.verified or @indexer.231 or @abi" test -f progress2 | ||
|
||
docker-test: | ||
./run_integration.sh |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
from . import abi | ||
from . import account | ||
from . import algod | ||
from . import auction | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
from algosdk.abi.uint_type import UintType | ||
from algosdk.abi.ufixed_type import UfixedType | ||
from algosdk.abi.base_type import ABIType | ||
from algosdk.abi.bool_type import BoolType | ||
from algosdk.abi.byte_type import ByteType | ||
from algosdk.abi.address_type import AddressType | ||
from algosdk.abi.string_type import StringType | ||
from algosdk.abi.array_dynamic_type import ArrayDynamicType | ||
from algosdk.abi.array_static_type import ArrayStaticType | ||
from algosdk.abi.tuple_type import TupleType | ||
from .method import Method, Argument, Returns | ||
from .interface import Interface | ||
from .contract import Contract | ||
|
||
name = "abi" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
from typing import Union | ||
|
||
from algosdk.abi.base_type import ABIType | ||
from algosdk.abi.byte_type import ByteType | ||
from algosdk.abi.tuple_type import TupleType | ||
from algosdk import error | ||
|
||
from algosdk import encoding | ||
|
||
|
||
class AddressType(ABIType): | ||
""" | ||
Represents an Address ABI Type for encoding. | ||
""" | ||
|
||
def __init__(self) -> None: | ||
super().__init__() | ||
|
||
def __eq__(self, other: object) -> bool: | ||
if not isinstance(other, AddressType): | ||
return False | ||
return True | ||
|
||
def __str__(self) -> str: | ||
return "address" | ||
|
||
def byte_len(self) -> int: | ||
return 32 | ||
|
||
def is_dynamic(self) -> bool: | ||
return False | ||
|
||
def _to_tuple_type(self): | ||
child_type_array = list() | ||
for _ in range(self.byte_len()): | ||
child_type_array.append(ByteType()) | ||
return TupleType(child_type_array) | ||
|
||
def encode(self, value: Union[str, bytes]) -> bytes: | ||
""" | ||
Encode an address string or a 32-byte public key into a Address ABI bytestring. | ||
Args: | ||
value (str | bytes): value to be encoded. It can be either a base32 | ||
address string or a 32-byte public key. | ||
Returns: | ||
bytes: encoded bytes of the address | ||
""" | ||
# Check that the value is an address in string or the public key in bytes | ||
if isinstance(value, str): | ||
try: | ||
value = encoding.decode_address(value) | ||
except Exception as e: | ||
raise error.ABIEncodingError( | ||
"cannot encode the following address: {}".format(value) | ||
) from e | ||
elif ( | ||
not (isinstance(value, bytes) or isinstance(value, bytearray)) | ||
or len(value) != 32 | ||
): | ||
raise error.ABIEncodingError( | ||
"cannot encode the following public key: {}".format(value) | ||
) | ||
return bytes(value) | ||
|
||
def decode(self, bytestring: Union[bytearray, bytes]) -> str: | ||
""" | ||
Decodes a bytestring to a base32 encoded address string. | ||
Args: | ||
bytestring (bytes | bytearray): bytestring to be decoded | ||
Returns: | ||
str: base32 encoded address from the encoded bytestring | ||
""" | ||
if ( | ||
not ( | ||
isinstance(bytestring, bytearray) | ||
or isinstance(bytestring, bytes) | ||
) | ||
or len(bytestring) != 32 | ||
): | ||
raise error.ABIEncodingError( | ||
"address string must be in bytes and correspond to a byte[32]: {}".format( | ||
bytestring | ||
) | ||
) | ||
# Return the base32 encoded address string | ||
return encoding.encode_address(bytestring) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
from typing import Any, List, NoReturn, Union | ||
|
||
from algosdk.abi.base_type import ABI_LENGTH_SIZE, ABIType | ||
from algosdk.abi.byte_type import ByteType | ||
from algosdk.abi.tuple_type import TupleType | ||
from algosdk import error | ||
|
||
|
||
class ArrayDynamicType(ABIType): | ||
""" | ||
Represents a ArrayDynamic ABI Type for encoding. | ||
Args: | ||
child_type (ABIType): the type of the dynamic array. | ||
Attributes: | ||
child_type (ABIType) | ||
""" | ||
|
||
def __init__(self, arg_type: ABIType) -> None: | ||
super().__init__() | ||
self.child_type = arg_type | ||
|
||
def __eq__(self, other: object) -> bool: | ||
if not isinstance(other, ArrayDynamicType): | ||
return False | ||
return self.child_type == other.child_type | ||
|
||
def __str__(self) -> str: | ||
return "{}[]".format(self.child_type) | ||
|
||
def byte_len(self) -> NoReturn: | ||
raise error.ABITypeError( | ||
"cannot get length of a dynamic type: {}".format(self) | ||
) | ||
|
||
def is_dynamic(self) -> bool: | ||
return True | ||
|
||
def _to_tuple_type(self, length: int) -> TupleType: | ||
child_type_array = [self.child_type] * length | ||
return TupleType(child_type_array) | ||
|
||
def encode(self, value_array: Union[List[Any], bytes, bytearray]) -> bytes: | ||
""" | ||
Encodes a list of values into a ArrayDynamic ABI bytestring. | ||
Args: | ||
value_array (list | bytes | bytearray): list of values to be encoded. | ||
If the child types are ByteType, then bytes or bytearray can be | ||
passed in to be encoded as well. | ||
Returns: | ||
bytes: encoded bytes of the dynamic array | ||
""" | ||
if ( | ||
isinstance(value_array, bytes) | ||
or isinstance(value_array, bytearray) | ||
) and not isinstance(self.child_type, ByteType): | ||
raise error.ABIEncodingError( | ||
"cannot pass in bytes when the type of the array is not ByteType: {}".format( | ||
value_array | ||
) | ||
) | ||
converted_tuple = self._to_tuple_type(len(value_array)) | ||
length_to_encode = len(converted_tuple.child_types).to_bytes( | ||
2, byteorder="big" | ||
) | ||
encoded = converted_tuple.encode(value_array) | ||
return bytes(length_to_encode) + encoded | ||
|
||
def decode(self, array_bytes: Union[bytes, bytearray]) -> list: | ||
""" | ||
Decodes a bytestring to a dynamic list. | ||
Args: | ||
array_bytes (bytes | bytearray): bytestring to be decoded | ||
Returns: | ||
list: values from the encoded bytestring | ||
""" | ||
if not ( | ||
isinstance(array_bytes, bytearray) | ||
or isinstance(array_bytes, bytes) | ||
): | ||
raise error.ABIEncodingError( | ||
"value to be decoded must be in bytes: {}".format(array_bytes) | ||
) | ||
if len(array_bytes) < ABI_LENGTH_SIZE: | ||
raise error.ABIEncodingError( | ||
"dynamic array is too short to be decoded: {}".format( | ||
len(array_bytes) | ||
) | ||
) | ||
|
||
byte_length = int.from_bytes( | ||
array_bytes[:ABI_LENGTH_SIZE], byteorder="big" | ||
) | ||
converted_tuple = self._to_tuple_type(byte_length) | ||
return converted_tuple.decode(array_bytes[ABI_LENGTH_SIZE:]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
import math | ||
from typing import Any, List, Union | ||
|
||
from algosdk.abi.base_type import ABIType | ||
from algosdk.abi.bool_type import BoolType | ||
from algosdk.abi.byte_type import ByteType | ||
from algosdk.abi.tuple_type import TupleType | ||
from algosdk import error | ||
|
||
|
||
class ArrayStaticType(ABIType): | ||
""" | ||
Represents a ArrayStatic ABI Type for encoding. | ||
Args: | ||
child_type (ABIType): the type of the child_types array. | ||
array_len (int): length of the static array. | ||
Attributes: | ||
child_type (ABIType) | ||
static_length (int) | ||
""" | ||
|
||
def __init__(self, arg_type: ABIType, array_len: int) -> None: | ||
if array_len < 1: | ||
raise error.ABITypeError( | ||
"static array length must be a positive integer: {}".format( | ||
array_len | ||
) | ||
) | ||
super().__init__() | ||
self.child_type = arg_type | ||
self.static_length = array_len | ||
|
||
def __eq__(self, other: object) -> bool: | ||
if not isinstance(other, ArrayStaticType): | ||
return False | ||
return ( | ||
self.child_type == other.child_type | ||
and self.static_length == other.static_length | ||
) | ||
|
||
def __str__(self) -> str: | ||
return "{}[{}]".format(self.child_type, self.static_length) | ||
|
||
def byte_len(self) -> int: | ||
if isinstance(self.child_type, BoolType): | ||
# 8 Boolean values can be encoded into 1 byte | ||
return math.ceil(self.static_length / 8) | ||
element_byte_length = self.child_type.byte_len() | ||
return self.static_length * element_byte_length | ||
|
||
def is_dynamic(self) -> bool: | ||
return self.child_type.is_dynamic() | ||
|
||
def _to_tuple_type(self) -> TupleType: | ||
child_type_array = [self.child_type] * self.static_length | ||
return TupleType(child_type_array) | ||
|
||
def encode(self, value_array: Union[List[Any], bytes, bytearray]) -> bytes: | ||
""" | ||
Encodes a list of values into a ArrayStatic ABI bytestring. | ||
Args: | ||
value_array (list | bytes | bytearray): list of values to be encoded. | ||
The number of elements must match the predefined length of array. | ||
If the child types are ByteType, then bytes or bytearray can be | ||
passed in to be encoded as well. | ||
Returns: | ||
bytes: encoded bytes of the static array | ||
""" | ||
if len(value_array) != self.static_length: | ||
raise error.ABIEncodingError( | ||
"value array length does not match static array length: {}".format( | ||
len(value_array) | ||
) | ||
) | ||
if ( | ||
isinstance(value_array, bytes) | ||
or isinstance(value_array, bytearray) | ||
) and not isinstance(self.child_type, ByteType): | ||
raise error.ABIEncodingError( | ||
"cannot pass in bytes when the type of the array is not ByteType: {}".format( | ||
value_array | ||
) | ||
) | ||
converted_tuple = self._to_tuple_type() | ||
return converted_tuple.encode(value_array) | ||
|
||
def decode(self, array_bytes: Union[bytes, bytearray]) -> list: | ||
""" | ||
Decodes a bytestring to a static list. | ||
Args: | ||
array_bytes (bytes | bytearray): bytestring to be decoded | ||
Returns: | ||
list: values from the encoded bytestring | ||
""" | ||
if not ( | ||
isinstance(array_bytes, bytearray) | ||
or isinstance(array_bytes, bytes) | ||
): | ||
raise error.ABIEncodingError( | ||
"value to be decoded must be in bytes: {}".format(array_bytes) | ||
) | ||
converted_tuple = self._to_tuple_type() | ||
return converted_tuple.decode(array_bytes) |
Oops, something went wrong.