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")
Exemple #2
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
Exemple #3
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()}]")
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)
        }
    }
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()}]")
Exemple #6
0
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"]
Exemple #7
0
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, 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

    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, caller, function, arguments, gas_price, gas_limit, value,
                chain, version) -> Transaction:
        self.caller = caller

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

        tx = Transaction()
        tx.nonce = caller.nonce
        tx.value = value
        tx.sender = caller.address.bech32()
        tx.receiver = self.address.bech32()
        tx.gasPrice = gas_price
        tx.gasLimit = gas_limit
        tx.data = self.prepare_execute_transaction_data(function, arguments)
        tx.chainID = chain
        tx.version = version

        tx.sign(caller)
        return tx

    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, owner, arguments, gas_price, gas_limit, value, chain,
                version) -> Transaction:
        self.owner = owner

        arguments = arguments or []
        gas_price = int(gas_price or config.DEFAULT_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 = self.address.bech32()
        tx.gasPrice = gas_price
        tx.gasLimit = gas_limit
        tx.data = self.prepare_upgrade_transaction_data(arguments)
        tx.chainID = chain
        tx.version = version

        tx.sign(owner)
        return tx

    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) -> List[Any]:
        arguments = arguments or []
        prepared_arguments = [
            _prepare_argument(argument) for argument in arguments
        ]

        payload = {
            "ScAddress": self.address.bech32(),
            "FuncName": function,
            "Args": prepared_arguments
        }

        response = proxy.query_contract(payload)
        return_data = response.get("data", {}).get("returnData")
        return [self._interpret_return_data(data) for data in return_data]

    def _interpret_return_data(self, data):
        try:
            as_bytes = base64.b64decode(data)
            as_hex = as_bytes.hex()
            as_number = int(as_hex, 16)

            result = utils.Object()
            result.base64 = data
            result.hex = as_hex
            result.number = as_number
            return result
        except Exception:
            logger.warn(f"Cannot interpret return data: {data}")
            return None
Exemple #8
0
def main():
    logging.basicConfig(level=logging.DEBUG)

    parser = ArgumentParser()
    parser.add_argument("--proxy", default="https://testnet-api.elrond.com")
    parser.add_argument("--pem", required=True)
    parser.add_argument("--reward-address",
                        required=True,
                        help="the reward address")
    parser.add_argument("--nodes-file",
                        required=True,
                        help="file containing list of BLS keys, one per line")
    parser.add_argument("--value", required=True, help="the value to stake")
    args = parser.parse_args()

    proxy_url = args.proxy
    reward_address = Address(args.reward_address)
    lines = utils.read_lines(args.nodes_file)
    value = args.value
    chain = config.get_chain_id()

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

    print("Number of Nodes to stake:", len(lines))
    confirm_continuation()

    for line in lines:
        print(line[:8], "...", line[-8:])

    confirm_continuation()

    print("Elrond Proxy (or Observer) address:", proxy_url)
    print("Chain ID:", chain)
    confirm_continuation()

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

    stake_args: Any = utils.Object()
    stake_args.reward_address = reward_address.bech32()
    stake_args.number_of_nodes = len(lines)
    # Minor programming artifice (the CSV formatting),
    # so that we are compatible with erdpy 0.7.2 (this will change in the future)
    stake_args.nodes_public_keys = ",".join(lines)
    stake_args.estimate_gas = True
    stake_args.gas_price = 1000000000
    stake_args.value = args.value

    stake_args.pem = args.pem
    stake_args.proxy = proxy_url
    stake_args.chain = chain
    stake_args.version = config.get_tx_version()
    stake_args.recall_nonce = True

    print("Transaction will now be sent.")
    confirm_continuation()
    facade.prepare_and_send_stake_transaction(stake_args)
    print("Done.")