def asset_issue( self, owner: TAddress, abbr: str, total_supply: int, *, url: str, name: str = None, description: str = "", start_time: int = None, end_time: int = None, precision: int = 6, frozen_supply: list = None, trx_num: int = 1, num: int = 1, ) -> AsyncTransactionBuilder: """Issue a TRC10 token. Almost all parameters have resonable defaults. """ if name is None: name = abbr if start_time is None: # use default expiration start_time = current_timestamp() + 60_000 if end_time is None: # use default expiration end_time = current_timestamp() + 60_000 + 1 if frozen_supply is None: frozen_supply = [] return self._build_transaction( "AssetIssueContract", { "owner_address": keys.to_hex_address(owner), "abbr": abbr.encode().hex(), "name": name.encode().hex(), "total_supply": total_supply, "precision": precision, "url": url.encode().hex(), "description": description.encode().hex(), "start_time": start_time, "end_time": end_time, "frozen_supply": frozen_supply, "trx_num": trx_num, "num": num, "public_free_asset_net_limit": 0, "free_asset_net_limit": 0, }, )
def is_note_spent(self, zkey: dict, note: dict) -> bool: """Is a note spent.""" payload = dict(note) payload["shielded_TRC20_contract_address"] = keys.to_hex_address(self.shielded.contract_address) if "position" not in note: payload["position"] = 0 payload["ak"] = zkey["ak"] payload["nk"] = zkey["nk"] ret = self._client.provider.make_request("wallet/isshieldedtrc20contractnotespent", payload) return ret.get('is_spent', None)
def account_permission_update(self, owner: TAddress, perm: dict) -> "AsyncTransactionBuilder": """Update account permission. :param owner: Address of owner :param perm: Permission dict from :meth:`~tronpy.Tron.get_account_permission` """ if 'owner' in perm: for key in perm['owner']['keys']: key['address'] = keys.to_hex_address(key['address']) if 'actives' in perm: for act in perm['actives']: for key in act['keys']: key['address'] = keys.to_hex_address(key['address']) if perm.get('witness', None): for key in perm['witness']['keys']: key['address'] = keys.to_hex_address(key['address']) return self._build_transaction( "AccountPermissionUpdateContract", dict(owner_address=keys.to_hex_address(owner), **perm), )
async def mint( self, taddr: str, zaddr: str, amount: int, memo: str = "") -> "tronpy.async_tron.AsyncTransactionBuilder": """Mint, transfer from T-address to z-address.""" rcm = await self.get_rcm() payload = { "from_amount": str(amount), "shielded_receives": { "note": { "value": amount // self.scale_factor, "payment_address": zaddr, "rcm": rcm, "memo": memo.encode().hex(), } }, "shielded_TRC20_contract_address": keys.to_hex_address(self.shielded.contract_address), } ret = await self._client.provider.make_request( "wallet/createshieldedcontractparameters", payload) self._client._handle_api_error(ret) parameter = ret["trigger_contract_input"] function_signature = self.shielded.functions.mint.function_signature_hash return self._client.trx._build_transaction( "TriggerSmartContract", { "owner_address": keys.to_hex_address(taddr), "contract_address": keys.to_hex_address(self.shielded.contract_address), "data": function_signature + parameter, }, method=self.shielded.functions.mint, )
def deploy(self) -> Any: if self.contract_address: raise RuntimeError("this contract has already deployed to {}".format(self.contract_address)) if self.origin_address != self.owner_address: raise RuntimeError("origin address and owner address mismatch") return self._client.trx._build_transaction( "CreateSmartContract", { "owner_address": keys.to_hex_address(self.owner_address), "new_contract": { "origin_address": keys.to_hex_address(self.origin_address), "abi": {"entrys": self.abi}, "bytecode": self.bytecode, "call_value": 0, # TODO "name": self.name, "consume_user_resource_percent": self.user_resource_percent, "origin_energy_limit": self.origin_energy_limit, }, }, )
async def _async_trigger_contract(self, parameter): if self._abi.get("stateMutability", None).lower() in ["view", "pure"]: # const call, contract ret ret = await self._client.trigger_const_smart_contract_function( self._owner_address, self._contract.contract_address, self.function_signature, parameter, ) return self.parse_output(ret) else: return self._client.trx._build_transaction( "TriggerSmartContract", { "owner_address": keys.to_hex_address(self._owner_address), "contract_address": keys.to_hex_address(self._contract.contract_address), "data": self.function_signature_hash + parameter, "call_token_value": self.call_token_value, "call_value": self.call_value, "token_id": self.call_token_id, }, method=self, )
def freeze_balance(self, owner: TAddress, amount: int, resource: str = "ENERGY", *, receiver: TAddress = None) -> "TransactionBuilder": """Freeze balance to get energy or bandwidth, for 3 days. :param owner: :param amount: :param resource: Resource type, can be ``"ENERGY"`` or ``"BANDWIDTH"`` :param receiver: """ payload = { "owner_address": keys.to_hex_address(owner), "frozen_balance": amount, "frozen_duration": 3, "resource": resource, } if receiver is not None: payload["receiver_address"] = keys.to_hex_address(receiver) return self._build_transaction("FreezeBalanceContract", payload)
def scan_incoming_notes(self, zkey: dict, start_block_number: int, end_block_number: int = None) -> list: """Scan incoming notes using ivk, ak, nk.""" if end_block_number is None: end_block_number = start_block_number + 1000 payload = { "start_block_index": start_block_number, "end_block_index": end_block_number, "shielded_TRC20_contract_address": keys.to_hex_address(self.shielded.contract_address), "ivk": zkey["ivk"], "ak": zkey["ak"], "nk": zkey["nk"], } ret = self._client.provider.make_request("wallet/scanshieldedtrc20notesbyivk", payload) self._client._handle_api_error(ret) return self._fix_notes(ret.get("noteTxs", []))
def scan_outgoing_notes( self, zkey_or_ovk: Union[dict, str], start_block_number: int, end_block_number: int = None ) -> list: """Scan outgoing notes using ovk.""" if end_block_number is None: end_block_number = start_block_number + 1000 ovk = zkey_or_ovk if isinstance(zkey_or_ovk, (dict,)): ovk = zkey_or_ovk["ovk"] payload = { "start_block_index": start_block_number, "end_block_index": end_block_number, "shielded_TRC20_contract_address": keys.to_hex_address(self.shielded.contract_address), "ovk": ovk, } ret = self._client.provider.make_request("wallet/scanshieldedtrc20notesbyovk", payload) self._client._handle_api_error(ret) return ret.get("noteTxs", [])
def burn( self, zkey: dict, note: dict, *to: Union[Tuple[str, int], Tuple[str, int, str]] ) -> "tronpy.tron.TransactionBuilder": """Burn, transfer from z-address to T-address.""" spends = [] alpha = self.get_rcm() root, path = self.get_path(note.get("position", 0)) if note.get("is_spent", False): raise DoubleSpending spends.append( {"note": note["note"], "alpha": alpha, "root": root, "path": path, "pos": note.get("position", 0)} ) change_amount = 0 receives = [] to_addr = None to_amount = 0 to_memo = '' if not to: raise ValueError('burn must have a output') for receive in to: addr = receive[0] amount = receive[1] if len(receive) == 3: memo = receive[2] else: memo = "" if addr.startswith('ztron1'): change_amount += amount rcm = self.get_rcm() receives = [ {"note": {"value": amount, "payment_address": addr, "rcm": rcm, "memo": memo.encode().hex()}} ] else: # assume T-address to_addr = addr to_amount = amount to_memo = memo if note["note"]["value"] * self.scale_factor - change_amount * self.scale_factor != to_amount: raise ValueError("Balance amount is wrong") payload = { "ask": zkey["ask"], "nsk": zkey["nsk"], "ovk": zkey["ovk"], "shielded_spends": spends, "shielded_receives": receives, "to_amount": str(to_amount), "transparent_to_address": keys.to_hex_address(to_addr), "shielded_TRC20_contract_address": keys.to_hex_address(self.shielded.contract_address), } ret = self._client.provider.make_request("wallet/createshieldedcontractparameters", payload) self._client._handle_api_error(ret) parameter = ret["trigger_contract_input"] function_signature = self.shielded.functions.burn.function_signature_hash txn = self._client.trx._build_transaction( "TriggerSmartContract", { "owner_address": "410000000000000000000000000000000000000000", "contract_address": keys.to_hex_address(self.shielded.contract_address), "data": function_signature + parameter, }, method=self.shielded.functions.burn, ) if to_memo: txn = txn.memo(to_memo) return txn
def transfer( self, zkey: dict, notes: Union[list, dict], *to: Union[Tuple[str, int], Tuple[str, int, str]], ) -> "tronpy.tron.TransactionBuilder": """Transfer from z-address to z-address.""" if isinstance(notes, (dict,)): notes = [notes] assert 1 <= len(notes) <= 2 spends = [] spend_amount = 0 for note in notes: if note.get("is_spent", False): raise DoubleSpending alpha = self.get_rcm() root, path = self.get_path(note.get("position", 0)) spends.append( {"note": note["note"], "alpha": alpha, "root": root, "path": path, "pos": note.get("position", 0)} ) spend_amount += note["note"]["value"] receives = [] receive_amount = 0 for recv in to: addr = recv[0] amount = recv[1] receive_amount += amount if len(recv) == 3: memo = recv[2] else: memo = "" rcm = self.get_rcm() receives.append( {"note": {"value": amount, "payment_address": addr, "rcm": rcm, "memo": memo.encode().hex()}} ) if spend_amount != receive_amount: raise ValueError("spend amount is not equal to receive amount") payload = { "ask": zkey["ask"], "nsk": zkey["nsk"], "ovk": zkey["ovk"], "shielded_spends": spends, "shielded_receives": receives, "shielded_TRC20_contract_address": keys.to_hex_address(self.shielded.contract_address), } ret = self._client.provider.make_request("wallet/createshieldedcontractparameters", payload) self._client._handle_api_error(ret) parameter = ret["trigger_contract_input"] function_signature = self.shielded.functions.transfer.function_signature_hash return self._client.trx._build_transaction( "TriggerSmartContract", { "owner_address": "0000000000000000000000000000000000000000", "contract_address": keys.to_hex_address(self.shielded.contract_address), "data": function_signature + parameter, }, method=self.shielded.functions.transfer, )
def vote_witness(self, owner: TAddress, *votes: Tuple[TAddress, int]) -> "TransactionBuilder": """Vote for witnesses. Empty ``votes`` to clean voted.""" votes = [dict(vote_address=keys.to_hex_address(addr), vote_count=count) for addr, count in votes] payload = {"owner_address": keys.to_hex_address(owner), "votes": votes} return self._build_transaction("VoteWitnessContract", payload)
def create_witness(self, owner: TAddress, url: str) -> "TransactionBuilder": """Create a new witness, will consume 1_000 TRX.""" payload = {"owner_address": keys.to_hex_address(owner), "url": url.encode().hex()} return self._build_transaction("WitnessCreateContract", payload)
def account_update(self, owner: TAddress, name: str) -> "TransactionBuilder": """Update account name. An account can only set name once.""" return self._build_transaction( "UpdateAccountContract", {"owner_address": keys.to_hex_address(owner), "account_name": name.encode().hex()}, )
def transfer(self, from_: TAddress, to: TAddress, amount: int) -> TransactionBuilder: """Transfer TRX. ``amount`` in `SUN`.""" return self._build_transaction( "TransferContract", {"owner_address": keys.to_hex_address(from_), "to_address": keys.to_hex_address(to), "amount": amount}, )
def __call__(self, *args, **kwargs) -> "tronpy.tron.TransactionBuilder": """Call the contract method.""" parameter = "" if args and kwargs: raise ValueError( "do not mix positional arguments and keyword arguments") if len(self.inputs) == 0: if args or kwargs: raise TypeError("{} expected {} arguments".format( self.name, len(self.inputs))) elif args: if len(args) != len(self.inputs): raise TypeError( "wrong number of arguments, require {} got {}".format( len(self.inputs), len(args))) parameter = trx_abi.encode_single(self.input_type, args).hex() elif kwargs: if len(kwargs) != len(self.inputs): raise TypeError( "wrong number of arguments, require {} got {}".format( len(self.inputs), len(args))) args = [] for arg in self.inputs: try: args.append(kwargs[arg["name"]]) except KeyError: raise TypeError("missing argument '{}'".format( arg["name"])) parameter = trx_abi.encode_single(self.input_type, args).hex() else: raise TypeError("wrong number of arguments, require {}".format( len(self.inputs))) if self._abi.get("stateMutability", None).lower() in ["view", "pure"]: # const call, contract ret ret = self._client.trigger_const_smart_contract_function( self._owner_address, self._contract.contract_address, self.function_signature, parameter, ) return self.parse_output(ret) else: return self._client.trx._build_transaction( "TriggerSmartContract", { "owner_address": keys.to_hex_address(self._owner_address), "contract_address": keys.to_hex_address(self._contract.contract_address), "data": self.function_signature_hash + parameter, "call_token_value": self.call_token_value, "call_value": self.call_value, "token_id": self.call_token_id, }, method=self, )