Example #1
0
    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,
            },
        )
Example #2
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)
Example #3
0
    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),
        )
Example #4
0
    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,
        )
Example #5
0
    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,
                },
            },
        )
Example #6
0
    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,
            )
Example #7
0
    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)
Example #8
0
 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", []))
Example #9
0
    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", [])
Example #10
0
    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
Example #11
0
    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,
        )
Example #12
0
 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)
Example #13
0
 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)
Example #14
0
 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()},
     )
Example #15
0
 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},
     )
Example #16
0
    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,
            )