async def get_parent_vasp_account( self, vasp_account_address: typing.Union[diem_types.AccountAddress, str] ) -> rpc.Account: """get parent_vasp account accepts child/parent vasp account address, returns parent vasp account raise ValueError if given account address is not ChildVASP or ParentVASP account address raise AccountNotFoundError if no account found by given account address, or could not find the account by the parent_vasp_address found in ChildVASP account. """ account = await self.must_get_account(vasp_account_address) if account.role.type == ACCOUNT_ROLE_PARENT_VASP: return account if account.role.type == ACCOUNT_ROLE_CHILD_VASP: return await self.get_parent_vasp_account( account.role.parent_vasp_address) hex = utils.account_address_hex(vasp_account_address) raise ValueError( f"given account address({hex}) is not a VASP account: {account}")
def send_fake_tx(amount=100, send_to_self=False) -> Tuple[int, Transaction]: user = OneUser.run(db_session, account_amount=100_000_000_000, account_currency=DiemCurrency.XUS) account_id = user.account_id amount = amount payment_type = types.TransactionType.EXTERNAL currency = diem_utils.types.currencies.DiemCurrency.XUS destination_address = "receiver_address" destination_subaddress = "receiver_subaddress" if send_to_self: destination_address = account_address_hex( context.get().config.vasp_address) destination_subaddress = generate_new_subaddress(account_id) send_tx = send_transaction( sender_id=account_id, amount=amount, currency=currency, payment_type=payment_type, destination_address=destination_address, destination_subaddress=destination_subaddress, ) return account_id, get_transaction(send_tx.id) if send_tx else None
def get_account_state_with_proof( self, account_address: diem_types.AccountAddress, version: typing.Optional[int] = None, ledger_version: typing.Optional[int] = None, ) -> rpc.AccountStateWithProof: address = utils.account_address_hex(account_address) params = [address, version, ledger_version] return self.execute("get_account_state_with_proof", params, _parse_obj(lambda: rpc.AccountStateWithProof()))
async def must_get_account( self, account_address: typing.Union[diem_types.AccountAddress, str] ) -> rpc.Account: """must_get_account raises AccountNotFoundError if account could not be found by given address""" account = await self.get_account(account_address) if account is None: hex = utils.account_address_hex(account_address) raise AccountNotFoundError(f"account not found by address: {hex}") return account
def test_sync(): jsonrpc_client = testnet.create_client() faucet = testnet.Faucet(jsonrpc_client) parent_vasp = faucet.gen_account() account = jsonrpc_client.get_account(parent_vasp.account_address) processor = ProcessorStub() config = DEFL_CONFIG.copy() config["accounts"] = [account.address] config["processor"] = processor with tempfile.TemporaryDirectory() as tmpdir: config["progress_file_path"] = tmpdir + "/progress" client = LRWPubSubClient(config) state = client.init_progress_state() assert state == {account.received_events_key: 0} new_state = client.sync(state) assert state == { account.received_events_key: 0 }, "state pass in should be not be changed" # new state seq num increased, as we found the event transfered from DD account when # we genreate the account. assert new_state == {account.received_events_key: 1} # new state is saved assert new_state == client.progress.fetch_state() assert len(processor.events) == 1 assert processor.events[0].sender == utils.account_address_hex( testnet.DESIGNATED_DEALER_ADDRESS) assert processor.events[0].receiver == account.address # nothing happened, do sync once, new state should be same new_state2 = client.sync(new_state) assert new_state2 == new_state assert new_state2 == client.progress.fetch_state() assert len(processor.events) == 1 # transfer coins to account, one new event should be fetched currency = account.balances[0].currency faucet.mint(parent_vasp.auth_key.hex(), 1_000, currency) sleep(2) new_state3 = client.sync(new_state2) assert new_state3 == {account.received_events_key: 2} assert new_state3 == client.progress.fetch_state() assert len(processor.events) == 2 # when init progress state, we should get back state last synced reload_state = client.init_progress_state() assert reload_state == new_state3
def __init__( self, diem_client: DiemClient, custody_account_name: Optional[str] = _DEFAULT_ACCOUNT_NAME, ): self._diem_client = diem_client self._custody: Custody = Custody() self._custody_account_name = custody_account_name self.account = self._custody.get_account(custody_account_name) self.address_str = utils.account_address_hex(self.account.account_address)
async def test_get_parent_vasp_account(client: AsyncClient): faucet = Faucet(client) parent_vasp, child_vasp = await faucet.gen_vasp() account = await client.get_parent_vasp_account(child_vasp.account_address) expected_address = utils.account_address_hex(parent_vasp.account_address) assert account.address == expected_address account = await client.get_parent_vasp_account(parent_vasp.account_address) assert account.address == expected_address
async def get_account( self, account_address: typing.Union[diem_types.AccountAddress, str] ) -> typing.Optional[rpc.Account]: """get on-chain account information Returns None if account not found See [JSON-RPC API Doc](https://github.com/diem/diem/blob/master/json-rpc/docs/method_get_account.md) """ address = utils.account_address_hex(account_address) return await self.execute("get_account", [address], _parse_obj(lambda: rpc.Account()))
def __trade_and_execute_buy(self, quote, trade, diem_deposit_address): if not diem_deposit_address: raise TradeError("Can't execute trade without a deposit address") receiver_vasp, receiver_subaddress = identifier.decode_account( diem_deposit_address, identifier.HRPS[CHAIN_ID.to_int()]) tx_version, tx_sequence = self.send_transaction( currency=quote.currency_pair.value.base, amount=quote.amount, dest_vasp_address=utils.account_address_hex(receiver_vasp), dest_sub_address=receiver_subaddress.hex(), ) trade.executed(tx_version)
def init_onchain_account(custody_private_keys, account_name, account: LocalAccount, base_url, compliance_key, chain_id: int): account_addr = utils.account_address_hex(account.account_address) print( f'Creating and initialize blockchain account {account_name} @ {account_addr}' ) os.environ["CUSTODY_PRIVATE_KEYS"] = custody_private_keys Custody.init(diem_types.ChainId.from_int(chain_id)) vasp = Vasp(diem_client, account_name) vasp.setup_blockchain(base_url, compliance_key) print(f'Account initialization done!') return vasp
async def get_account_sequence( self, account_address: typing.Union[diem_types.AccountAddress, str]) -> int: """get on-chain account sequence number Calls get_account to find on-chain account information and return it's sequence. Raises AccountNotFoundError if get_account returns None """ account = await self.get_account(account_address) if account is None: hex = utils.account_address_hex(account_address) raise AccountNotFoundError(f"account not found by address: {hex}") return int(account.sequence_number)
def refund(payment): if not payment_can_refund(payment): raise InvalidPaymentStatus("unclearedrefund") if not len(payment.chain_transactions) == 1: raise InvalidPaymentStatus("chain_transactions") # TODO - support refund of multiple payments # TODO - Resolve refund address, currency and amount from blockchain target_transaction = payment.chain_transactions[0] if target_transaction.is_refund: raise InvalidPaymentStatus("refund_transaction") refund_target_address, refund_target_sub_address = identifier.decode_account( target_transaction.sender_address, CHAIN_HRP) refund_target_address = utils.account_address_hex(refund_target_address) refund_target_sub_address = refund_target_sub_address.hex() refund_amount = target_transaction.amount # payment.requested_amount refund_currency = DiemCurrency(target_transaction.currency) payment.set_status(PaymentStatus.refund_requested) refund_tx_id = None try: wallet = OnchainWallet() refund_tx_id, _ = wallet.send_transaction( refund_currency, refund_amount, refund_target_address, refund_target_sub_address, # TODO - new sub_address for refund? ) payment.add_chain_transaction( amount=refund_amount, sender_address=wallet.address_str, currency=refund_currency, tx_id=refund_tx_id, is_refund=True, ) payment.set_status(PaymentStatus.refund_completed) except Exception as e: # TODO - narrow to blockchain exception logger.exception("Failed during refund") payment.set_status(PaymentStatus.refund_error) return refund_tx_id, target_transaction
async def get_account_transaction( self, account_address: typing.Union[diem_types.AccountAddress, str], sequence: int, include_events: typing.Optional[bool] = None, ) -> typing.Optional[rpc.Transaction]: """get on-chain account transaction by sequence number Returns None if transaction is not found See [JSON-RPC API Doc](https://github.com/diem/diem/blob/master/json-rpc/docs/method_get_account_transaction.md) """ address = utils.account_address_hex(account_address) params = [address, int(sequence), bool(include_events)] return await self.execute("get_account_transaction", params, _parse_obj(lambda: rpc.Transaction()))
async def get_account_transactions( self, account_address: typing.Union[diem_types.AccountAddress, str], sequence: int, limit: int, include_events: typing.Optional[bool] = None, ) -> typing.List[rpc.Transaction]: """get on-chain account transactions by start sequence number and limit size Returns empty list if no transactions found See [JSON-RPC API Doc](https://github.com/diem/diem/blob/master/json-rpc/docs/method_get_account_transactions.md) """ address = utils.account_address_hex(account_address) params = [address, int(sequence), int(limit), bool(include_events)] return await self.execute("get_account_transactions", params, _parse_list(lambda: rpc.Transaction()))
def test_get_parent_vasp_account(): client = testnet.create_client() faucet = testnet.Faucet(client) parent_vasp = faucet.gen_account() child_vasp = LocalAccount.generate() signed_txn = create_child_vasp_txn(parent_vasp, child_vasp) client.submit(signed_txn) client.wait_for_transaction(signed_txn) account = client.get_parent_vasp_account(child_vasp.account_address) expected_address = utils.account_address_hex(parent_vasp.account_address) assert account.address == expected_address account = client.get_parent_vasp_account(parent_vasp.account_address) assert account.address == expected_address
def mint( self, authkey_hex: str, amount: int, identifier: str, session: Optional[requests.Session] = None, timeout: Optional[Union[float, Tuple[float, float]]] = None, ) -> int: dd_address_hex = account_address_hex(DESIGNATED_DEALER_ADDRESS) account = BlockchainMock.get_account_resource(dd_address_hex) sequence = account.sequence_number version = BlockchainMock.blockchain.version decoded_addr, decoded_subaddr = decode_account(authkey_hex) metadata = general_metadata(to_subaddress=decoded_subaddr) address_hex_bytes = account_address_bytes(decoded_addr) process_incoming_transaction( sender_address=dd_address_hex, receiver_address=authkey_hex, sequence=sequence, amount=amount, currency=DiemCurrency.Coin1, metadata=metadata, ) BlockchainMock.blockchain.version += 1 tx = MockSignedTransaction( sender=bytes.fromhex(ASSOC_AUTHKEY), amount=amount, currency=identifier, receiver=address_hex_bytes, metadata=metadata, sequence=account.sequence_number, version=version, ) account.sequence_number += 1 account.transactions[sequence] = tx BlockchainMock.blockchain.transactions[version] = tx return sequence
def main(): # generate private key private_key = Ed25519PrivateKey.generate() # generate auth key auth_key = AuthKey.from_public_key(private_key.public_key()) # create intent identifier account_identifier = identifier.encode_account( utils.account_address_hex(auth_key.account_address()), None, identifier.TDM) encoded_intent_identifier = identifier.encode_intent( account_identifier, "XUS", 10000000) print(f"Encoded IntentIdentifier: {encoded_intent_identifier}") # deserialize IntentIdentifier intent_identifier = identifier.decode_intent(encoded_intent_identifier, identifier.TDM) print( f"Account (HEX) from intent: {utils.account_address_hex(intent_identifier.account_address)}" ) print(f"Amount from intent: {intent_identifier.amount}") print(f"Currency from intent: {intent_identifier.currency_code}")
def _cover_buy(order: Order, quote: QuoteData) -> bool: deposit_address = get_inventory_deposit_address() trade_id = LpClient().trade_and_execute( quote_id=quote.quote_id, direction=Direction[order.direction], diem_deposit_address=deposit_address, ) trade_info = _wait_for_trade(order=order, trade_id=trade_id) if not trade_info: update_order( order_id=OrderId(UUID(order.id)), cover_status=CoverStatus.FailedCoverLPTradeError, ) return False update_order( order_id=OrderId(UUID(order.id)), cover_status=CoverStatus.PendingCoverValidation, ) vasp_address, internal_subaddress = decode_account( deposit_address, context.get().config.diem_address_hrp() ) if not _validate_blockchain_transaction( blockchain_version=trade_info.tx_version, vasp_address=utils.account_address_hex(vasp_address), internal_subaddress=internal_subaddress.hex(), amount=round(trade_info.amount), ): update_order( order_id=OrderId(UUID(order.id)), cover_status=CoverStatus.FailedCoverTransactionError, ) return False return True
refill_amount_human = args.amount threshold_amount_human = args.threshold currencies = args.currencies network_chainid = args.network_chainid network_json_rpc_url = args.network_json_rpc_url sleep_interval = args.sleep_interval if auth_key is None: print("Must get an authentication key to watch!") sys.exit(1) diem_client = jsonrpc.Client(network_json_rpc_url) watched_account_auth_key = AuthKey(bytes.fromhex(auth_key)) watched_account_addr = watched_account_auth_key.account_address() watched_account_addr_hex = utils.account_address_hex(watched_account_addr) refill_amount = int(refill_amount_human) * 1_000_000 # to microdiem threshold_amount = int(threshold_amount_human) * 1_000_000 # to microdiem sleep_interval = float(sleep_interval) while True: print(f'current datetime: {datetime.now().isoformat().replace("T", " ")}') for currency in currencies: currency_balance = next( b.amount for b in diem_client.get_account(watched_account_addr).balances) print(f"{currency} balance is {currency_balance} ", ) if currency_balance > threshold_amount:
def main(): print("#1 connect to testnet") client = testnet.create_client() print("#2 Generate Keys") # generate private key for sender account sender_private_key = Ed25519PrivateKey.generate() # generate auth key for sender account sender_auth_key = AuthKey.from_public_key(sender_private_key.public_key()) print( f"Generated sender address: {utils.account_address_hex(sender_auth_key.account_address())}" ) print("#3 Create account") faucet = testnet.Faucet(client) testnet.Faucet.mint(faucet, sender_auth_key.hex(), 100000000, CURRENCY) print("#4 Get account information") sender_account = client.get_account(sender_auth_key.account_address()) events_key = sender_account.received_events_key print("#5 Start event listener") get_events_example.subscribe(client, events_key) print("#6 Add money to account") faucet = testnet.Faucet(client) testnet.Faucet.mint(faucet, sender_auth_key.hex(), 10000000, CURRENCY) print("#7 Generate Keys") # generate private key for receiver account receiver_private_key = Ed25519PrivateKey.generate() # generate auth key for receiver account receiver_auth_key = AuthKey.from_public_key( receiver_private_key.public_key()) print( f"Generated receiver address: {utils.account_address_hex(receiver_auth_key.account_address())}" ) print("#8 Create second account") faucet = testnet.Faucet(client) testnet.Faucet.mint(faucet, receiver_auth_key.hex(), 1000000, CURRENCY) print("#9 Generate IntentIdentifier") account_identifier = identifier.encode_account( utils.account_address_hex(receiver_auth_key.account_address()), None, identifier.TDM) encoded_intent_identifier = identifier.encode_intent( account_identifier, CURRENCY, 10000000) print(f"Encoded IntentIdentifier: {encoded_intent_identifier}") print("#10 Deserialize IntentIdentifier") intent_identifier = identifier.decode_intent(encoded_intent_identifier, identifier.TDM) print( f"Account (HEX) from intent: {utils.account_address_hex(intent_identifier.account_address)}" ) print(f"Amount from intent: {intent_identifier.amount}") print(f"Currency from intent: {intent_identifier.currency_code}") print("#11 Peer 2 peer transaction") # create script script = stdlib.encode_peer_to_peer_with_metadata_script( currency=utils.currency_code(intent_identifier.currency_code), payee=intent_identifier.account_address, amount=intent_identifier.amount, metadata=b'', # no requirement for metadata and metadata signature metadata_signature=b'', ) # create transaction raw_transaction = diem_types.RawTransaction( sender=sender_auth_key.account_address(), sequence_number=sender_account.sequence_number, payload=diem_types.TransactionPayload__Script(script), max_gas_amount=1_000_000, gas_unit_price=0, gas_currency_code=CURRENCY, expiration_timestamp_secs=int(time.time()) + 30, chain_id=testnet.CHAIN_ID, ) # sign transaction signature = sender_private_key.sign( utils.raw_transaction_signing_msg(raw_transaction)) public_key_bytes = utils.public_key_bytes(sender_private_key.public_key()) signed_txn = utils.create_signed_transaction(raw_transaction, public_key_bytes, signature) # submit transaction client.submit(signed_txn) # wait for transaction client.wait_for_transaction(signed_txn)
def __init__(self): super().__init__(utils.account_address_hex(DESIGNATED_DEALER_ADDRESS))