def test_from_proto_text_memo(self): op_result = gen_payment_op_result(xdr_const.PAYMENT_UNDERFUNDED) result_xdr = gen_result_xdr(xdr_const.txFAILED, [op_result]) tx_src = gen_account_id() dest = gen_account_id() operations = [gen_payment_op(dest, amount=20)] envelope_xdr = gen_tx_envelope_xdr(tx_src, 1, operations, gen_text_memo(b'somememo')) history_item = tx_pb.HistoryItem( hash=model_pb2.TransactionHash(value=b'somehash'), result_xdr=result_xdr, envelope_xdr=envelope_xdr, cursor=tx_pb.Cursor(value=b'cursor1'), ) data = TransactionData.from_proto(history_item) assert data.tx_hash == b'somehash' assert len(data.payments) == 1 payment = data.payments[0] assert payment.sender.raw == tx_src.ed25519 assert payment.destination.raw == dest.ed25519 assert payment.tx_type == TransactionType.UNKNOWN assert payment.quarks == 20 assert not payment.invoice assert payment.memo == 'somememo'
def test_submit_earn_batch_with_memo(self, grpc_channel, executor, app_index_client): sender = PrivateKey.random() earns = [Earn(PrivateKey.random().public_key, 100000)] future = executor.submit(app_index_client.submit_earn_batch, sender, earns, memo="somememo") account_req = self._set_successful_get_account_info_response(grpc_channel, sender, 10) result_xdr = gen_result_xdr(xdr_const.txSUCCESS, [gen_payment_op_result(xdr_const.PAYMENT_SUCCESS)]) submit_req = self._set_successful_submit_transaction_response(grpc_channel, b'somehash', result_xdr) batch_earn_result = future.result() assert len(batch_earn_result.succeeded) == 1 assert len(batch_earn_result.failed) == 0 earn_result = batch_earn_result.succeeded[0] assert earn_result.earn == earns[0] assert earn_result.tx_hash == b'somehash' assert not earn_result.error assert account_req.account_id.value == sender.public_key.stellar_address expected_memo = memo.TextMemo('somememo') self._assert_earn_batch_envelope(submit_req.envelope_xdr, [sender], sender, 100, 11, expected_memo, sender, earns) assert len(submit_req.invoice_list.invoices) == 0
def test_submit_earn_batch_with_invoices(self, grpc_channel, executor, app_index_client): sender = PrivateKey.random() earns = [ Earn(PrivateKey.random().public_key, 100000, invoice=Invoice([LineItem('title1', 100000, 'description1', b'somesku')])), Earn(PrivateKey.random().public_key, 100000, invoice=Invoice([LineItem('title2', 100000, 'description2', b'somesku')])), ] future = executor.submit(app_index_client.submit_earn_batch, sender, earns) account_req = self._set_successful_get_account_info_response(grpc_channel, sender, 10) result_xdr = gen_result_xdr(xdr_const.txSUCCESS, [gen_payment_op_result(xdr_const.PAYMENT_SUCCESS)]) submit_req = self._set_successful_submit_transaction_response(grpc_channel, b'somehash', result_xdr) batch_earn_result = future.result() assert len(batch_earn_result.succeeded) == 2 assert len(batch_earn_result.failed) == 0 for idx, earn_result in enumerate(batch_earn_result.succeeded): assert earn_result.tx_hash == b'somehash' assert earn_result.earn == earns[idx] assert not earn_result.error assert account_req.account_id.value == sender.public_key.stellar_address il = InvoiceList([earn.invoice for earn in earns]) expected_memo = memo.HashMemo(AgoraMemo.new(1, TransactionType.EARN, 1, il.get_sha_224_hash()).val) self._assert_earn_batch_envelope(submit_req.envelope_xdr, [sender], sender, 100, 11, expected_memo, sender, earns) assert len(submit_req.invoice_list.invoices) == 2 assert submit_req.invoice_list.SerializeToString() == il.to_proto().SerializeToString()
def test_submit_payment_tx_failed(self, grpc_channel, executor, app_index_client): sender = PrivateKey.random() dest = PrivateKey.random().public_key payment = Payment(sender, dest, TransactionType.EARN, 100000) future = executor.submit(app_index_client.submit_payment, payment) account_req = self._set_successful_get_account_info_response(grpc_channel, sender, 10) result_xdr = gen_result_xdr(xdr_const.txFAILED, [gen_payment_op_result(xdr_const.PAYMENT_UNDERFUNDED)]) resp = tx_pb.SubmitTransactionResponse( result=tx_pb.SubmitTransactionResponse.Result.FAILED, hash=model_pb2.TransactionHash(value=b'somehash'), ledger=10, result_xdr=result_xdr, ) submit_req = self._set_submit_transaction_response(grpc_channel, resp) with pytest.raises(InsufficientBalanceError): future.result() assert account_req.account_id.value == sender.public_key.stellar_address expected_memo = memo.HashMemo(AgoraMemo.new(1, TransactionType.EARN, 1, b'').val) self._assert_payment_envelope(submit_req.envelope_xdr, [sender], sender, 100, 11, expected_memo, payment) assert len(submit_req.invoice_list.invoices) == 0
def test_submit_earn_batch_with_whitelisting(self, grpc_channel, executor, whitelisting_client): sender = PrivateKey.random() earns = [Earn(PrivateKey.random().public_key, 100000)] future = executor.submit(whitelisting_client.submit_earn_batch, sender, earns) account_req = self._set_successful_get_account_info_response(grpc_channel, sender, 10) result_xdr = gen_result_xdr(xdr_const.txSUCCESS, [gen_payment_op_result(xdr_const.PAYMENT_SUCCESS)]) submit_req = self._set_successful_submit_transaction_response(grpc_channel, b'somehash', result_xdr) batch_earn_result = future.result() assert len(batch_earn_result.succeeded) == 1 assert len(batch_earn_result.failed) == 0 earn_result = batch_earn_result.succeeded[0] assert earn_result.earn == earns[0] assert earn_result.tx_hash == b'somehash' assert not earn_result.error assert account_req.account_id.value == sender.public_key.stellar_address expected_signers = [sender, whitelisting_client.whitelist_key] expected_memo = memo.HashMemo(AgoraMemo.new(1, TransactionType.EARN, 1, b'').val) self._assert_earn_batch_envelope(submit_req.envelope_xdr, expected_signers, sender, 100, 11, expected_memo, sender, earns)
def test_submit_earn_batch_multiple(self, grpc_channel, executor, app_index_client): sender = PrivateKey.random() all_earns = [Earn(PrivateKey.random().public_key, i) for i in range(250)] future = executor.submit(app_index_client.submit_earn_batch, sender, all_earns) account_reqs = [] submit_reqs = [] tx_hashes = [] result_xdr = gen_result_xdr(xdr_const.txSUCCESS, [gen_payment_op_result(xdr_const.PAYMENT_SUCCESS)]) starting_seq = 10 for i in range(3): account_reqs.append(self._set_successful_get_account_info_response(grpc_channel, sender, starting_seq + i)) tx_hash = 'somehash{}'.format(i).encode() submit_reqs.append(self._set_successful_submit_transaction_response(grpc_channel, tx_hash, result_xdr)) tx_hashes.append(tx_hash) batch_earn_result = future.result() assert len(batch_earn_result.succeeded) == 250 assert len(batch_earn_result.failed) == 0 for account_req in account_reqs: assert account_req.account_id.value == sender.public_key.stellar_address earn_batches = partition(all_earns, 100) for idx, submit_req in enumerate(submit_reqs): expected_memo = memo.HashMemo(AgoraMemo.new(1, TransactionType.EARN, 1, b'').val) self._assert_earn_batch_envelope(submit_req.envelope_xdr, [sender], sender, 100, starting_seq + idx + 1, expected_memo, sender, earn_batches[idx]) assert len(submit_req.invoice_list.invoices) == 0
def test_get_transaction(self, grpc_channel, executor, app_index_client): tx_hash = b'somehash' future = executor.submit(app_index_client.get_transaction, tx_hash) _, request, rpc = grpc_channel.take_unary_unary( tx_pb.DESCRIPTOR.services_by_name['Transaction'].methods_by_name['GetTransaction'] ) # Create full response op_result = gen_payment_op_result(xdr_const.PAYMENT_SUCCESS) result_xdr = gen_result_xdr(xdr_const.txSUCCESS, [op_result, op_result]) il = model_pb2.InvoiceList(invoices=[ model_pb2.Invoice( items=[ model_pb2.Invoice.LineItem(title='t1', amount=15), ] ), ]) fk = InvoiceList.from_proto(il).get_sha_224_hash() memo = AgoraMemo.new(1, TransactionType.EARN, 1, fk) hash_memo = gen_hash_memo(memo.val) acc1 = gen_account_id() acc2 = gen_account_id() operations = [gen_payment_op(acc2, amount=15)] envelope_xdr = gen_tx_envelope_xdr(acc1, 1, operations, hash_memo) history_item = tx_pb.HistoryItem( hash=model_pb2.TransactionHash(value=tx_hash), result_xdr=result_xdr, envelope_xdr=envelope_xdr, cursor=tx_pb.Cursor(value=b'cursor1'), invoice_list=il, ) resp = tx_pb.GetTransactionResponse( state=tx_pb.GetTransactionResponse.State.SUCCESS, ledger=10, item=history_item, ) rpc.terminate(resp, (), grpc.StatusCode.OK, '') tx_data = future.result() assert tx_data.tx_hash == tx_hash assert len(tx_data.payments) == 1 assert not tx_data.error payment1 = tx_data.payments[0] assert payment1.sender.raw == acc1.ed25519 assert payment1.destination.raw == acc2.ed25519 assert payment1.tx_type == memo.tx_type() assert payment1.quarks == 15 assert (payment1.invoice.to_proto().SerializeToString() == il.invoices[0].SerializeToString()) assert not payment1.memo assert request.transaction_hash.value == tx_hash
def test_from_proto_agora_memo(self): op_result = gen_payment_op_result(xdr_const.PAYMENT_SUCCESS) result_xdr = gen_result_xdr(xdr_const.txSUCCESS, [op_result, op_result]) il = model_pb2.InvoiceList(invoices=[ model_pb2.Invoice(items=[ model_pb2.Invoice.LineItem(title='t1', amount=10), ]), model_pb2.Invoice(items=[ model_pb2.Invoice.LineItem(title='t1', amount=15), ]), ]) fk = InvoiceList.from_proto(il).get_sha_224_hash() memo = AgoraMemo.new(1, TransactionType.P2P, 0, fk) hash_memo = gen_hash_memo(memo.val) acc1 = gen_account_id() acc2 = gen_account_id() acc3 = gen_account_id() operations = [ gen_payment_op(acc2, src=acc1, amount=10), gen_payment_op(acc1, src=acc2, amount=15), ] envelope_xdr = gen_tx_envelope_xdr(acc3, 1, operations, hash_memo) history_item = tx_pb.HistoryItem( hash=model_pb2.TransactionHash(value=b'somehash'), result_xdr=result_xdr, envelope_xdr=envelope_xdr, cursor=tx_pb.Cursor(value=b'cursor1'), invoice_list=il, ) data = TransactionData.from_proto(history_item) assert data.tx_hash == b'somehash' assert len(data.payments) == 2 payment1 = data.payments[0] assert payment1.sender.raw == acc1.ed25519 assert payment1.destination.raw == acc2.ed25519 assert payment1.tx_type == memo.tx_type() assert payment1.quarks == 10 assert (payment1.invoice.to_proto().SerializeToString() == il.invoices[0].SerializeToString()) assert not payment1.memo payment2 = data.payments[1] assert payment2.sender.raw == acc2.ed25519 assert payment2.destination.raw == acc1.ed25519 assert payment2.tx_type == TransactionType.P2P assert payment2.quarks == 15 assert (payment2.invoice.to_proto().SerializeToString() == il.invoices[1].SerializeToString()) assert not payment2.memo
def test_error_from_result_multi_op(self): op_results = [ gen_create_op_result(xdr_const.CREATE_ACCOUNT_SUCCESS), gen_create_op_result(xdr_const.CREATE_ACCOUNT_MALFORMED), gen_payment_op_result(xdr_const.PAYMENT_UNDERFUNDED), ] result_xdr = gen_result_xdr(xdr_const.txFAILED, op_results) te = TransactionErrors.from_result(result_xdr) assert isinstance(te.tx_error, Error) assert not te.op_errors[0] assert isinstance(te.op_errors[1], TransactionMalformedError) assert isinstance(te.op_errors[2], InsufficientBalanceError)
def test_submit_earn_batch_tx_failed(self, grpc_channel, executor, app_index_client): sender = PrivateKey.random() earns = [ Earn(PrivateKey.random().public_key, 100000), Earn(PrivateKey.random().public_key, 100000), ] future = executor.submit(app_index_client.submit_earn_batch, sender, earns) account_req = self._set_successful_get_account_info_response(grpc_channel, sender, 10) result_xdr = gen_result_xdr(xdr_const.txFAILED, [gen_payment_op_result(xdr_const.PAYMENT_UNDERFUNDED), gen_payment_op_result(xdr_const.PAYMENT_NO_DESTINATION)]) resp = tx_pb.SubmitTransactionResponse( result=tx_pb.SubmitTransactionResponse.Result.FAILED, hash=model_pb2.TransactionHash(value=b'somehash'), ledger=10, result_xdr=result_xdr, ) submit_req = self._set_submit_transaction_response(grpc_channel, resp) batch_earn_result = future.result() assert len(batch_earn_result.succeeded) == 0 assert len(batch_earn_result.failed) == 2 expected_errors = [InsufficientBalanceError, DestinationDoesNotExistError] for idx, earn_result in enumerate(batch_earn_result.failed): assert earn_result.earn == earns[idx] assert earn_result.tx_hash # make sure it's set assert isinstance(earn_result.error, expected_errors[idx]) assert account_req.account_id.value == sender.public_key.stellar_address expected_memo = memo.HashMemo(AgoraMemo.new(1, TransactionType.EARN, 1, b'').val) self._assert_earn_batch_envelope(submit_req.envelope_xdr, [sender], sender, 100, 11, expected_memo, sender, earns) assert len(submit_req.invoice_list.invoices) == 0
def test_from_result_tx_failed(self, tx_result_code: int, op_type: int, op_result_code: int, op_error_type: type): """ Tests conversion of error types with transaction results containing only one operation result. """ if op_type == xdr_const.CREATE_ACCOUNT: op_result = gen_create_op_result(op_result_code) elif op_type == xdr_const.PAYMENT: op_result = gen_payment_op_result(op_result_code) else: raise ValueError('invalid op_type') result_xdr = gen_result_xdr(tx_result_code, [op_result] if op_result else []) te = TransactionErrors.from_result(result_xdr) assert isinstance(te.tx_error, Error) assert isinstance(te.op_errors[0], op_error_type)
def test_submit_payment_with_memo(self, grpc_channel, executor, app_index_client): sender = PrivateKey.random() dest = PrivateKey.random().public_key payment = Payment(sender, dest, TransactionType.EARN, 100000, memo='somememo') future = executor.submit(app_index_client.submit_payment, payment) account_req = self._set_successful_get_account_info_response(grpc_channel, sender, 10) result_xdr = gen_result_xdr(xdr_const.txSUCCESS, [gen_payment_op_result(xdr_const.PAYMENT_SUCCESS)]) submit_req = self._set_successful_submit_transaction_response(grpc_channel, b'somehash', result_xdr) assert future.result() == b'somehash' assert account_req.account_id.value == sender.public_key.stellar_address expected_memo = memo.TextMemo('somememo') self._assert_payment_envelope(submit_req.envelope_xdr, [sender], sender, 100, 11, expected_memo, payment) assert len(submit_req.invoice_list.invoices) == 0
def test_from_proto_stellar_text_memo(self): op_result = gen_payment_op_result(xdr_const.PAYMENT_UNDERFUNDED) result_xdr = gen_result_xdr(xdr_const.txFAILED, [op_result]) tx_src = gen_account_id() dest = gen_account_id() operations = [gen_payment_op(dest, amount=20)] envelope_xdr = gen_tx_envelope_xdr(tx_src, 1, operations, gen_text_memo(b'somememo')) history_item = tx_pb.HistoryItem( transaction_id=model_pb.TransactionId(value=b'somehash'), cursor=tx_pb.Cursor(value=b'cursor1'), stellar_transaction=model_pb.StellarTransaction( result_xdr=result_xdr, envelope_xdr=envelope_xdr, ), payments=[ tx_pb.HistoryItem.Payment( source=model_pb.SolanaAccountId(value=tx_src.ed25519), destination=model_pb.SolanaAccountId(value=dest.ed25519), amount=20, ), ], ) data = TransactionData.from_proto( history_item, tx_pb.GetTransactionResponse.State.SUCCESS) assert data.tx_id == b'somehash' assert data.transaction_state == TransactionState.SUCCESS assert len(data.payments) == 1 payment = data.payments[0] assert payment.sender.raw == tx_src.ed25519 assert payment.destination.raw == dest.ed25519 assert payment.tx_type == TransactionType.UNKNOWN assert payment.quarks == 20 assert not payment.invoice assert payment.memo == 'somememo'
def test_submit_payment_with_invoice(self, grpc_channel, executor, app_index_client): sender = PrivateKey.random() dest = PrivateKey.random().public_key invoice = Invoice([LineItem('title1', 100000, 'description1', b'somesku')]) payment = Payment(sender, dest, TransactionType.EARN, 100000, invoice=invoice) future = executor.submit(app_index_client.submit_payment, payment) account_req = self._set_successful_get_account_info_response(grpc_channel, sender, 10) result_xdr = gen_result_xdr(xdr_const.txSUCCESS, [gen_payment_op_result(xdr_const.PAYMENT_SUCCESS)]) submit_req = self._set_successful_submit_transaction_response(grpc_channel, b'somehash', result_xdr) assert future.result() == b'somehash' assert account_req.account_id.value == sender.public_key.stellar_address expected_memo = memo.HashMemo( AgoraMemo.new(1, TransactionType.EARN, 1, InvoiceList([invoice]).get_sha_224_hash()).val) self._assert_payment_envelope(submit_req.envelope_xdr, [sender], sender, 100, 11, expected_memo, payment) assert len(submit_req.invoice_list.invoices) == 1 assert submit_req.invoice_list.invoices[0].SerializeToString() == invoice.to_proto().SerializeToString()
def test_submit_earn_batch_same_dest(self, grpc_channel, executor, app_index_client): sender = PrivateKey.random() dest = PrivateKey.random().public_key all_earns = [Earn(dest, i) for i in range(5)] future = executor.submit(app_index_client.submit_earn_batch, sender, all_earns) result_xdr = gen_result_xdr(xdr_const.txSUCCESS, [gen_payment_op_result(xdr_const.PAYMENT_SUCCESS)]) account_req = self._set_successful_get_account_info_response(grpc_channel, sender, 10) tx_hash = 'somehash'.encode() submit_req = self._set_successful_submit_transaction_response(grpc_channel, tx_hash, result_xdr) batch_earn_result = future.result() assert len(batch_earn_result.succeeded) == 5 assert len(batch_earn_result.failed) == 0 assert account_req.account_id.value == sender.public_key.stellar_address expected_memo = memo.HashMemo(AgoraMemo.new(1, TransactionType.EARN, 1, b'').val) self._assert_earn_batch_envelope(submit_req.envelope_xdr, [sender], sender, 100, 11, expected_memo, sender, all_earns) assert len(submit_req.invoice_list.invoices) == 0