コード例 #1
0
def prepare_args_for_stake(args: Any):
    validators_file = ValidatorsFile(args.validators_file)

    reward_address = args.reward_address

    # TODO: Refactor, so that only address is received here.
    if args.pem:
        account = Account(pem_file=args.pem)
    elif args.keyfile and args.passfile:
        account = Account(key_file=args.keyfile, pass_file=args.passfile)

    num_of_nodes = validators_file.get_num_of_nodes()
    stake_data = 'stake@' + binascii.hexlify(num_of_nodes.to_bytes(1, byteorder="little")).decode()
    validators_list = validators_file.get_validators_list()
    for validator in validators_list:
        # get validator
        validator_pem = validator.get("pemFile")
        validator_pem = path.join(path.dirname(args.validators_file), validator_pem)
        seed, bls_key = parse_validator_pem(validator_pem)
        signed_message = sign_message_with_bls_key(account.address.pubkey().hex(), seed.hex())
        stake_data += f"@{bls_key}@{signed_message}"

    if reward_address:
        reward_address = Address(args.reward_address)
        stake_data += '@' + reward_address.hex()

    args.receiver = AUCTION_SMART_CONTRACT_ADDRESS
    args.data = stake_data

    if args.estimate_gas:
        args.gas_limit = estimate_system_sc_call(args, MetaChainSystemSCsCost.STAKE, num_of_nodes)
コード例 #2
0
ファイル: validators.py プロジェクト: natebolam/elrond-sdk
def parse_args_for_stake(args):
    num_of_nodes = int(args.number_of_nodes)
    keys = args.nodes_public_keys.split(',')
    if num_of_nodes != len(keys):
        logger.info(
            "number of nodes is not equals with number of provided validators keys"
        )
        return

    reward_address = args.reward_address

    stake_data = 'stake@' + binascii.hexlify(
        num_of_nodes.to_bytes(1, byteorder="little")).decode()
    for key in keys:
        stake_data += '@' + key + '@' + convert_to_hex('genesis')

    if reward_address:
        reward_address = Address(args.reward_address)
        stake_data += '@' + reward_address.hex()

    args.receiver = _STAKE_SMART_CONTRACT_ADDRESS
    args.data = stake_data

    if args.estimate_gas:
        args.gas_limit = estimate_system_sc_call(args,
                                                 MetaChainSystemSCsCost.STAKE,
                                                 len(keys))

    return args
コード例 #3
0
def prepare_args_for_change_reward_address(args: Any):
    reward_address = Address(args.reward_address)
    args.data = 'changeRewardAddress@' + reward_address.hex()
    args.receiver = AUCTION_SMART_CONTRACT_ADDRESS

    if args.estimate_gas:
        args.gas_limit = estimate_system_sc_call(args, MetaChainSystemSCsCost.CHANGE_REWARD_ADDRESS)
コード例 #4
0
def do_bech32(args):
    encode = args.encode
    value = args.value
    address = Address(value)

    result = address.bech32() if encode else address.hex()
    print(result)
    return result
コード例 #5
0
def resolve(name: str, proxy: ElrondProxy) -> Address:
    name_arg = "0x{}".format(str.encode(name).hex())
    dns_address = dns_address_for_name(name)
    contract = SmartContract(dns_address)
    result = contract.query(proxy, "resolve", [name_arg])
    if len(result) == 0:
        return Address.zero()
    return Address(result[0].hex)
コード例 #6
0
ファイル: transactions.py プロジェクト: irfan798/elrond-sdk
    def to_dictionary_as_inner(self) -> Dict[str, Any]:
        dictionary = self.to_dictionary()
        dictionary["receiver"] = base64.b64encode(Address(self.receiver).pubkey()).decode()
        dictionary["sender"] = base64.b64encode(Address(self.sender).pubkey()).decode()
        dictionary["chainID"] = base64.b64encode(self.chainID.encode()).decode()
        dictionary["signature"] = base64.b64encode(bytes(bytearray.fromhex(self.signature))).decode()
        dictionary["value"] = int(self.value)

        return dictionary
コード例 #7
0
ファイル: validators.py プロジェクト: natebolam/elrond-sdk
def parse_args_for_changing_reward_address(args):
    reward_address = Address(args.reward_address)
    args.data = 'changeRewardAddress@' + reward_address.hex()
    args.receiver = _STAKE_SMART_CONTRACT_ADDRESS

    if args.estimate_gas:
        args.gas_limit = estimate_system_sc_call(
            args, MetaChainSystemSCsCost.CHANGE_REWARD_ADDRESS)

    return args
コード例 #8
0
ファイル: contracts.py プロジェクト: kamalzaman/elrond-sdk
 def compute_address(self):
     """
     8 bytes of zero + 2 bytes for VM type + 20 bytes of hash(owner) + 2 bytes of shard(owner)
     """
     owner_bytes = self.owner.address.pubkey()
     nonce_bytes = self.owner.nonce.to_bytes(8, byteorder="little")
     bytes_to_hash = owner_bytes + nonce_bytes
     address = keccak.new(digest_bits=256).update(bytes_to_hash).digest()
     address = bytes([0] * 8) + bytes(
         [5, 0]) + address[10:30] + owner_bytes[30:]
     self.address = Address(address)
コード例 #9
0
def generate_pem(args):
    pem_file = args.pem
    mnemonic = args.mnemonic

    seed, pubkey = wallet.generate_pair()
    if mnemonic:
        seed, pubkey = wallet.derive_keys(mnemonic)

    address = Address(pubkey)
    pem.write(pem_file, seed, pubkey, name=address.bech32())
    logger.info(f"Created PEM file [{pem_file}] for [{address.bech32()}]")
コード例 #10
0
def generate_pem(args: Any):
    pem_file = args.pem
    mnemonic = args.mnemonic
    index = args.index

    seed, pubkey = wallet.generate_pair()
    if mnemonic:
        mnemonic = input("Enter mnemonic:\n")
        mnemonic = mnemonic.strip()
        seed, pubkey = wallet.derive_keys(mnemonic, index)

    address = Address(pubkey)
    pem.write(pem_file, seed, pubkey, name=address.bech32())
    logger.info(f"Created PEM file [{pem_file}] for [{address.bech32()}]")
コード例 #11
0
def _get_sc_address_from_tx(data: Any):
    if not isinstance(data, dict):
        raise errors.ProgrammingError("error")

    sc_results = data.get('smartContractResults')
    if sc_results is None:
        raise errors.ProgrammingError("smart contract results missing")

    # TODO improve robustness of this code in case of failed transaction
    try:
        sc_result = sc_results[0]
        data_field = sc_result['data']

        data_field_split = data_field.split('@')
        arg_1 = binascii.unhexlify(data_field_split[1])
        if not arg_1 == b'ok':
            raise errors.ProgrammingError(arg_1.decode("utf-8"))

        sc_address = binascii.unhexlify(data_field_split[2])
        address = Address(sc_address)
        print("Contract address: ", address)
    except:
        raise errors.ProgrammingError(
            "cannot get the smart contract address from transaction results, please try again"
        )
コード例 #12
0
def get_account_transactions(args: Any):
    proxy_url = args.proxy
    address = args.address
    proxy = ElrondProxy(proxy_url)

    response = proxy.get_account_transactions(Address(address))
    utils.dump_out_json(response, args.outfile)
コード例 #13
0
def get_account_balance(args):
    proxy_url = args.proxy
    address = args.address

    proxy = ElrondProxy(proxy_url)
    balance = proxy.get_account_balance(Address(address))
    print(balance)
    return balance
コード例 #14
0
def get_account_transactions(args):
    proxy_url = args.proxy
    address = args.address

    proxy = ElrondProxy(proxy_url)
    account = proxy.get_account_transactions(Address(address))
    print(account)
    return account
コード例 #15
0
ファイル: test_wallet.py プロジェクト: EniCristian/elrond-sdk
    def test_pem_parse_multiple(self):
        pem_file = self.testdata.joinpath("keys", "walletKey.pem")

        seed, address = pem.parse(pem_file, index=0)
        self.assertEqual("1f4dd8b7d18b5d0785c9d0802ec14d553dba356812b85c7e3414373388472010", seed.hex())
        self.assertEqual(Address("erd1sjsk3n2d0krq3pyxxtgf0q7j3t56sgusqaujj4n82l39t9h7jers6gslr4").hex(), address.hex())

        seed, address = pem.parse(pem_file, index=1)
        self.assertEqual("2565dbbdb62301e4c7b12b8a41cd3b2fbd7ae687c8d9741937aa48cf246aeb25", seed.hex())
        self.assertEqual(Address("erd10536tc3s886yqxtln74u6mztuwl5gy9k9gp8fttxda0klgxg979srtg5wt").hex(), address.hex())

        seed, address = pem.parse(pem_file, index=2)
        self.assertEqual("08de69d398f4a5ffdce0f1a8569704dbc8b58aaf7ba3e726134e32f1e8bf04ad", seed.hex())
        self.assertEqual(Address("erd1n230jlgfepdvf28vqt3zeawexg2jhvxqxjuqdfsss0xc62xcqcps9k54ag").hex(), address.hex())

        seed, address = pem.parse(pem_file, index=3)
        self.assertEqual("4d9dcc1c09a6d00c4c9a389e662d9fe26e0bf4c859776d4d338b5a9c41fc12d4", seed.hex())
        self.assertEqual(Address("erd143907zxv0ujxr9q4mda7rmczn2xwhmqn7p9lfz666z8hd2lcks2szt5yql").hex(), address.hex())
コード例 #16
0
def get_account(args: Any):
    proxy_url = args.proxy
    address = args.address
    proxy = ElrondProxy(proxy_url)
    account = proxy.get_account(Address(address))

    if args.balance:
        print(account.get("balance", 0))
    elif args.nonce:
        print(account.get("nonce", 0))
    else:
        print(account)
コード例 #17
0
def post_process_hyperblock(block: dict):
    # The timestamp can be computed deterministically, given the round and the genesis time
    round = int(block.get("round", 0))
    block["timestamp"] = constants.ERD_START_TIME + constants.ERD_ROUND_TIME * round

    hyperblock_nonce = block.get("nonce")
    hyperblock_hash = block.get("hash")

    # Hyperblocks V1 does not provide the transaction fees (nor "gasUsed"). Hyperblocks V2 will provide this information.
    # Until then, we can compute the fees deterministically (best-effort).
    # For Smart Contract transactions, the refunds will be incompletely provided by the API - until Hyperblocks V2 becomes available.
    # (e.g. intra-shard refunds are not visible etc.)

    for transaction in block["transactions"]:
        tx_type = transaction.get("type")
        tx_gas_limit = int(transaction.get("gasLimit", 0))
        tx_gas_price = int(transaction.get("gasPrice", 0))
        tx_receiver = Address(transaction.get("receiver"))
        tx_data = transaction.get("data", None)
        tx_data_decoded = ""
        tx_data_len = 0
        tx_gas_used = 0

        if tx_data:
            tx_data_decoded = base64.b64decode(tx_data)
            tx_data_len = len(tx_data_decoded)

        if tx_type == "normal":
            if tx_receiver.is_contract_address():
                tx_gas_used = tx_gas_limit
            else:
                tx_gas_used = constants.ERD_MIN_GAS_LIMIT + tx_data_len * constants.ERD_GAS_PER_DATA_BYTE

        fee = tx_gas_used * tx_gas_price
        transaction["fee"] = str(fee)

        # Also add the hyperblock coordinates, for convenience
        # (a bit of content duplication, since they are also provided in the parent structure):
        transaction["hyperblockNonce"] = hyperblock_nonce
        transaction["hyperblockHash"] = hyperblock_hash
コード例 #18
0
def compute_dns_address_for_shard_id(shard_id) -> Address:
    deployer_pubkey_prefix = InitialDNSAddress[:len(InitialDNSAddress) -
                                               ShardIdentiferLen]

    deployer_pubkey = deployer_pubkey_prefix + bytes([0, shard_id])
    deployer = Account(address=Address(deployer_pubkey))
    deployer.nonce = 0
    # Workaround: currently, in erdpy, in order to compute the address of a contract, one has to create an instance of the class "SmartContract".
    # This might change in the future.
    contract = SmartContract()
    contract.owner = deployer
    contract.compute_address()
    return contract.address
コード例 #19
0
def _build_user_entry(nickname: str, account: Account, value: int,
                      delegated_value: int, delegation_address: Address):
    return {
        "nickname": nickname,
        "address": account.address.bech32(),
        "supply": str(value),
        "balance": str(value - delegated_value),
        "stakingvalue": "0",
        "delegation": {
            "address": delegation_address.bech32(),
            "value": str(delegated_value)
        }
    }
コード例 #20
0
def get_account(args: Any):
    proxy_url = args.proxy
    address = args.address
    proxy = ElrondProxy(proxy_url)
    account = proxy.get_account(Address(address))
    omit_fields = cli_shared.parse_omit_fields_arg(args)

    if args.balance:
        print(account.get("balance", 0))
    elif args.nonce:
        print(account.get("nonce", 0))
    else:
        utils.omit_fields(account, omit_fields)
        utils.dump_out_json(account)
コード例 #21
0
ファイル: core.py プロジェクト: f80dev/elMoney
def parse_args_for_stake(args: Any):
    validators_file = args.validators_file
    validators_data = _read_json_file(validators_file)

    reward_address = args.reward_address

    if args.pem:
        account = Account(pem_file=args.pem)
    elif args.keyfile and args.passfile:
        account = Account(key_file=args.keyfile, pass_file=args.passfile)

    num_of_nodes = len(validators_data.get("validators", []))
    stake_data = 'stake@' + binascii.hexlify(
        num_of_nodes.to_bytes(1, byteorder="little")).decode()
    for validator in validators_data.get("validators", []):
        # get validator
        validator_pem = validator.get("pemFile")
        validator_pem = path.join(path.dirname(validators_file), validator_pem)
        seed, bls_key = parse_validator_pem(validator_pem)
        signed_message = sign_message_with_bls_key(
            account.address.pubkey().hex(), seed.hex())
        stake_data += f"@{bls_key}@{signed_message}"

    if reward_address:
        reward_address = Address(args.reward_address)
        stake_data += '@' + reward_address.hex()

    args.receiver = _STAKE_SMART_CONTRACT_ADDRESS
    args.data = stake_data

    if args.estimate_gas:
        args.gas_limit = estimate_system_sc_call(args,
                                                 MetaChainSystemSCsCost.STAKE,
                                                 num_of_nodes)

    return args
コード例 #22
0
ファイル: staking.py プロジェクト: sorinfederiga/elrond-sdk
def main():
    logging.basicConfig(level=logging.DEBUG)

    parser = ArgumentParser()
    parser.add_argument("--proxy", default="https://testnet-api.elrond.com")
    parser.add_argument("--keyfile", help="wallet JSON keyfile", required=True)
    parser.add_argument("--passfile", help="wallet password file", required=True)
    parser.add_argument("--reward-address", required=True, help="the reward address")
    parser.add_argument("--validators-file", required=True, help="validators JSON file (with links to PEM files)")
    parser.add_argument("--value", required=True, help="the value to stake")
    args = parser.parse_args()
    args.estimate_gas = True
    args.pem = None

    proxy = ElrondProxy(args.proxy)
    network = proxy.get_network_config()
    args.chain = network.chain_id
    args.gas_price = network.min_gas_price
    args.version = network.min_tx_version

    print("Reward address:")
    print(Address(args.reward_address).bech32())
    confirm_continuation()

    prepare_args_for_stake(args)
    print("Transaction data:")
    print(args.data)
    confirm_continuation()

    print("Elrond Proxy (or Observer) address:", args.proxy)
    print("Chain ID:", args.chain)
    confirm_continuation()

    print("Value to stake:")
    print(int(args.value) / int(math.pow(10, 18)), "ERD")
    confirm_continuation()

    node_operator = Account(key_file=args.keyfile, pass_file=args.passfile)
    node_operator.sync_nonce(proxy)
    args.nonce = node_operator.nonce

    tx = do_prepare_transaction(args)
    tx.dump_to(sys.stdout)
    print("Transaction will now be sent.")
    confirm_continuation()

    tx.send(proxy)
    print("Done.")
コード例 #23
0
ファイル: transactions.py プロジェクト: ezaruba/elrond-sdk
def do_prepare_transaction(args):
    # "sender" taken from the PEM file
    sender_bytes = pem.get_pubkey(args.pem)
    sender_bech32 = Address(sender_bytes).bech32()

    plain = PlainTransaction()
    plain.nonce = int(args.nonce)
    plain.value = args.value
    plain.sender = sender_bech32
    plain.receiver = args.receiver
    plain.gasPrice = int(args.gas_price)
    plain.gasLimit = int(args.gas_limit)
    plain.data = args.data

    payload = TransactionPayloadToSign(plain)
    signature = signing.sign_transaction(payload, args.pem)
    prepared = PreparedTransaction(plain, signature)
    return prepared
コード例 #24
0
ファイル: contracts.py プロジェクト: kamalzaman/elrond-sdk
    def prepare_deploy_transaction(self, owner, arguments, gas_price,
                                   gas_limit, value):
        arguments = arguments or []
        gas_price = int(gas_price or config.DEFAULT_GAS_PRICE)
        gas_limit = int(gas_limit)
        value = str(value or "0")

        plain = PlainTransaction()
        plain.nonce = owner.nonce
        plain.value = value
        plain.sender = owner.address.bech32()
        plain.receiver = Address.zero().bech32()
        plain.gasPrice = gas_price
        plain.gasLimit = gas_limit
        plain.data = self.prepare_deploy_transaction_data(arguments)

        payload = TransactionPayloadToSign(plain)
        signature = signing.sign_transaction(payload, owner.pem_file)
        prepared = PreparedTransaction(plain, signature)
        return prepared
コード例 #25
0
ファイル: cli_contracts.py プロジェクト: f80dev/elMoney
def upgrade(args: Any):
    logger.debug("upgrade")
    cli_shared.check_broadcast_args(args)

    contract_address = args.contract
    arguments = args.arguments
    gas_price = args.gas_price
    gas_limit = args.gas_limit
    value = args.value
    chain = args.chain
    version = args.version

    contract = _prepare_contract(args)
    contract.address = Address(contract_address)
    sender = _prepare_sender(args)

    tx = contract.upgrade(sender, arguments, gas_price, gas_limit, value, chain, version)
    try:
        result = _send_or_simulate(tx, args)
    finally:
        txdict = tx.to_dump_dict()
        dump_tx_and_result(txdict, result, args)
コード例 #26
0
ファイル: contracts.py プロジェクト: EniCristian/elrond-sdk
    def deploy(self, owner, arguments, gas_price, gas_limit, value, chain,
               version) -> Transaction:
        self.owner = owner
        self.compute_address()

        arguments = arguments or []
        gas_price = int(gas_price)
        gas_limit = int(gas_limit)
        value = str(value or "0")

        tx = Transaction()
        tx.nonce = owner.nonce
        tx.value = value
        tx.sender = owner.address.bech32()
        tx.receiver = Address.zero().bech32()
        tx.gasPrice = gas_price
        tx.gasLimit = gas_limit
        tx.data = self.prepare_deploy_transaction_data(arguments)
        tx.chainID = chain
        tx.version = version

        tx.sign(owner)
        return tx
コード例 #27
0
    def test_address(self):
        address = Address("erd1l453hd0gt5gzdp7czpuall8ggt2dcv5zwmfdf3sd3lguxseux2fsmsgldz")
        address_cloned = Address(address)
        self.assertEqual("fd691bb5e85d102687d81079dffce842d4dc328276d2d4c60d8fd1c3433c3293", address.hex())
        self.assertEqual("erd1l453hd0gt5gzdp7czpuall8ggt2dcv5zwmfdf3sd3lguxseux2fsmsgldz", address.bech32())
        self.assertEqual(address.hex(), address_cloned.hex())
        self.assertEqual(address.bech32(), address_cloned.bech32())

        address = Address("fd691bb5e85d102687d81079dffce842d4dc328276d2d4c60d8fd1c3433c3293")
        address_cloned = Address(address)
        self.assertEqual("fd691bb5e85d102687d81079dffce842d4dc328276d2d4c60d8fd1c3433c3293", address.hex())
        self.assertEqual("erd1l453hd0gt5gzdp7czpuall8ggt2dcv5zwmfdf3sd3lguxseux2fsmsgldz", address.bech32())
        self.assertEqual(address.hex(), address_cloned.hex())
        self.assertEqual(address.bech32(), address_cloned.bech32())

        address = Address("")
        self.assertRaises(errors.EmptyAddressError, address.hex)
        self.assertRaises(errors.EmptyAddressError, address.bech32)

        address = Address(None)
        self.assertRaises(errors.EmptyAddressError, address.hex)
        self.assertRaises(errors.EmptyAddressError, address.bech32)

        with self.assertRaises(errors.BadAddressFormatError) as _:
            address = Address("bad")
コード例 #28
0
ファイル: contracts.py プロジェクト: kamalzaman/elrond-sdk
 def __init__(self, address=None, bytecode=None, metadata=None):
     self.address = Address(address)
     self.bytecode = bytecode
     self.metadata = metadata or CodeMetadata()
コード例 #29
0
ファイル: cli_dns.py プロジェクト: stjordanis/elrond-sdk
def dns_resolve(args: Any):
    addr = resolve(args.name, ElrondProxy(args.proxy))
    if addr.hex() != Address.zero().hex():
        print(addr.bech32())
コード例 #30
0
ファイル: contracts.py プロジェクト: kamalzaman/elrond-sdk
class SmartContract:
    def __init__(self, address=None, bytecode=None, metadata=None):
        self.address = Address(address)
        self.bytecode = bytecode
        self.metadata = metadata or CodeMetadata()

    def deploy(self, proxy, owner, arguments, gas_price, gas_limit, value):
        self.owner = owner
        self.owner.sync_nonce(proxy)
        self.compute_address()
        transaction = self.prepare_deploy_transaction(owner, arguments,
                                                      gas_price, gas_limit,
                                                      value)
        tx_hash = transaction.send(proxy)
        return tx_hash, self.address

    def prepare_deploy_transaction(self, owner, arguments, gas_price,
                                   gas_limit, value):
        arguments = arguments or []
        gas_price = int(gas_price or config.DEFAULT_GAS_PRICE)
        gas_limit = int(gas_limit)
        value = str(value or "0")

        plain = PlainTransaction()
        plain.nonce = owner.nonce
        plain.value = value
        plain.sender = owner.address.bech32()
        plain.receiver = Address.zero().bech32()
        plain.gasPrice = gas_price
        plain.gasLimit = gas_limit
        plain.data = self.prepare_deploy_transaction_data(arguments)

        payload = TransactionPayloadToSign(plain)
        signature = signing.sign_transaction(payload, owner.pem_file)
        prepared = PreparedTransaction(plain, signature)
        return prepared

    def prepare_deploy_transaction_data(self, arguments):
        tx_data = f"{self.bytecode}@{VM_TYPE_ARWEN}@{self.metadata.to_hex()}"

        for arg in arguments:
            tx_data += f"@{_prepare_argument(arg)}"

        return tx_data

    def compute_address(self):
        """
        8 bytes of zero + 2 bytes for VM type + 20 bytes of hash(owner) + 2 bytes of shard(owner)
        """
        owner_bytes = self.owner.address.pubkey()
        nonce_bytes = self.owner.nonce.to_bytes(8, byteorder="little")
        bytes_to_hash = owner_bytes + nonce_bytes
        address = keccak.new(digest_bits=256).update(bytes_to_hash).digest()
        address = bytes([0] * 8) + bytes(
            [5, 0]) + address[10:30] + owner_bytes[30:]
        self.address = Address(address)

    def execute(self, proxy, caller, function, arguments, gas_price, gas_limit,
                value):
        self.caller = caller
        self.caller.sync_nonce(proxy)
        transaction = self.prepare_execute_transaction(caller, function,
                                                       arguments, gas_price,
                                                       gas_limit, value)
        tx_hash = transaction.send(proxy)
        return tx_hash

    def prepare_execute_transaction(self, caller, function, arguments,
                                    gas_price, gas_limit, value):
        arguments = arguments or []
        gas_price = int(gas_price or config.DEFAULT_GAS_PRICE)
        gas_limit = int(gas_limit)
        value = str(value or "0")

        plain = PlainTransaction()
        plain.nonce = caller.nonce
        plain.value = value
        plain.sender = caller.address.bech32()
        plain.receiver = self.address.bech32()
        plain.gasPrice = gas_price
        plain.gasLimit = gas_limit
        plain.data = self.prepare_execute_transaction_data(function, arguments)

        payload = TransactionPayloadToSign(plain)
        signature = signing.sign_transaction(payload, caller.pem_file)
        prepared = PreparedTransaction(plain, signature)
        return prepared

    def prepare_execute_transaction_data(self, function, arguments):
        tx_data = function

        for arg in arguments:
            tx_data += f"@{_prepare_argument(arg)}"

        return tx_data

    def upgrade(self, proxy, caller, arguments, gas_price, gas_limit, value):
        self.caller = caller
        self.caller.sync_nonce(proxy)
        transaction = self.prepare_upgrade_transaction(caller, arguments,
                                                       gas_price, gas_limit,
                                                       value)
        tx_hash = transaction.send(proxy)
        return tx_hash

    def prepare_upgrade_transaction(self, owner, arguments, gas_price,
                                    gas_limit, value):
        arguments = arguments or []
        gas_price = int(gas_price or config.DEFAULT_GAS_PRICE)
        gas_limit = int(gas_limit)
        value = str(value or "0")

        plain = PlainTransaction()
        plain.nonce = owner.nonce
        plain.value = value
        plain.sender = owner.address.bech32()
        plain.receiver = self.address.bech32()
        plain.gasPrice = gas_price
        plain.gasLimit = gas_limit
        plain.data = self.prepare_upgrade_transaction_data(arguments)

        payload = TransactionPayloadToSign(plain)
        signature = signing.sign_transaction(payload, owner.pem_file)
        prepared = PreparedTransaction(plain, signature)
        return prepared

    def prepare_upgrade_transaction_data(self, arguments):
        tx_data = f"upgradeContract@{self.bytecode}@{self.metadata.to_hex()}"

        for arg in arguments:
            tx_data += f"@{_prepare_argument(arg)}"

        return tx_data

    def query(self, proxy, function, arguments):
        arguments = arguments or []
        prepared_arguments = [
            _prepare_argument(argument) for argument in arguments
        ]

        # TODO: move to proxy/core.py?
        payload = {
            "ScAddress": self.address.bech32(),
            "FuncName": function,
            "Args": prepared_arguments
        }

        response = proxy.query_contract(payload)
        return response["data"]["ReturnData"]