def __init__(self, client: ExonumClient, instance_name: str = "crypto", version: str = "0.2.0"): self.client = client service_name = "exonum-cryptocurrency" self.service_version = version self.instance_name = instance_name self.loader = client.protobuf_loader() self.loader.initialize() self.loader.load_main_proto_files() self.loader.load_service_proto_files(runtime_id=0, artifact_name="exonum-supervisor", artifact_version="1.0.0") self.loader.load_service_proto_files( runtime_id=0, artifact_name=service_name, artifact_version=self.service_version) self.cryptocurrency_module = ModuleManager.import_service_module( service_name, self.service_version, "service") self.types_module = ModuleManager.import_service_module( service_name, self.service_version, "exonum.crypto.types") instance_id = client.public_api.get_instance_id_by_name( self.instance_name) self.msg_generator = MessageGenerator( instance_id=instance_id, artifact_name=service_name, artifact_version=self.service_version)
def __init__(self, client: ExonumClient): self.client = client cryptocurrency_service_name = "exonum-cryptocurrency-advanced" cryptocurrency_service_version = "0.13.0-rc.2" self.loader = client.protobuf_loader() self.loader.initialize() self.loader.load_main_proto_files() self.loader.load_service_proto_files( runtime_id=0, artifact_name="exonum-supervisor", artifact_version="0.13.0-rc.2", ) self.loader.load_service_proto_files( runtime_id=0, artifact_name=cryptocurrency_service_name, artifact_version=cryptocurrency_service_version, ) self.cryptocurrency_module = ModuleManager.import_service_module( cryptocurrency_service_name, cryptocurrency_service_version, "service") self.types_module = ModuleManager.import_service_module( cryptocurrency_service_name, cryptocurrency_service_version, "types") instance_id = client.public_api.get_instance_id_by_name("crypto") self.msg_generator = MessageGenerator( instance_id=instance_id, artifact_name=cryptocurrency_service_name, artifact_version=cryptocurrency_service_version)
class ExonumCryptoAdvancedClient: """Class provides an interface to simplify interaction with cryptocurrency-advanced service.""" def __init__(self, client: ExonumClient): self.client = client cryptocurrency_service_name = 'exonum-cryptocurrency-advanced:0.13.0-rc.2' self.loader = client.protobuf_loader() self.loader.initialize() self.loader.load_main_proto_files() self.loader.load_service_proto_files( runtime_id=0, service_name='exonum-supervisor:0.13.0-rc.2') self.loader.load_service_proto_files( runtime_id=0, service_name=cryptocurrency_service_name) self.cryptocurrency_module = ModuleManager.import_service_module( cryptocurrency_service_name, 'service') self.types_module = ModuleManager.import_service_module( cryptocurrency_service_name, 'types') instance_id = client.get_instance_id_by_name("crypto") self.msg_generator = MessageGenerator( instance_id=instance_id, artifact_name=cryptocurrency_service_name) def __enter__(self): return self def __exit__(self, exc_type, exc_value, traceback): self.loader.deinitialize() def create_wallet(self, keys, wallet_name): """Wrapper for create wallet operation.""" create_wallet = self.cryptocurrency_module.CreateWallet() create_wallet.name = wallet_name create_wallet_tx = self.msg_generator.create_message(create_wallet) create_wallet_tx.sign(keys) return self.client.send_transaction(create_wallet_tx) def issue(self, keys, amount): """Wrapper for issue operation.""" issue = self.cryptocurrency_module.Issue() issue.amount = amount issue.seed = gen_seed() issue_tx = self.msg_generator.create_message(issue) issue_tx.sign(keys) return self.client.send_transaction(issue_tx) def get_wallet_info(self, keys): """Wrapper for get wallet info operation.""" return self.client.get_service( "crypto/v1", "wallets/info?pub_key=" + keys.public_key.hex()) def transfer(self, amount, from_wallet, to_wallet): """Wrapper for transfer operation.""" transfer = self.cryptocurrency_module.Transfer() transfer.amount = amount transfer.seed = gen_seed() transfer.to.CopyFrom(self.types_module.PublicKey(data=to_wallet)) transfer_tx = self.msg_generator.create_message(transfer) transfer_tx.sign(from_wallet) return self.client.send_transaction(transfer_tx)
def create_wallet(client: ExonumClient, message_generator: MessageGenerator, name: str) -> KeyPair: """Creates a wallet with the given name and returns a KeyPair for it.""" key_pair = KeyPair.generate() # Load the "service.proto" from the Cryptocurrency service: cryptocurrency_module = ModuleManager.import_service_module( CRYPTOCURRENCY_ARTIFACT_NAME, "service") # Create a Protobuf message: create_wallet_message = cryptocurrency_module.TxCreateWallet() create_wallet_message.name = name # Convert the Protobuf message to an Exonum message and sign it: create_wallet_tx = message_generator.create_message(create_wallet_message) create_wallet_tx.sign(key_pair) # Send the transaction to Exonum: response = client.send_transaction(create_wallet_tx) ensure_status_code(response) tx_hash = response.json()["tx_hash"] # Wait for new blocks: with client.create_subscriber() as subscriber: subscriber.wait_for_new_block() subscriber.wait_for_new_block() ensure_transaction_success(client, tx_hash) print(f"Successfully created wallet with name '{name}'") return key_pair
def transfer( client: ExonumClient, message_generator: MessageGenerator, from_keypair: KeyPair, to_key: PublicKey, amount: int ) -> Tuple[int, int]: """This example transfers tokens from one wallet to the other one and returns the balances of these wallets.""" cryptocurrency_module = ModuleManager.import_service_module(CRYPTOCURRENCY_ARTIFACT_NAME, "service") # Note that since we are using the Cryptocurrency module, # we need to load helpers from this module and not from the main module: helpers_module = ModuleManager.import_service_module(CRYPTOCURRENCY_ARTIFACT_NAME, "helpers") transfer_message = cryptocurrency_module.Transfer() transfer_message.to.CopyFrom(helpers_module.PublicKey(data=to_key.value)) transfer_message.amount = amount transfer_message.seed = Seed.get_seed() transfer_tx = message_generator.create_message(transfer_message) transfer_tx.sign(from_keypair) response = client.send_transaction(transfer_tx) ensure_status_code(response) tx_hash = response.json()["tx_hash"] # Wait for new blocks: with client.create_subscriber() as subscriber: subscriber.wait_for_new_block() subscriber.wait_for_new_block() ensure_transaction_success(client, tx_hash) from_balance = get_balance(client, from_keypair.public_key) to_balance = get_balance(client, to_key) return from_balance, to_balance
def __init__(self, client: ExonumClient): self.client = client cryptocurrency_service_name = 'exonum-cryptocurrency-advanced:0.13.0-rc.2' self.loader = client.protobuf_loader() self.loader.initialize() self.loader.load_main_proto_files() self.loader.load_service_proto_files( runtime_id=0, service_name='exonum-supervisor:0.13.0-rc.2') self.loader.load_service_proto_files( runtime_id=0, service_name=cryptocurrency_service_name) self.cryptocurrency_module = ModuleManager.import_service_module( cryptocurrency_service_name, 'service') self.types_module = ModuleManager.import_service_module( cryptocurrency_service_name, 'types') instance_id = client.get_instance_id_by_name("crypto") self.msg_generator = MessageGenerator( instance_id=instance_id, artifact_name=cryptocurrency_service_name)
def transfer(client: ExonumClient, message_generator: MessageGenerator, from_keypair: KeyPair, to_key: PublicKey, amount: int) -> Tuple[int, int]: """This example transfers tokens from one wallet to the other one and returns the balances of these wallets.""" cryptocurrency_module = ModuleManager.import_service_module( CRYPTOCURRENCY_ARTIFACT_NAME, CRYPTOCURRENCY_ARTIFACT_VERSION, "service") # Note that since we are using the Cryptocurrency module, # we need to load types from this module and not from the main module: types_module = ModuleManager.import_service_module( CRYPTOCURRENCY_ARTIFACT_NAME, CRYPTOCURRENCY_ARTIFACT_VERSION, "exonum.crypto.types") transfer_message = cryptocurrency_module.Transfer() # The address is a hash of a `Caller` protobuf message. hash_address = message_generator.pk_to_hash_address(to_key) if hash_address is None: raise Exception transfer_message.to.CopyFrom(types_module.Hash(data=hash_address.value)) transfer_message.amount = amount transfer_message.seed = Seed.get_seed() transfer_tx = message_generator.create_message(transfer_message) transfer_tx.sign(from_keypair) response = client.public_api.send_transaction(transfer_tx) ensure_status_code(response) tx_hash = response.json()["tx_hash"] # Wait for new blocks: with client.create_subscriber("blocks") as subscriber: subscriber.wait_for_new_event() subscriber.wait_for_new_event() ensure_transaction_success(client, tx_hash) from_balance = get_balance(client, from_keypair.public_key) to_balance = get_balance(client, to_key) return from_balance, to_balance
def run() -> None: """This example creates two wallets (for Alice and Bob) and performs several transactions between these wallets.""" client = ExonumClient(hostname="127.0.0.1", public_api_port=8080, private_api_port=8081) with client.protobuf_loader() as loader: # Load and compile proto files: loader.load_main_proto_files() loader.load_service_proto_files(RUST_RUNTIME_ID, CRYPTOCURRENCY_ARTIFACT_NAME, CRYPTOCURRENCY_ARTIFACT_VERSION) instance_id = get_cryptocurrency_instance_id(client) cryptocurrency_message_generator = MessageGenerator( instance_id, CRYPTOCURRENCY_ARTIFACT_NAME, CRYPTOCURRENCY_ARTIFACT_VERSION) alice_keypair = create_wallet(client, cryptocurrency_message_generator, "Alice") bob_keypair = create_wallet(client, cryptocurrency_message_generator, "Bob") alice_balance = get_balance(client, alice_keypair.public_key) bob_balance = get_balance(client, bob_keypair.public_key) print("Created the wallets for Alice and Bob. Balance:") print(f" Alice => {alice_balance}") print(f" Bob => {bob_balance}") amount = 10 alice_balance, bob_balance = transfer( client, cryptocurrency_message_generator, alice_keypair, bob_keypair.public_key, amount) print(f"Transferred {amount} tokens from Alice's wallet to Bob's one") print(f" Alice => {alice_balance}") print(f" Bob => {bob_balance}") amount = 25 bob_balance, alice_balance = transfer( client, cryptocurrency_message_generator, bob_keypair, alice_keypair.public_key, amount) print(f"Transferred {amount} tokens from Bob's wallet to Alice's one") print(f" Alice => {alice_balance}") print(f" Bob => {bob_balance}")
class ExonumCryptoAdvancedClient: """Class provides an interface to simplify interaction with cryptocurrency-advanced service.""" def __init__(self, client: ExonumClient, instance_name: str = "crypto", version: str = "0.2.0"): self.client = client service_name = "exonum-cryptocurrency" self.service_version = version self.instance_name = instance_name self.loader = client.protobuf_loader() self.loader.initialize() self.loader.load_main_proto_files() self.loader.load_service_proto_files(runtime_id=0, artifact_name="exonum-supervisor", artifact_version="1.0.0") self.loader.load_service_proto_files( runtime_id=0, artifact_name=service_name, artifact_version=self.service_version) self.cryptocurrency_module = ModuleManager.import_service_module( service_name, self.service_version, "service") self.types_module = ModuleManager.import_service_module( service_name, self.service_version, "exonum.crypto.types") instance_id = client.public_api.get_instance_id_by_name( self.instance_name) self.msg_generator = MessageGenerator( instance_id=instance_id, artifact_name=service_name, artifact_version=self.service_version) def __enter__(self): return self def __exit__(self, exc_type, exc_value, traceback): self.loader.deinitialize() def create_wallet(self, keys, wallet_name): """Wrapper for create wallet operation.""" if self.service_version == "0.1.0": create_wallet = self.cryptocurrency_module.TxCreateWallet() else: create_wallet = self.cryptocurrency_module.CreateWallet() create_wallet.name = wallet_name create_wallet_tx = self.msg_generator.create_message(create_wallet) create_wallet_tx.sign(keys) return self.client.public_api.send_transaction(create_wallet_tx) def issue(self, keys, amount): """Wrapper for issue operation.""" issue = self.cryptocurrency_module.Issue() issue.amount = amount issue.seed = gen_seed() issue_tx = self.msg_generator.create_message(issue) issue_tx.sign(keys) return self.client.public_api.send_transaction(issue_tx) def get_wallet_info(self, keys): """Wrapper for get wallet info operation.""" public_service_api = self.client.service_public_api(self.instance_name) return public_service_api.get_service("v1/wallets/info?pub_key=" + keys.public_key.hex()) def get_balance(self, keys): wallet = self.get_wallet_info(keys).json() return wallet["wallet_proof"]["to_wallet"]["entries"][0]["value"][ "balance"] def get_history_len(self, keys): wallet = self.get_wallet_info(keys).json() return wallet["wallet_proof"]["to_wallet"]["entries"][0]["value"][ "history_len"] def transfer(self, amount, from_wallet, to_wallet): """Wrapper for transfer operation.""" transfer = self.cryptocurrency_module.Transfer() transfer.amount = amount transfer.seed = gen_seed() hash_address = self.msg_generator.pk_to_hash_address(to_wallet) transfer.to.CopyFrom(self.types_module.Hash(data=hash_address.value)) transfer_tx = self.msg_generator.create_message(transfer) transfer_tx.sign(from_wallet) return self.client.public_api.send_transaction(transfer_tx)
def run() -> None: """This example creates a wallet in the Cryptocurrency service, retrieves proofs for the wallet and verifies them. For the example to work, be sure to have `exonum-cryptocurrency-advanced` service instance with name `XNM` deployed.""" client = ExonumClient(hostname="127.0.0.1", public_api_port=8080, private_api_port=8081) with client.protobuf_loader() as loader: # Load and compile proto files: loader.load_main_proto_files() loader.load_service_proto_files(RUST_RUNTIME_ID, CRYPTOCURRENCY_ARTIFACT_NAME) instance_id = get_cryptocurrency_instance_id(client) cryptocurrency_message_generator = MessageGenerator( instance_id, CRYPTOCURRENCY_ARTIFACT_NAME) alice_keypair = create_wallet(client, cryptocurrency_message_generator, "Alice") wallet_info_response = client.get_service( CRYPTOCURRENCY_INSTANCE_NAME, "v1/wallets/info?pub_key={}".format( alice_keypair.public_key.hex())) ensure_status_code(wallet_info_response) wallet_info = wallet_info_response.json() # `MapProof` to the whole Exonum state hash: proof_to_table = wallet_info["wallet_proof"]["to_table"] # Expected hash of the proof to the table is a state hash of the block: expected_to_table_hash_raw = wallet_info["block_proof"]["block"][ "state_hash"] expected_to_table_hash = Hash( bytes.fromhex(expected_to_table_hash_raw)) # Verify the proof to the table: verify_proof_to_table(proof_to_table, expected_to_table_hash) # `MapProof` to the wallet as a part of the Cryptocurrency schema: proof_to_wallet = wallet_info["wallet_proof"]["to_wallet"] # Expected hash of the proof to the wallet is the value stored in the # proof to the table: expected_to_wallet_hash_raw = wallet_info["wallet_proof"]["to_table"][ "entries"][0]["value"] expected_to_wallet_hash = Hash( bytes.fromhex(expected_to_wallet_hash_raw)) # Verify the proof to the wallet: verify_proof_to_wallet(proof_to_wallet, expected_to_wallet_hash) # `ListProof` for the transactions associtated with the wallet: proof_wallet_history = wallet_info["wallet_history"]["proof"] # Expected hash for the wallet history is the hash stored in the proof # to the wallet: expected_history_hash_raw = wallet_info["wallet_proof"]["to_wallet"][ "entries"][0]["value"]["history_hash"] expected_history_hash = Hash(bytes(expected_history_hash_raw["data"])) # Verify the proof for the wallet history: verify_wallet_history_proof(proof_wallet_history, expected_history_hash)