Source code for pyacryl2.utils.address

"""
pyacryl2.utils.address
~~~~~~~~~~~~~~~~~~~~~~

Acryl address
"""

import base64
import json
import math
import struct
import time
from functools import wraps

import base58

from pyacryl2.client import DEFAULT_NODE_ADDRESS, AcrylClient, CHAIN_ID_NAMES
from pyacryl2.utils.crypto import sign_with_private_key


DEFAULT_ADDRESS_VERSION = 1

DEFAULT_TRANSFER_TRANSACTION_FEE = 100000
DEFAULT_LEASE_TRANSACTION_FEE = 100000
DEFAULT_ALIAS_TRANSACTION_FEE = 100000
DEFAULT_ISSUE_TRANSACTION_FEE = 100000000
DEFAULT_REISSUE_TRANSACTION_FEE = 100000000
DEFAULT_BURN_TRANSACTION_FEE = 100000
DEFAULT_MASS_TRANSFER_TRANSACTION_FEE = 100000
DEFAULT_CANCEL_LEASE_TRANSACTION_FEE = 100000
DEFAULT_SPONSORSHIP_TRANSACTION_FEE = 100000000
DEFAULT_SET_SCRIPT_TRANSACTION_FEE = 1000000
DEFAULT_SET_ASSET_SCRIPT_TRANSACTION_FEE = 100000000
DEFAULT_DATA_TRANSACTION_FEE_MULTIPLICATOR = 1000000

TRANSACTION_TYPE_GENESIS = 1
TRANSACTION_TYPE_PAYMENT = 2
TRANSACTION_TYPE_ISSUE = 3
TRANSACTION_TYPE_TRANSFER = 4
TRANSACTION_TYPE_REISSUE = 5
TRANSACTION_TYPE_BURN = 6
TRANSACTION_TYPE_EXCHANGE = 7
TRANSACTION_TYPE_LEASE = 8
TRANSACTION_TYPE_CANCEL_LEASE = 9
TRANSACTION_TYPE_ALIAS = 10
TRANSACTION_TYPE_MASS_TRANSFER = 11
TRANSACTION_TYPE_DATA = 12
TRANSACTION_TYPE_SET_SCRIPT = 13
TRANSACTION_TYPE_SPONSORSHIP = 14
TRANSACTION_TYPE_SET_ASSET_SCRIPT = 15
TRANSACTION_TYPE_INVOKE_SCRIPT = 16

DATA_TRANSACTION_INT_TYPE = 0
DATA_TRANSACTION_BOOLEAN_TYPE = 1
DATA_TRANSACTION_STRING_TYPE = 2
DATA_TRANSACTION_BINARY_TYPE = 3

DEFAULT_TRANSACTION_VERSION = 1


[docs]def sign_required(method): """ Decorator. Check if address can sign request data, if not then raises ValueError :param method: address class method :return: wrapped method :rtype: Callable :raises: ValueError """ @wraps(method) def wrapper(*args, **kwargs): if not args[0].can_sign: raise ValueError("Can't sign request: address has not private key") return method(*args, **kwargs) return wrapper
[docs]class BaseAcrylAddress: """ Base address class. Has methods for transaction data generation, common for child address classes :param value: address text value in base58 :param private_key: address private key string in base58 :param public_key: address public key string in base58 :param address_seed: address seed :param chain_id: address chain id :param nonce: nonce :param node_address: node API address for data retrieve and transaction broadcast :param version: address version (currently, only for information) :param online: make requests or return only request data :param client_request_params: client API request param (check API client doc) """ def __init__(self, value=None, private_key=None, public_key=None, address_seed=None, chain_id=None, nonce=0, node_address=DEFAULT_NODE_ADDRESS, version=DEFAULT_ADDRESS_VERSION, online=True, client_request_params=None): self.value = value self.private_key = private_key self.public_key = public_key self.seed = address_seed self.chain_id = chain_id if not self.chain_id and self.value: self.chain_id = chr(base58.b58decode(self.value)[1]) self.nonce = nonce self.node_address = node_address self.version = version self.online = online self.client_request_params = client_request_params self._api_client = None
[docs] def save_as_json(self, file_path, encode_seed=False): """ Save address data as json :param file_path: file path :param encode_seed: encode seed to base58 :return: nothing :rtype: None """ file_data = { "address": self.value, "private_key": self.private_key, "public_key": self.public_key, "seed": base58.b58encode(self.seed).decode() if encode_seed else self.seed, "chain_id": self.chain_id } with open(file_path, 'w') as json_file: json.dump(file_data, json_file)
[docs] def load_from_json(self, file_path, decode_seed=False): """ Get address data from json file :param file_path: file path :param decode_seed: decode seed from base58 :return: nothing :rtype: None """ with open(file_path, 'r') as json_file: file_data = json.load(json_file) self.value = file_data.get('address') self.private_key = file_data.get('private_key') self.public_key = file_data.get('public_key') self.seed = file_data.get('seed') if self.seed and decode_seed: self.seed = base58.b58decode(self.seed) self.chain_id = file_data.get('chain_id')
def _generate_asset_sponsorship_transaction(self, asset_id, min_sponsored_asset_fee, transaction_fee, timestamp): """ Prepare data for sponsorship transaction :param asset_id: :param min_sponsored_asset_fee: :param transaction_fee: :param timestamp: :return: """ if timestamp == 0: timestamp_param = int(time.time() * 1000) else: timestamp_param = timestamp version = 1 sign_data = [ TRANSACTION_TYPE_SPONSORSHIP.to_bytes(1, 'big'), version.to_bytes(1, 'big'), base58.b58decode(self.public_key), base58.b58decode(asset_id), struct.pack(">Q", min_sponsored_asset_fee), struct.pack(">Q", transaction_fee), struct.pack(">Q", timestamp_param), ] signature = sign_with_private_key(self.private_key, b''.join(sign_data)) transaction_data = { "type": TRANSACTION_TYPE_SPONSORSHIP, "version": version, "senderPublicKey": self.public_key, "assetId": asset_id, "fee": transaction_fee, "timestamp": timestamp_param, "minSponsoredAssetFee": min_sponsored_asset_fee, "proofs": [signature] } return transaction_data def _generate_alias_transaction(self, alias, transaction_fee, timestamp): """ Prepare data for alias transaction :return: """ if timestamp == 0: timestamp_param = int(time.time() * 1000) else: timestamp_param = timestamp alias_data = b''.join(( b'\x02', self.chain_id.encode('latin-1'), struct.pack(">H", len(alias)), alias.encode('latin-1') )) sign_data = [ TRANSACTION_TYPE_ALIAS.to_bytes(1, 'big'), base58.b58decode(self.public_key), struct.pack(">H", len(alias_data)), alias_data, struct.pack(">Q", transaction_fee), struct.pack(">Q", timestamp_param), ] signature = sign_with_private_key(self.private_key, b''.join(sign_data)) transaction_data = { "senderPublicKey": self.public_key, "alias": alias, "fee": transaction_fee, "timestamp": timestamp_param, "signature": signature, } return transaction_data def _generate_transfer_transaction(self, recipient, asset_id, fee_asset_id, amount, attachment, transaction_fee, timestamp): """ Prepare data for transfer transaction :param recipient: :param amount: :param attachment: :param transaction_fee: :param timestamp: :return: """ if isinstance(recipient, AcrylAddress): recipient_address = recipient.value else: recipient_address = recipient if timestamp == 0: timestamp_param = int(time.time() * 1000) else: timestamp_param = timestamp if not attachment: encoded_attachment = b'' else: encoded_attachment = attachment.encode('latin-1') if asset_id: asset_sign_data = b'\1%s' % base58.b58decode(asset_id) else: asset_sign_data = b'\0' if fee_asset_id: fee_asset_sign_data = b'\1%s' % base58.b58decode(fee_asset_id) else: fee_asset_sign_data = b'\0' sign_data = [ TRANSACTION_TYPE_TRANSFER.to_bytes(1, 'big'), base58.b58decode(self.public_key), asset_sign_data, fee_asset_sign_data, struct.pack(">Q", timestamp_param), struct.pack(">Q", amount), struct.pack(">Q", transaction_fee), base58.b58decode(recipient_address), struct.pack(">H", len(b'' or encoded_attachment)), encoded_attachment ] signature = sign_with_private_key(self.private_key, b''.join(sign_data)) transaction_data = { "senderPublicKey": self.public_key, "recipient": recipient_address, "amount": amount, "fee": transaction_fee, "timestamp": timestamp_param, "attachment": base58.b58encode(encoded_attachment).decode(), "signature": signature, } if asset_id: transaction_data["assetId"] = asset_id if fee_asset_id: transaction_data["feeAssetId"] = fee_asset_id return transaction_data def _generate_asset_issue_transaction(self, name, description, quantity, decimals, reissuable, transaction_fee, script, version, timestamp): """ Prepare asset issue transaction data :param name: :param description: :param quantity: :param decimals: :param reissuable: :param version :param timestamp: :return: """ if not timestamp: timestamp_param = int(time.time() * 1000) else: timestamp_param = timestamp sign_data = [ TRANSACTION_TYPE_ISSUE.to_bytes(1, 'big'), base58.b58decode(self.public_key), struct.pack(">H", len(name)), name.encode('latin-1'), struct.pack(">H", len(description)), description.encode('latin-1'), struct.pack(">Q", quantity), struct.pack(">B", decimals), reissuable.to_bytes(1, 'big'), struct.pack(">Q", transaction_fee), struct.pack(">Q", timestamp_param) ] transaction_data = { "senderPublicKey": self.public_key, "name": name, "quantity": quantity, "timestamp": timestamp_param, "description": description, "decimals": decimals, "reissuable": reissuable, "fee": transaction_fee, } if version > 1: sign_data.insert(1, version.to_bytes(1, 'big')) sign_data.insert(2, self.chain_id.encode('latin-1')) transaction_data.update({ "type": TRANSACTION_TYPE_ISSUE, "senderPublicKey": self.public_key, "version": version, "chainId": self.chain_id }) if script: if version < 2: raise ValueError("Smart assets require at least 2 transaction version") compiled_script = base64.b64decode(script) sign_data.extend([ b'\1', # smart asset struct.pack(">H", len(compiled_script)), compiled_script ]) transaction_data["script"] = 'base64:' + script else: if version >= 2: sign_data.append(b'\0') signature = sign_with_private_key(self.private_key, b''.join(sign_data)) if version == 1: transaction_data["signature"] = signature else: transaction_data["proofs"] = [signature] return transaction_data def _generate_asset_reissue_transaction(self, asset_id, quantity, reissuable, transaction_fee, timestamp): """ Prepare asset reissue transaction data :param asset_id: :param quantity: :param reissuable: :param timestamp: :return: """ if timestamp == 0: timestamp_param = int(time.time() * 1000) else: timestamp_param = timestamp sign_data = [ TRANSACTION_TYPE_REISSUE.to_bytes(1, 'big'), base58.b58decode(self.public_key), base58.b58decode(asset_id), struct.pack(">Q", quantity), reissuable.to_bytes(1, 'big'), struct.pack(">Q", transaction_fee), struct.pack(">Q", timestamp_param) ] signature = sign_with_private_key(self.private_key, b''.join(sign_data)) transaction_data = { "senderPublicKey": self.public_key, "assetId": asset_id, "quantity": quantity, "timestamp": timestamp_param, "reissuable": reissuable, "fee": transaction_fee, "signature": signature } return transaction_data def _generate_asset_burn_transaction(self, asset_id, quantity, transaction_fee, timestamp): """ Prepare asset reissue transaction data :param asset_id: :param quantity: :param reissuable: :param timestamp: :return: """ if timestamp == 0: timestamp_param = int(time.time() * 1000) else: timestamp_param = timestamp sign_data = [ TRANSACTION_TYPE_BURN.to_bytes(1, 'big'), base58.b58decode(self.public_key), base58.b58decode(asset_id), struct.pack(">Q", quantity), struct.pack(">Q", transaction_fee), struct.pack(">Q", timestamp_param) ] signature = sign_with_private_key(self.private_key, b''.join(sign_data)) transaction_data = { "senderPublicKey": self.public_key, "assetId": asset_id, "quantity": quantity, "timestamp": timestamp_param, "fee": transaction_fee, "signature": signature } return transaction_data def _generate_data_transaction(self, data, fee=0, version=1, timestamp=0): """ Prepare data for data transaction :return: """ if not timestamp: timestamp_param = int(time.time() * 1000) else: timestamp_param = timestamp data_buffer = [] for item in data: key_encoded = item['key'].encode('latin-1') data_buffer.extend([struct.pack(">H", len(key_encoded)), key_encoded]) if item['type'] == 'integer': item_value = [ DATA_TRANSACTION_INT_TYPE.to_bytes(1, 'big'), struct.pack(">Q", item['value']) ] elif item['type'] == 'boolean': item_value = [ DATA_TRANSACTION_BOOLEAN_TYPE.to_bytes(1, 'big'), item['value'].to_bytes(1, 'big') ] elif item['type'] == 'binary': item_value = [ DATA_TRANSACTION_STRING_TYPE.to_bytes(1, 'big'), struct.pack(">H", len(item['value'])), item['value'] ] item['value'] = "base64:" + base64.b64encode(item['value']).decode('latin-1') elif item['type'] == 'string': item_value = [ DATA_TRANSACTION_BINARY_TYPE.to_bytes(1, 'big'), struct.pack(">H", len(item['value'])), item['value'].encode('latin-1') ] else: raise ValueError("Unknown data type: '{}'".format(item['type'])) data_buffer.extend(item_value) if not fee: transaction_fee = int(math.floor(1 + (len(json.dumps(data)) + 8 - 1) / 1024) * DEFAULT_DATA_TRANSACTION_FEE_MULTIPLICATOR) else: transaction_fee = fee sign_data = [ TRANSACTION_TYPE_DATA.to_bytes(1, 'big'), version.to_bytes(1, 'big'), base58.b58decode(self.public_key), struct.pack(">H", len(data)), b''.join(data_buffer), struct.pack(">Q", timestamp_param), struct.pack(">Q", transaction_fee), ] transaction_data = { "type": TRANSACTION_TYPE_DATA, "version": version, "senderPublicKey": self.public_key, "data": data, "fee": transaction_fee, "timestamp": timestamp_param, "proofs": [sign_with_private_key(self.private_key, b''.join(sign_data))] } return transaction_data def _generate_lease_transaction(self, recipient, amount, transaction_fee, timestamp): """ Prepare data for lease transaction :param recipient: :param amount: :param transaction_fee: :param timestamp: :return: """ if isinstance(recipient, AcrylAddress): recipient_address = recipient.value else: recipient_address = recipient if timestamp == 0: timestamp_param = int(time.time() * 1000) else: timestamp_param = timestamp sign_data = [ TRANSACTION_TYPE_LEASE.to_bytes(1, 'big'), base58.b58decode(self.public_key), base58.b58decode(recipient_address), struct.pack(">Q", amount), struct.pack(">Q", transaction_fee), struct.pack(">Q", timestamp_param), ] signature = sign_with_private_key(self.private_key, b''.join(sign_data)) transaction_data = { "senderPublicKey": self.public_key, "recipient": recipient_address, "amount": amount, "fee": transaction_fee, "timestamp": timestamp_param, "signature": signature } return transaction_data def _generate_cancel_lease_transaction(self, transaction_id, transaction_fee, timestamp): """ Prepare data for cancel lease transaction :param transaction_id: :param transaction_fee: :param timestamp: :return: """ if timestamp == 0: timestamp_param = int(time.time() * 1000) else: timestamp_param = timestamp sign_data = [ TRANSACTION_TYPE_CANCEL_LEASE.to_bytes(1, 'big'), base58.b58decode(self.public_key), struct.pack(">Q", transaction_fee), struct.pack(">Q", timestamp_param), base58.b58decode(transaction_id), ] signature = sign_with_private_key(self.private_key, b''.join(sign_data)) transaction_data = { "senderPublicKey": self.public_key, "txId": transaction_id, "fee": transaction_fee, "timestamp": timestamp_param, "signature": signature } return transaction_data def _generate_mass_transfer_transaction(self, transfer_data, asset_id, attachment, version, timestamp): """ Setup mass transfer transaction data :param transfer_data: :param attachment: :param timestamp: :return: """ if not timestamp: timestamp_param = int(time.time() * 1000) else: timestamp_param = timestamp if not attachment: encoded_attachment = b'' else: encoded_attachment = attachment.encode('latin-1') mass_fee = 100000 + math.ceil(0.5 * len(transfer_data)) * 100000 recipients_sign_data = [] for recipient_data in transfer_data: recipients_sign_data.append(base58.b58decode(recipient_data['recipient'])) recipients_sign_data.append(struct.pack(">Q", recipient_data['amount'])) sign_data = [ TRANSACTION_TYPE_MASS_TRANSFER.to_bytes(1, 'big'), version.to_bytes(1, 'big'), base58.b58decode(self.public_key), b'\0', # for default asset (Acryl) struct.pack(">H", len(transfer_data)), b''.join(recipients_sign_data), struct.pack(">Q", timestamp_param), struct.pack(">Q", mass_fee), struct.pack(">H", len(encoded_attachment)), encoded_attachment ] if asset_id: sign_data[3] = b'\1' sign_data.insert(4, base58.b58decode(asset_id)) signature = sign_with_private_key(self.private_key, b''.join(sign_data)) transaction_data = { "type": TRANSACTION_TYPE_MASS_TRANSFER, "version": 1, "assetId": asset_id or "", "senderPublicKey": self.public_key, "fee": mass_fee, "timestamp": timestamp_param, "transfers": transfer_data, "attachment": base58.b58encode(encoded_attachment).decode(), "signature": signature, "proofs": [ signature ] } return transaction_data def _generate_set_script_transaction(self, script, transaction_fee, timestamp, version): """ Generate set script transaction data :param script: :param transaction_fee: :return: """ if not timestamp: timestamp_param = int(time.time() * 1000) else: timestamp_param = timestamp script_bytes = base64.b64decode(script) sign_data = [ TRANSACTION_TYPE_SET_SCRIPT.to_bytes(1, 'big'), version.to_bytes(1, 'big'), self.chain_id.encode('latin-1'), base58.b58decode(self.public_key), b'\1', struct.pack(">H", len(script_bytes)), script_bytes, struct.pack(">Q", transaction_fee), struct.pack(">Q", timestamp_param), ] signature = sign_with_private_key(self.private_key, b''.join(sign_data)) transaction_data = { "type": TRANSACTION_TYPE_SET_SCRIPT, "version": version, "senderPublicKey": self.public_key, "fee": transaction_fee, "timestamp": timestamp_param, "script": 'base64:' + script, "proofs": [signature] } return transaction_data def _generate_set_asset_script_transaction(self, script, asset_id, transaction_fee, timestamp, version): """ Generate set script transaction data :param asset_id: :param script: :param transaction_fee: :return: """ if not timestamp: timestamp_param = int(time.time() * 1000) else: timestamp_param = timestamp script_bytes = base64.b64decode(script) sign_data = [ TRANSACTION_TYPE_SET_ASSET_SCRIPT.to_bytes(1, 'big'), version.to_bytes(1, 'big'), self.chain_id.encode('latin-1'), base58.b58decode(self.public_key), base58.b58decode(asset_id), struct.pack(">Q", transaction_fee), struct.pack(">Q", timestamp_param), b'\1', struct.pack(">H", len(script_bytes)), script_bytes, ] signature = sign_with_private_key(self.private_key, b''.join(sign_data)) transaction_data = { "type": TRANSACTION_TYPE_SET_ASSET_SCRIPT, "version": version, "assetId": asset_id, "senderPublicKey": self.public_key, "fee": transaction_fee, "timestamp": timestamp_param, "script": 'base64:' + script, "proofs": [signature] } return transaction_data @property def can_sign(self): """ Ability to sign requests :return: yes or no :rtype: bool """ return bool(self.private_key) @property def chain(self): """ Address chain name :return: chain name :rtype: str """ chains_dict = dict(CHAIN_ID_NAMES) return chains_dict[self.chain_id] @property def client(self): """ Current API client instance :return: API client instance """ return self._api_client @property def base58_seed(self): """ Seed encoded base58 :return: seed in base58 :rtype: bytes """ return base58.b58encode(self.seed.encode('latin-1')).decode()
[docs]class AcrylAddress(BaseAcrylAddress): """ Acryl address class. Simplifies transaction data generation and data requests :param value: address text value in base58 :param private_key: address private key string in base58 :param public_key: address public key string in base58 :param address_seed: address seed :param chain_id: address chain id :param nonce: nonce """ def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._api_client = AcrylClient( node_address=self.node_address, chain_id=self.chain_id, online=self.online, request_params=self.client_request_params )
[docs] def from_alias(self, alias): """ Set address value from alias :param alias: alias of address :return: address object with address value """ address_data = self._api_client.alias_by_alias(alias) address_bytes = base58.b58decode(address_data["address"]) self.value = address_data["address"] self.private_key = None self.public_key = None self.seed = None self.chain_id = chr(address_bytes[1]) self.nonce = None self.version = int(address_bytes[0])
[docs] def get_balance(self): """ Get address balance :return: balance value :rtype: int or dict """ data = self._api_client.address_balance(self.value) if not self.online: return data return data["balance"]
[docs] def get_effective_balance(self): """ Get address effective balance :return: balance value :rtype: int or dict """ data = self._api_client.address_effective_balance(self.value) if not self.online: return data return data["balance"]
[docs] def get_confirmed_balance(self, confirmations): """ Get address balance :return: balance value :rtype: int or dict """ data = self._api_client.address_balance_confirmed(self.value, confirmations) if not self.online: return data return data["balance"]
[docs] def get_assets(self): """ Get address assets :return: asset balances in dict :rtype: int or dict """ data = self._api_client.assets_balance(self.value) if not self.online: return data return data["balances"]
[docs] def get_address_data(self): """ Get address data from blockchain :return: data in dict :rtype: dict """ data = self._api_client.address_data_address(self.value) if not self.online: return data return data
[docs] def get_aliases(self, flat=True): """ Get address aliases :param flat: get only alias names without chain ids :return: list of dicts with prefix, chain ids and alias names or only alias names :rtype: list or dict """ aliases = [] data = self._api_client.alias_by_address(self.value) if not self.online: return data for alias_data_string in data.response_data: prefix, chain_id, alias = alias_data_string.split(":") if flat: aliases.append(alias) else: aliases.append({"chain_id": chain_id, "alias": alias, "prefix": prefix}) return aliases
[docs] def validate(self): """ Validate address :return: :rtype bool or dict """ data = self._api_client.address_validate(self.value) if not self.online: return data return data["valid"]
[docs] def get_address_info(self): """ Collect address info (balances, assets, data) :return: address info dict :rtype: dict """ address_info = dict() address_info["valid"] = self.validate() if not address_info["valid"]: return address_info address_info["balance"] = self.get_balance() address_info["effective_balance"] = self.get_effective_balance() address_info["assets"] = self.get_assets() address_info["address_data"] = self.get_address_data() return address_info
[docs] @sign_required def data_transaction(self, data, fee=0, version=DEFAULT_TRANSACTION_VERSION, timestamp=0): """ Create data transaction :param data: data for data transaction (list of dicts with keys type, key, value) Suitable python types for transaction data types: - boolean - `bool` - binary - `bytes` (converts them to base64 string) - integer - `int` - string - `str` :type data: list :param version: data transaction version :type fee: int :param fee: transaction fee. 1000000 is minimum. :type version: int :param timestamp: transaction timestamp :type timestamp: int :return: client request result :rtype: AcrylClientResponse or dict """ transaction_data = self._generate_data_transaction(data, fee, version, timestamp) result = self._api_client.transaction_broadcast(transaction_data) return result
[docs] @sign_required def transfer_acryl(self, recipient, amount, attachment=None, transaction_fee=DEFAULT_TRANSFER_TRANSACTION_FEE, timestamp=0): """ Send acryl to address :param recipient: recipient address in base58 :type recipient: str or AcrylAddress or AcrylAsyncAddress :param amount: amount of acryl :type amount: int :param attachment: attachment string :type attachment: str :param transaction_fee: fee for transfer transaction :type transaction_fee: int :param timestamp: timestamp of transaction :type timestamp: int :return: transfer result :rtype: AcrylClientResponse or dict """ transaction_data = self._generate_transfer_transaction( recipient, None, None, amount, attachment, transaction_fee, timestamp ) result = self._api_client.asset_broadcast_transfer(transaction_data) return result
[docs] @sign_required def transfer_asset(self, recipient, asset_id, fee_asset_id, amount, attachment=None, transaction_fee=DEFAULT_TRANSFER_TRANSACTION_FEE, timestamp=0): """ Send asset to address. If asset_id or fee_asset_id is None then acryl will be used :param recipient: recipient address in base58 :type recipient: str or AcrylAddress or AcrylAsyncAddress :param asset_id: asset id :type asset_id: str or None :param fee_asset_id: fee asset id :type fee_asset_id: str or None :param amount: amount of acryl :type amount: int :param attachment: attachment string :type attachment: str :param transaction_fee: fee for transfer transaction :type transaction_fee: int :param timestamp: timestamp of transaction :type timestamp: int :return: transfer result :rtype: AcrylClientResponse or dict """ transaction_data = self._generate_transfer_transaction( recipient, asset_id, fee_asset_id, amount, attachment, transaction_fee, timestamp ) result = self._api_client.asset_broadcast_transfer(transaction_data) return result
[docs] @sign_required def mass_transfer_acryl(self, transfer_data, attachment=None, timestamp=None): """ Mass transfer acryl :param transfer_data: list of dicts with recipient and amount i.e. `[{ 'recipient': '3N1xca2DY8AEwqRDAJpzUgY99eq8J9h4rB3', 'amount': 1000 }]` :param attachment: transaction attachment :param transaction_fee: mass transfer transaction fee :param timestamp: transaction timestamp :return: :rtype: AcrylClientResponse or dict """ transaction_data = self._generate_mass_transfer_transaction( transfer_data, None, attachment, DEFAULT_TRANSACTION_VERSION, timestamp) result = self._api_client.transaction_broadcast(transaction_data) return result
[docs] @sign_required def mass_transfer_assets(self, transfer_data, asset_id=None, attachment=None, version=DEFAULT_TRANSACTION_VERSION, timestamp=None): """ Mass transfer acryl :param transfer_data: list of dicts with recipient and amount i.e. `[{ 'recipient': '3N1xca2DY8AEwqRDAJpzUgY99eq8J9h4rB3', 'amount': 1000 }]` :param attachment: transaction attachment :param asset_id: ID of transferring asset :param timestamp: transaction timestamp :return: """ transaction_data = self._generate_mass_transfer_transaction( transfer_data, asset_id, attachment, version, timestamp ) result = self._api_client.transaction_broadcast(transaction_data) return result
[docs] @sign_required def lease_acryl(self, recipient, amount, transaction_fee=DEFAULT_LEASE_TRANSACTION_FEE, timestamp=0): """ Lease acryl to address :param recipient: :param amount: :param transaction_fee: :param timestamp: :return: """ transaction_data = self._generate_lease_transaction(recipient, amount, transaction_fee, timestamp) result = self._api_client.leasing_broadcast_lease(transaction_data) return result
[docs] @sign_required def lease_cancel(self, transaction_id, transaction_fee=DEFAULT_CANCEL_LEASE_TRANSACTION_FEE, timestamp=0): """ Cancel acryl lease :param transaction_id: :param transaction_fee: :param timestamp: :return: """ transaction_data = self._generate_cancel_lease_transaction(transaction_id, transaction_fee, timestamp) result = self._api_client.leasing_broadcast_cancel_lease(transaction_data) return result
[docs] @sign_required def create_alias(self, alias, transaction_fee=DEFAULT_ALIAS_TRANSACTION_FEE, timestamp=0): """ Create alias for address :param alias: alias (min 4, max 30 chars) :param transaction_fee: :param timestamp: :return: """ transaction_data = self._generate_alias_transaction(alias, transaction_fee, timestamp) result = self._api_client.alias_broadcast_create(transaction_data) return result
[docs] @sign_required def issue_asset(self, name, description, quantity, decimals, reissuable, transaction_fee=DEFAULT_ISSUE_TRANSACTION_FEE, version=DEFAULT_TRANSACTION_VERSION, timestamp=0): """ Issue asset in acryl blockchain :param name: asset name (min 4, max 16 chars) :param description: asset description :param quantity: asset quantity :param decimals: asset decimals :param reissuable: is asset reissuable :param transaction_fee: asset issue transaction fee :param version: transaction version :param timestamp: transaction timestamp :return: """ transaction_data = self._generate_asset_issue_transaction( name, description, quantity, decimals, reissuable, transaction_fee, None, version, timestamp ) if version == 1: result = self._api_client.asset_broadcast_issue(transaction_data) else: result = self._api_client.transaction_broadcast(transaction_data) return result
[docs] @sign_required def issue_smart_asset(self, name, description, quantity, decimals, reissuable, script, transaction_fee=DEFAULT_ISSUE_TRANSACTION_FEE, timestamp=0): """ Issue smart asset in acryl blockchain (asset with script) :param name: asset name (min 4, max 16 chars) :param description: asset description :param quantity: asset quantity :param decimals: asset decimals :param reissuable: is asset reissuable :param transaction_fee: asset issue transaction fee :param timestamp: transaction timestamp :return: """ transaction_data = self._generate_asset_issue_transaction( name, description, quantity, decimals, reissuable, transaction_fee, script, 2, timestamp ) result = self._api_client.transaction_broadcast(transaction_data) return result
[docs] @sign_required def reissue_asset(self, asset_id, quantity, reissuable, transaction_fee=DEFAULT_REISSUE_TRANSACTION_FEE, timestamp=0): """ Reissue asset in acryl blockchain :param asset_id: asset id :param quantity: asset quantity :param transaction_fee: :param timestamp: transaction timestamp :return: """ transaction_data = self._generate_asset_reissue_transaction( asset_id, quantity, reissuable, transaction_fee, timestamp ) result = self._api_client.asset_broadcast_reissue(transaction_data) return result
[docs] @sign_required def burn_asset(self, asset_id, quantity, transaction_fee=DEFAULT_BURN_TRANSACTION_FEE, timestamp=0): """ Burn asset :param asset_id: asset id :param quantity: asset quantity :param transaction_fee: :param timestamp: transaction timestamp :return: """ transaction_data = self._generate_asset_burn_transaction(asset_id, quantity, transaction_fee, timestamp) result = self._api_client.asset_broadcast_burn(transaction_data) return result
[docs] @sign_required def asset_sponsorship(self, asset_id, min_sponsored_asset_fee, transaction_fee=DEFAULT_SPONSORSHIP_TRANSACTION_FEE, timestamp=0): """ Sponsor asset :param asset_id: :param min_sponsored_asset_fee: :param transaction_fee: :param timestamp: :return: """ transaction_data = self._generate_asset_sponsorship_transaction( asset_id, min_sponsored_asset_fee, transaction_fee, timestamp ) result = self._api_client.transaction_broadcast(transaction_data) return result
[docs] @sign_required def set_script(self, script, transaction_fee=DEFAULT_SET_SCRIPT_TRANSACTION_FEE, timestamp=None, version=DEFAULT_TRANSACTION_VERSION): """ Set script for account :param script: :param transaction_fee: :param timestamp: :param version: :return: """ transaction_data = self._generate_set_script_transaction(script, transaction_fee, timestamp, version) result = self._api_client.transaction_broadcast(transaction_data) return result
[docs] @sign_required def set_asset_script(self, script, asset_id, transaction_fee=DEFAULT_SET_ASSET_SCRIPT_TRANSACTION_FEE, timestamp=None, version=DEFAULT_TRANSACTION_VERSION): """ Set script for asset :param script: :param asset_id: :param transaction_fee: :param timestamp: :param version: :return: """ transaction_data = self._generate_set_asset_script_transaction( script, asset_id, transaction_fee, timestamp, version ) result = self._api_client.transaction_broadcast(transaction_data) return result
def __repr__(self): return "AcrylAddress({})".format(self.value)