Exemplo n.º 1
0
 def send_transaction(self, contract_address: bytes or bytearray, acct: Account, payer_acct: Account, gas_limit: int,
                      gas_price: int, func: AbiFunction, pre_exec: bool):
     if func is not None:
         params = BuildParams.serialize_abi_function(func)
     else:
         params = bytearray()
     if pre_exec:
         if isinstance(contract_address, bytes):
             tx = NeoVm.make_invoke_transaction(bytearray(contract_address), bytearray(params), b'', 0, 0)
         elif isinstance(contract_address, bytearray):
             tx = NeoVm.make_invoke_transaction(contract_address, bytearray(params), b'', 0, 0)
         else:
             raise SDKException(ErrorCode.param_err('the data type of contract address is incorrect.'))
         if acct is not None:
             self.__sdk.sign_transaction(tx, acct)
         return self.__sdk.rpc.send_raw_transaction_pre_exec(tx)
     else:
         unix_time_now = int(time())
         params.append(0x67)
         for i in contract_address:
             params.append(i)
         if payer_acct is None:
             raise SDKException(ErrorCode.param_err('payer account is None.'))
         tx = Transaction(0, 0xd1, unix_time_now, gas_price, gas_limit, payer_acct.get_address().to_array(),
                          params, bytearray(), [], bytearray())
         self.__sdk.sign_transaction(tx, acct)
         if acct.get_address_base58() != payer_acct.get_address_base58():
             self.__sdk.add_sign_transaction(tx, payer_acct)
         return self.__sdk.rpc.send_raw_transaction(tx)
    def get_smart_contract(self, contract_address: str) -> dict:
        """
        This interface is used to get the information of smart contract based on the specified hexadecimal hash value.

        :param contract_address: str, a hexadecimal hash value.
        :return: the information of smart contract in dictionary form.
        """
        if type(contract_address) != str:
            raise SDKException(
                ErrorCode.param_err(
                    'a hexadecimal contract address is required.'))
        if len(contract_address) != 40:
            raise SDKException(
                ErrorCode.param_err(
                    'the length of the contract address should be 40 bytes.'))
        payload = RpcClient.set_json_rpc_version(RPC_GET_SMART_CONTRACT,
                                                 [contract_address, 1])
        try:
            response = HttpRequest.request("post", self.addr, payload)
        except requests.exceptions.ConnectTimeout:
            raise SDKException(
                ErrorCode.other_error(''.join(['ConnectTimeout: ',
                                               self.addr])))
        except requests.exceptions.ConnectionError:
            raise SDKException(
                ErrorCode.other_error(''.join(['ConnectionError: ',
                                               self.addr])))
        contract = json.loads(response.content.decode())["result"]
        return contract
Exemplo n.º 3
0
 def add_multi_sign_transaction(self, tx: Transaction, m: int, pubkeys: [],
                                signer: Account):
     pubkeys = ProgramBuilder.sort_publickeys(pubkeys)
     tx_hash = tx.hash256_bytes()
     sig_data = signer.generate_signature(tx_hash,
                                          signer.get_signature_scheme())
     if tx.sigs is None or len(tx.sigs) == 0:
         tx.sigs = []
     elif len(tx.sigs) >= Common.TX_MAX_SIG_SIZE:
         raise SDKException(
             ErrorCode.param_err(
                 'the number of transaction signatures should not be over 16'
             ))
     else:
         for i in range(len(tx.sigs)):
             if tx.sigs[i].public_keys == pubkeys:
                 if len(tx.sigs[i].sig_data) + 1 > len(pubkeys):
                     raise SDKException(
                         ErrorCode.param_err('too more sigData'))
                 if tx.sigs[i].M != m:
                     raise SDKException(ErrorCode.param_err('M error'))
                 tx.sigs[i].sig_data.append(sig_data)
                 return tx
     sig = Sig(pubkeys, m, [sig_data])
     tx.sigs.append(sig)
     return tx
Exemplo n.º 4
0
    def approve(self, owner_acct: Account, b58_spender_address: str,
                amount: int, payer_acct: Account, gas_limit: int,
                gas_price: int):
        """
        This interface is used to call the Approve method in ope4
        that allows spender to withdraw a certain amount of oep4 token from owner account multiple times.

        If this function is called again, it will overwrite the current allowance with new value.

        :param owner_acct: an Account class that indicate the owner.
        :param b58_spender_address: a base58 encode address that be allowed to spend the oep4 token in owner's account.
        :param amount: an int value that indicate the amount oep4 token that will be transferred in this transaction.
        :param payer_acct: an Account class that used to pay for the transaction.
        :param gas_limit: an int value that indicate the gas limit.
        :param gas_price: an int value that indicate the gas price.
        :return: the hexadecimal transaction hash value.
        """
        func = self.__abi_info.get_function('approve')
        if not isinstance(amount, int):
            raise SDKException(
                ErrorCode.param_err('the data type of amount should be int.'))
        if amount < 0:
            raise SDKException(
                ErrorCode.param_err(
                    'the amount should be equal or great than 0.'))
        owner_address = owner_acct.get_address().to_array()
        Oep4.__b58_address_check(b58_spender_address)
        spender_address = Address.b58decode(b58_spender_address).to_array()
        params = (owner_address, spender_address, amount)
        func.set_params_value(params)
        tx_hash = self.__sdk.neo_vm().send_transaction(self.__contract_address,
                                                       owner_acct, payer_acct,
                                                       gas_limit, gas_price,
                                                       func, False)
        return tx_hash
Exemplo n.º 5
0
    def add_multi_sign_transaction(tx: Transaction, m: int, pub_keys: list,
                                   signer: Account):
        """
        This interface is used to generate an Transaction object which has multi signature.

        :param tx: a Transaction object which will be signed.
        :param m: the amount of signer.
        :param pub_keys: a list of public keys.
        :param signer: an Account object which will sign the transaction.
        :return: a Transaction object which has been signed.
        """
        pub_keys = ProgramBuilder.sort_publickeys(pub_keys)
        tx_hash = tx.hash256_bytes()
        sig_data = signer.generate_signature(tx_hash,
                                             signer.get_signature_scheme())
        if tx.sigs is None or len(tx.sigs) == 0:
            tx.sigs = []
        elif len(tx.sigs) >= Common.TX_MAX_SIG_SIZE:
            raise SDKException(
                ErrorCode.param_err(
                    'the number of transaction signatures should not be over 16'
                ))
        else:
            for i in range(len(tx.sigs)):
                if tx.sigs[i].public_keys == pub_keys:
                    if len(tx.sigs[i].sig_data) + 1 > len(pub_keys):
                        raise SDKException(
                            ErrorCode.param_err('too more sigData'))
                    if tx.sigs[i].M != m:
                        raise SDKException(ErrorCode.param_err('M error'))
                    tx.sigs[i].sig_data.append(sig_data)
                    return tx
        sig = Sig(pub_keys, m, [sig_data])
        tx.sigs.append(sig)
        return tx
Exemplo n.º 6
0
    def new_withdraw_ong_transaction(b58_claimer_address: str,
                                     b58_recv_address: str, amount: int,
                                     b58_payer_address: str, gas_limit: int,
                                     gas_price: int) -> Transaction:
        """
        This interface is used to generate a Transaction object that
        allow one account to withdraw an amount of ong and transfer them to receive address.

        :param b58_claimer_address: a base58 encode address which is used to indicate who is the claimer.
        :param b58_recv_address: a base58 encode address which is used to indicate who receive the claimed ong.
        :param amount: the amount of asset that will be claimed.
        :param b58_payer_address: a base58 encode address which indicate who will pay for the transaction.
        :param gas_limit: an int value that indicate the gas limit.
        :param gas_price: an int value that indicate the gas price.
        :return: a Transaction object which can be used for withdraw ong.
        """
        if not isinstance(b58_claimer_address, str) or not isinstance(
                b58_recv_address, str) or not isinstance(
                    b58_payer_address, str):
            raise SDKException(
                ErrorCode.param_err(
                    'the data type of base58 encode address should be the string.'
                ))
        if len(b58_claimer_address) != 34 or len(
                b58_recv_address) != 34 or len(b58_payer_address) != 34:
            raise SDKException(
                ErrorCode.param_err(
                    'the length of base58 encode address should be 34 bytes.'))
        if amount <= 0:
            raise SDKException(
                ErrorCode.other_error(
                    'the amount should be greater than than zero.'))
        if gas_price < 0:
            raise SDKException(
                ErrorCode.other_error(
                    'the gas price should be equal or greater than zero.'))
        if gas_limit < 0:
            raise SDKException(
                ErrorCode.other_error(
                    'the gas limit should be equal or greater than zero.'))
        ont_contract_address = util.get_asset_address('onyx')
        ong_contract_address = util.get_asset_address("oxg")
        args = {
            "sender": Address.b58decode(b58_claimer_address).to_array(),
            "from": ont_contract_address,
            "to": Address.b58decode(b58_recv_address).to_array(),
            "value": amount
        }
        invoke_code = build_native_invoke_code(ong_contract_address,
                                               bytes([0]), "transferFrom",
                                               args)
        unix_time_now = int(time())
        payer_array = Address.b58decode(b58_payer_address).to_array()
        return Transaction(0, 0xd1, unix_time_now, gas_price, gas_limit,
                           payer_array, invoke_code, bytearray(), [],
                           bytearray())
Exemplo n.º 7
0
 def __b58_address_check(b58_address):
     if not isinstance(b58_address, str):
         raise SDKException(
             ErrorCode.param_err(
                 'the data type of base58 encode address should be the string.'
             ))
     if len(b58_address) != 34:
         raise SDKException(
             ErrorCode.param_err(
                 'the length of base58 encode address should be 34 bytes.'))
Exemplo n.º 8
0
    def new_transfer_transaction(asset: str, b58_from_address: str,
                                 b58_to_address: str, amount: int,
                                 b58_payer_address: str, gas_limit: int,
                                 gas_price: int) -> Transaction:
        """
        This interface is used to generate a Transaction object for transfer.

        :param asset: a string which is used to indicate which asset we want to transfer.
        :param b58_from_address: a base58 encode address which indicate where the asset from.
        :param b58_to_address: a base58 encode address which indicate where the asset to.
        :param amount: the amount of asset that will be transferred.
        :param b58_payer_address: a base58 encode address which indicate who will pay for the transaction.
        :param gas_limit: an int value that indicate the gas limit.
        :param gas_price: an int value that indicate the gas price.
        :return: a Transaction object which can be used for transfer.
        """
        if not isinstance(b58_from_address, str) or not isinstance(
                b58_to_address, str) or not isinstance(b58_payer_address, str):
            raise SDKException(
                ErrorCode.param_err(
                    'the data type of base58 encode address should be the string.'
                ))
        if len(b58_from_address) != 34 or len(b58_to_address) != 34 or len(
                b58_payer_address) != 34:
            raise SDKException(
                ErrorCode.param_err(
                    'the length of base58 encode address should be 34 bytes.'))
        if amount <= 0:
            raise SDKException(
                ErrorCode.other_error(
                    'the amount should be greater than than zero.'))
        if gas_price < 0:
            raise SDKException(
                ErrorCode.other_error(
                    'the gas price should be equal or greater than zero.'))
        if gas_limit < 0:
            raise SDKException(
                ErrorCode.other_error(
                    'the gas limit should be equal or greater than zero.'))
        contract_address = util.get_asset_address(asset)
        raw_from = Address.b58decode(b58_from_address).to_array()
        raw_to = Address.b58decode(b58_to_address).to_array()
        raw_payer = Address.b58decode(b58_payer_address).to_array()
        state = [{"from": raw_from, "to": raw_to, "amount": amount}]
        invoke_code = build_native_invoke_code(contract_address, bytes([0]),
                                               "transfer", state)
        unix_time_now = int(time())
        version = 0
        tx_type = 0xd1
        attributes = bytearray()
        signers = list()
        hash_value = bytearray()
        return Transaction(version, tx_type, unix_time_now, gas_price,
                           gas_limit, raw_payer, invoke_code, attributes,
                           signers, hash_value)
Exemplo n.º 9
0
    def transfer_from(self, spender_acct: Account, from_acct: Account,
                      b58_to_address: str, value: int, payer_acct: Account,
                      gas_limit: int, gas_price: int):
        """
        This interface is used to call the Allowance method in ope4
        that allow spender to withdraw amount of oep4 token from from-account to to-account.

        :param spender_acct: an Account class that spend the oep4 token.
        :param from_acct: an Account class that actually pay oep4 token for the spender's spending.
        :param b58_to_address: a base58 encode address that receive the oep4 token.
        :param value: the amount of ope4 token in this transaction.
        :param payer_acct: an Account class that used to pay for the transaction.
        :param gas_limit: an int value that indicate the gas limit.
        :param gas_price: an int value that indicate the gas price.
        :return: the hexadecimal transaction hash value.
        """
        func = self.__abi_info.get_function('TransferFrom')
        Oep4.__b58_address_check(b58_to_address)
        if not isinstance(from_acct, Account):
            raise SDKException(
                ErrorCode.param_err(
                    'the data type of from_acct should be Account.'))
        if not isinstance(spender_acct, Account):
            raise SDKException(
                ErrorCode.param_err(
                    'the data type of spender_acct should be Account.'))
        spender_address_array = spender_acct.get_address().to_array()
        from_address_array = from_acct.get_address().to_array()
        to_address_array = Address.b58decode(b58_to_address).to_array()
        if not isinstance(value, int):
            raise SDKException(
                ErrorCode.param_err('the data type of value should be int.'))
        params = (spender_address_array, from_address_array, to_address_array,
                  value)
        func.set_params_value(params)
        params = BuildParams.serialize_abi_function(func)
        unix_time_now = int(time.time())
        params.append(0x67)
        for i in self.__contract_address:
            params.append(i)
        if payer_acct is None:
            raise SDKException(ErrorCode.param_err('payer account is None.'))
        payer_address_array = payer_acct.get_address().to_array()
        tx = Transaction(0, 0xd1, unix_time_now, gas_price, gas_limit,
                         payer_address_array, params, bytearray(), [],
                         bytearray())
        self.__sdk.sign_transaction(tx, payer_acct)
        if spender_acct.get_address_base58() != payer_acct.get_address_base58(
        ):
            self.__sdk.add_sign_transaction(tx, spender_acct)
        if from_acct.get_address_base58() != payer_acct.get_address_base58():
            self.__sdk.add_sign_transaction(tx, payer_acct)
        tx_hash = self.__sdk.rpc.send_raw_transaction(tx)
        return tx_hash
Exemplo n.º 10
0
 def send_transfer(self, admin_identity: Identity, password: str, key_no: int, contract_address: str, new_admin_ont_id,
                   payer: Account, gas_limit: int, gas_price: int):
     if admin_identity is None or password is None or password == '' or contract_address is None or contract_address == '' or new_admin_ont_id is None or new_admin_ont_id == '' or payer is None:
         raise SDKException(ErrorCode.param_err("parameter should not be None"))
     if key_no < 0 or gas_limit < 0 or gas_price < 0:
         raise SDKException(ErrorCode.param_err('key_no or gas_limit or gas_price should not less than 0'))
     tx = self.make_transfer(contract_address, new_admin_ont_id, key_no, payer, gas_limit, gas_price)
     account = self.__sdk.wallet_manager.get_account(admin_identity.ont_id, password)
     self.__sdk.sign_transaction(tx, account)
     if payer is not None and account.get_address_base58() is not payer.get_address_base58():
         self.__sdk.add_sign_transaction(tx, payer)
     self.__sdk.rpc.send_raw_transaction(tx)
     return tx.hash256_explorer()
Exemplo n.º 11
0
    def transfer_multi(self, args: list, payer_acct: Account, signers: list,
                       gas_limit: int, gas_price: int):
        """
        This interface is used to call the TransferMulti method in ope4
        that allow transfer amount of token from multiple from-account to multiple to-account multiple times.

        :param args: a parameter list with each item contains three sub-items:
                base58 encode transaction sender address,
                base58 encode transaction receiver address,
                amount of token in transaction.
        :param payer_acct: an Account class that used to pay for the transaction.
        :param signers: a signer list used to sign this transaction which should contained all sender in args.
        :param gas_limit: an int value that indicate the gas limit.
        :param gas_price: an int value that indicate the gas price.
        :return: the hexadecimal transaction hash value.
        """
        func = self.__abi_info.get_function('transferMulti')
        for index in range(len(args)):
            item = args[index]
            Oep4.__b58_address_check(item[0])
            Oep4.__b58_address_check(item[1])
            if not isinstance(item[2], float) or isinstance(item[2], int):
                raise SDKException(
                    ErrorCode.param_err(
                        'the data type of value should be number.'))
            if item[2] < 0:
                raise SDKException(
                    ErrorCode.param_err(
                        'the value should be equal or great than 0.'))
            from_address_array = Address.b58decode(item[0]).to_array()
            to_address_array = Address.b58decode(item[1]).to_array()
            args[index] = [
                from_address_array, to_address_array,
                self.__to_int_according_to_decimal(item[2])
            ]
        func.set_params_value((args, ))
        params = BuildParams.serialize_abi_function(func)
        unix_time_now = int(time.time())
        params.append(0x67)
        for i in self.__contract_address:
            params.append(i)
        signers_len = len(signers)
        if signers_len == 0:
            raise SDKException(ErrorCode.param_err('payer account is None.'))
        payer_address = payer_acct.get_address().to_array()
        tx = Transaction(0, 0xd1, unix_time_now, gas_price, gas_limit,
                         payer_address, params, bytearray(), [], bytearray())
        for index in range(signers_len):
            self.__sdk.add_sign_transaction(tx, signers[index])
        tx_hash = self.__sdk.rpc.send_raw_transaction(tx)
        return tx_hash
Exemplo n.º 12
0
    def new_approve_transaction(asset: str, b58_send_address: str,
                                b58_recv_address: str, amount: int,
                                b58_payer_address: str, gas_limit: int,
                                gas_price: int) -> Transaction:
        """
        This interface is used to generate a Transaction object for approve.

        :param asset: a string which is used to indicate which asset we want to approve.
        :param b58_send_address: a base58 encode address which indicate where the approve from.
        :param b58_recv_address: a base58 encode address which indicate where the approve to.
        :param amount: the amount of asset that will be approved.
        :param b58_payer_address: a base58 encode address which indicate who will pay for the transaction.
        :param gas_limit: an int value that indicate the gas limit.
        :param gas_price: an int value that indicate the gas price.
        :return: a Transaction object which can be used for approve.
        """
        if not isinstance(b58_send_address, str) or not isinstance(
                b58_recv_address, str):
            raise SDKException(
                ErrorCode.param_err(
                    'the data type of base58 encode address should be the string.'
                ))
        if len(b58_send_address) != 34 or len(b58_recv_address) != 34:
            raise SDKException(
                ErrorCode.param_err(
                    'the length of base58 encode address should be 34 bytes.'))
        if amount <= 0:
            raise SDKException(
                ErrorCode.other_error(
                    'the amount should be greater than than zero.'))
        if gas_price < 0:
            raise SDKException(
                ErrorCode.other_error(
                    'the gas price should be equal or greater than zero.'))
        if gas_limit < 0:
            raise SDKException(
                ErrorCode.other_error(
                    'the gas limit should be equal or greater than zero.'))
        contract_address = util.get_asset_address(asset)
        raw_send = Address.b58decode(b58_send_address).to_array()
        raw_recv = Address.b58decode(b58_recv_address).to_array()
        raw_payer = Address.b58decode(b58_payer_address).to_array()
        args = {"from": raw_send, "to": raw_recv, "amount": amount}
        invoke_code = build_native_invoke_code(contract_address, bytes([0]),
                                               "approve", args)
        unix_time_now = int(time())
        return Transaction(0, 0xd1, unix_time_now, gas_price,
                           gas_limit, raw_payer, invoke_code, bytearray(), [],
                           bytearray())
Exemplo n.º 13
0
    def send_transfer_from(self, asset: str, sender: Account,
                           b58_from_address: str, b58_recv_address: str,
                           amount: int, payer: Account, gas_limit: int,
                           gas_price: int) -> str:
        """
        This interface is used to generate a Transaction object for transfer that
        allow one account to transfer a amount of ONT or ONG Asset to another account,
        in the condition of the first account had been approved.

        :param asset: a string which is used to indicate which asset we want to transfer.
        :param sender: an Account class that send the transfer transaction.
        :param b58_from_address: a base58 encode address which indicate where the asset from.
        :param b58_recv_address: a base58 encode address which indicate where the asset to.
        :param amount: the amount of asset want to transfer from from-address.
        :param payer: an Account class that used to pay for the transaction.
        :param gas_limit: an int value that indicate the gas limit.
        :param gas_price: an int value that indicate the gas price.
        :return: hexadecimal transaction hash value.
        """
        if sender is None:
            raise SDKException(
                ErrorCode.param_err('the sender should not be None.'))
        if payer is None:
            raise SDKException(
                ErrorCode.param_err('the payer should not be None.'))
        if amount <= 0:
            raise SDKException(
                ErrorCode.other_error(
                    'the amount should be greater than than zero.'))
        if gas_price < 0:
            raise SDKException(
                ErrorCode.other_error(
                    'the gas price should be equal or greater than zero.'))
        if gas_limit < 0:
            raise SDKException(
                ErrorCode.other_error(
                    'the gas limit should be equal or greater than zero.'))
        b58_payer_address = payer.get_address_base58()
        b58_sender_address = sender.get_address_base58()
        tx = Asset.new_transfer_from_transaction(asset, b58_sender_address,
                                                 b58_from_address,
                                                 b58_recv_address, amount,
                                                 b58_payer_address, gas_limit,
                                                 gas_price)
        tx = self.__sdk.sign_transaction(tx, sender)
        if b58_sender_address != b58_payer_address:
            tx = self.__sdk.add_sign_transaction(tx, payer)
        self.__sdk.rpc.send_raw_transaction(tx)
        return tx.hash256_explorer()
Exemplo n.º 14
0
    def get_smart_contract(self, contract_address: str) -> dict:
        """
        This interface is used to get the information of smart contract based on the specified hexadecimal hash value.

        :param contract_address: str, a hexadecimal hash value.
        :return: the information of smart contract in dictionary form.
        """
        if type(contract_address) != str:
            raise SDKException(ErrorCode.param_err('a hexadecimal contract address is required.'))
        if len(contract_address) != 40:
            raise SDKException(ErrorCode.param_err('the length of the contract address should be 40 bytes.'))
        rpc_struct = RpcClient.set_json_rpc_version(RPC_GET_SMART_CONTRACT, [contract_address, 1])
        r = HttpRequest.request("post", self.addr, rpc_struct)
        contract = json.loads(r.content.decode())["result"]
        return contract
Exemplo n.º 15
0
 def set_contract_address(self, contract_address: str or bytearray or bytes):
     if len(contract_address) == 20:
         if isinstance(contract_address, bytes):
             self.__contract_address = bytearray(contract_address)
             self.__update_abi_info()
         elif isinstance(contract_address, bytearray):
             self.__contract_address = contract_address
             self.__update_abi_info()
         else:
             raise SDKException(ErrorCode.param_err('the data type of the contract address unsupported.'))
     elif isinstance(contract_address, str) and len(contract_address) == 40:
         self.__contract_address = binascii.a2b_hex(contract_address)
         self.__update_abi_info()
     else:
         raise SDKException(ErrorCode.param_err('the length of contract address should be 20 bytes.'))
 def load(self):
     with open(self.wallet_path, "r") as f:
         obj = json.load(f)
         try:
             create_time = obj['createTime']
         except KeyError:
             create_time = ''
         try:
             default_id = obj['defaultOntid']
         except KeyError:
             default_id = ''
         try:
             default_address = obj['defaultAccountAddress']
         except KeyError:
             default_address = ''
         try:
             identities = obj['identities']
         except KeyError:
             identities = list()
         try:
             wallet = WalletData(obj['name'], obj['version'], create_time, default_id, default_address,
                                 obj['scrypt'], identities, obj['accounts'])
         except KeyError as e:
             raise SDKException(ErrorCode.param_err('wallet file format error: %s.' % e))
     return wallet
Exemplo n.º 17
0
 def load(self):
     with open(self.wallet_path, "r") as f:
         content = f.read()
         if content.startswith(u'\ufeff'):
             content = content.encode('utf8')[3:].decode('utf8')
         obj = json.loads(content)
         try:
             create_time = obj['createTime']
         except KeyError:
             create_time = ''
         try:
             default_id = obj['defaultOntid']
         except KeyError:
             default_id = ''
         try:
             default_address = obj['defaultAccountAddress']
         except KeyError:
             default_address = ''
         try:
             identities = obj['identities']
         except KeyError:
             identities = list()
         try:
             wallet = WalletData(obj['name'], obj['version'], create_time, default_id, default_address,
                                 obj['scrypt'], identities, obj['accounts'])
         except KeyError as e:
             raise SDKException(ErrorCode.param_err('wallet file format error: %s.' % e))
     return wallet
Exemplo n.º 18
0
 def load(self):
     with open(self.wallet_path, "rb") as f:
         content = f.read()
         if content.startswith(codecs.BOM_UTF8):
             content = content[len(codecs.BOM_UTF8):]
         obj = json.loads(content)
         try:
             create_time = obj['createTime']
         except KeyError:
             create_time = ''
         try:
             default_id = obj['defaultOntid']
         except KeyError:
             default_id = ''
         try:
             default_address = obj['defaultAccountAddress']
         except KeyError:
             default_address = ''
         try:
             identities = obj['identities']
         except KeyError:
             identities = list()
         try:
             scrypt_dict = obj['scrypt']
             scrypt_obj = Scrypt(scrypt_dict.get('n', 16384), scrypt_dict.get('r', 8), scrypt_dict.get('p', 8),
                                 scrypt_dict.get('dk_len', 64))
             wallet = WalletData(obj['name'], obj['version'], create_time, default_id, default_address,
                                 scrypt_obj, identities, obj['accounts'])
         except KeyError as e:
             raise SDKException(ErrorCode.param_err('wallet file format error: %s.' % e))
     return wallet
Exemplo n.º 19
0
    def read_serializable_array(self, class_name, max=sys.maxsize):
        """
        Deserialize a stream into the object specific by `class_name`.

        Args:
            class_name (str): a full path to the class to be deserialized into. e.g. 'neo.Core.Block.Block'
            max (int): (Optional) maximum number of bytes to read.

        Returns:
            list: list of `class_name` objects deserialized from the stream.
        """
        module = '.'.join(class_name.split('.')[:-1])
        klassname = class_name.split('.')[-1]
        klass = getattr(importlib.import_module(module), klassname)
        length = self.read_var_int(max=max)
        items = []
        try:
            for i in range(0, length):
                item = klass()
                item.Deserialize(self)
                items.append(item)
        except Exception as e:
            raise SDKException(ErrorCode.param_err("Couldn't deserialize %s" % e))

        return items
Exemplo n.º 20
0
    def read_var_int(self, max=sys.maxsize):
        """
        Read a variable length integer from the stream.
        The NEO network protocol supports encoded storage for space saving. See: http://docs.neo.org/en-us/node/network-protocol.html#convention

        Args:
            max (int): (Optional) maximum number of bytes to read.

        Returns:
            int:
        """
        fb = self.read_byte()
        if fb is 0:
            return fb
        value = 0
        if hex(fb) == '0xfd':
            value = self.read_uint16()
        elif hex(fb) == '0xfe':
            value = self.read_uint32()
        elif hex(fb) == '0xff':
            value = self.read_uint64()
        else:
            value = fb

        if value > max:
            raise SDKException(ErrorCode.param_err('Invalid format'))

        return int(value)
Exemplo n.º 21
0
    def send_approve(self, asset, sender: Account, b58_recv_address: str,
                     amount: int, payer: Account, gas_limit: int,
                     gas_price: int) -> str:
        """
        This is an interface used to send an approve transaction
        which allow receiver to spend a amount of ONT or ONG asset in sender's account.

        :param asset: a string which is used to indicate what asset we want to approve.
        :param sender: an Account class that send the approve transaction.
        :param b58_recv_address: a base58 encode address which indicate where the approve to.
        :param amount: the amount of asset want to approve.
        :param payer: an Account class that used to pay for the transaction.
        :param gas_limit: an int value that indicate the gas limit.
        :param gas_price: an int value that indicate the gas price.
        :return: hexadecimal transaction hash value.
        """
        if sender is None:
            raise SDKException(
                ErrorCode.param_err('the sender should not be None.'))
        if payer is None:
            raise SDKException(
                ErrorCode.param_err('the payer should not be None.'))
        if amount <= 0:
            raise SDKException(
                ErrorCode.other_error(
                    'the amount should be greater than than zero.'))
        if gas_price < 0:
            raise SDKException(
                ErrorCode.other_error(
                    'the gas price should be equal or greater than zero.'))
        if gas_limit < 0:
            raise SDKException(
                ErrorCode.other_error(
                    'the gas limit should be equal or greater than zero.'))
        b58_sender_address = sender.get_address_base58()
        b58_payer_address = payer.get_address_base58()
        tx = Asset.new_approve_transaction(asset, b58_sender_address,
                                           b58_recv_address, amount,
                                           b58_payer_address, gas_limit,
                                           gas_price)
        tx = self.__sdk.sign_transaction(tx, sender)
        if sender.get_address_base58() != payer.get_address_base58():
            tx = self.__sdk.add_sign_transaction(tx, payer)
        self.__sdk.rpc.send_raw_transaction(tx)
        return tx.hash256_explorer()
 def write_byte(self, value):
     if isinstance(value, bytearray) or isinstance(value, bytes):
         self.ms.write(value)
     elif isinstance(value, str):
         self.ms.write(value.encode())
     elif isinstance(value, int):
         self.ms.write(bytes([value]))
     else:
         raise SDKException(ErrorCode.param_err('type error, write byte failed.'))
Exemplo n.º 23
0
    def send_withdraw_ong_transaction(self, claimer: Account,
                                      b58_recv_address: str, amount: int,
                                      payer: Account, gas_limit: int,
                                      gas_price: int) -> str:
        """
        This interface is used to withdraw a amount of ong and transfer them to receive address.

        :param claimer: the owner of ong that remained to claim.
        :param b58_recv_address: the address that received the ong.
        :param amount: the amount of ong want to claim.
        :param payer: an Account class that used to pay for the transaction.
        :param gas_limit: an int value that indicate the gas limit.
        :param gas_price: an int value that indicate the gas price.
        :return: hexadecimal transaction hash value.
        """
        if claimer is None:
            raise SDKException(
                ErrorCode.param_err('the claimer should not be None.'))
        if payer is None:
            raise SDKException(
                ErrorCode.param_err('the payer should not be None.'))
        if amount <= 0:
            raise SDKException(
                ErrorCode.other_error(
                    'the amount should be greater than than zero.'))
        if gas_price < 0:
            raise SDKException(
                ErrorCode.other_error(
                    'the gas price should be equal or greater than zero.'))
        if gas_limit < 0:
            raise SDKException(
                ErrorCode.other_error(
                    'the gas limit should be equal or greater than zero.'))
        b58_claimer = claimer.get_address_base58()
        b58_payer = payer.get_address_base58()
        tx = Asset.new_withdraw_ong_transaction(b58_claimer, b58_recv_address,
                                                amount, b58_payer, gas_limit,
                                                gas_price)
        tx = self.__sdk.sign_transaction(tx, claimer)
        if claimer.get_address_base58() != payer.get_address_base58():
            tx = self.__sdk.add_sign_transaction(tx, payer)
        self.__sdk.rpc.send_raw_transaction(tx)
        return tx.hash256_explorer()
    def get_parameter(self, param_name: str) -> Parameter:
        """
        This interface is used to get a Parameter object from an AbiFunction object
        which contain given function parameter's name, type and value.

        :param param_name: a string used to indicate which parameter we want to get from AbiFunction.
        :return: a Parameter object which contain given function parameter's name, type and value.
        """
        for p in self.parameters:
            if p.name == param_name:
                return p
        raise SDKException(ErrorCode.param_err('get parameter failed.'))
Exemplo n.º 25
0
    def write_var_int(self, value, little_endian=True):
        """
        Write an integer value in a space saving way to the stream.

        Args:
            value (int):
            little_endian (bool): specify the endianness. (Default) Little endian.

        Raises:
            SDKException: if `value` is not of type int.
            SDKException: if `value` is < 0.

        Returns:
            int: the number of bytes written.
        """
        if little_endian:
            endian = "<"
        else:
            endian = ">"

        if not isinstance(value, int):
            raise SDKException(ErrorCode.param_err('%s not int type.' % value))

        if value < 0:
            raise SDKException(ErrorCode.param_err('%d too small.' % value))

        elif value < 0xfd:
            return self.write_byte(value)

        elif value <= 0xffff:
            self.write_byte(0xfd)
            return self.write_uint16(value, little_endian)

        elif value <= 0xFFFFFFFF:
            self.write_byte(0xfe)
            return self.write_uint32(value, little_endian)

        else:
            self.write_byte(0xff)
            return self.write_uint64(value, little_endian)
Exemplo n.º 26
0
    def transfer(self, from_acct: Account, b58_to_address: str, value: int,
                 payer_acct: Account, gas_limit: int, gas_price: int) -> str:
        """
        This interface is used to call the Transfer method in ope4
        that transfer an amount of tokens from one account to another account.

        :param from_acct: an Account class that send the oep4 token.
        :param b58_to_address: a base58 encode address that receive the oep4 token.
        :param value: an int value that indicate the amount oep4 token that will be transferred in this transaction.
        :param payer_acct: an Account class that used to pay for the transaction.
        :param gas_limit: an int value that indicate the gas limit.
        :param gas_price: an int value that indicate the gas price.
        :return: the hexadecimal transaction hash value.
        """
        func = self.__abi_info.get_function('transfer')
        if not isinstance(value, int) or isinstance(value, float):
            raise SDKException(
                ErrorCode.param_err(
                    'the data type of value should be number.'))
        if value < 0:
            raise SDKException(
                ErrorCode.param_err(
                    'the value should be equal or great than 0.'))
        if not isinstance(from_acct, Account):
            raise SDKException(
                ErrorCode.param_err(
                    'the data type of from_acct should be Account.'))
        Oep4.__b58_address_check(b58_to_address)
        from_address = from_acct.get_address().to_array()
        to_address = Address.b58decode(b58_to_address).to_array()
        value = self.__to_int_according_to_decimal(value)
        params = (from_address, to_address, value)
        func.set_params_value(params)
        tx_hash = self.__sdk.neo_vm().send_transaction(self.__contract_address,
                                                       from_acct, payer_acct,
                                                       gas_limit, gas_price,
                                                       func, False)
        return tx_hash
Exemplo n.º 27
0
 def read_byte(self, do_ord=True):
     """
     Read a single byte.
     Args:
         do_ord (bool): (default True) convert the byte to an ordinal first.
     Returns:
         bytes: a single byte if successful. 0 (int) if an exception occurred.
     """
     try:
         if do_ord:
             return ord(self.stream.read(1))
         return self.stream.read(1)
     except Exception as e:
         raise SDKException(ErrorCode.param_err(e.args[0]))
Exemplo n.º 28
0
 def add_sign_transaction(self, tx: Transaction, signer: Account):
     if tx.sigs is None or len(tx.sigs) == 0:
         tx.sigs = []
     elif len(tx.sigs) >= Common.TX_MAX_SIG_SIZE:
         raise SDKException(
             ErrorCode.param_err(
                 'the number of transaction signatures should not be over 16'
             ))
     tx_hash = tx.hash256_bytes()
     sig_data = signer.generate_signature(tx_hash,
                                          signer.get_signature_scheme())
     sig = Sig([signer.serialize_public_key()], 1, [sig_data])
     tx.sigs.append(sig)
     return tx
Exemplo n.º 29
0
 def send_transfer_from(self, asset: str, sender: Account, from_address: str, recv_address: str, amount: int,
                        payer: Account, gas_limit: int, gas_price: int) -> str:
     if sender is None or payer is None:
         raise SDKException(ErrorCode.param_err('parameters should not be null'))
     if amount <= 0 or gas_price < 0 or gas_limit < 0:
         raise SDKException(ErrorCode.param_error)
     b58_payer = payer.get_address_base58()
     b58_sender = sender.get_address_base58()
     tx = Asset.new_transfer_from(asset, b58_sender, from_address, recv_address, amount, b58_payer, gas_limit, gas_price)
     tx = self.__sdk.sign_transaction(tx, sender)
     if b58_sender != b58_payer:
         tx = self.__sdk.add_sign_transaction(tx, payer)
     self.__sdk.rpc.send_raw_transaction(tx)
     return tx.hash256_explorer()
Exemplo n.º 30
0
    def write_fixed_str(self, value, length):
        """
        Write a string value to the stream.

        Args:
            value (str): value to write to the stream.
            length (int): length of the string to write.
        """
        towrite = value.encode('utf-8')
        slen = len(towrite)
        if slen > length:
            raise SDKException(
                ErrorCode.param_err('string longer than fixed length: %s' %
                                    length))
        self.write_bytes(towrite)
        diff = length - slen

        while diff > 0:
            self.write_byte(0)
            diff -= 1