def test_from_json(self): memo = AgoraMemo.new(1, TransactionType.P2P, 0, b'somefk') keys = [key.public_key for key in generate_keys(4)] token_program = keys[3] tx = solana.Transaction.new(keys[0], [ solana.memo_instruction( base64.b64encode(memo.val).decode('utf-8')), solana.transfer( keys[1], keys[2], keys[3], 20, token_program, ), ]) data = { 'transaction': base64.b64encode(tx.marshal()).decode('utf-8'), 'transaction_error': 'unauthorized', 'transaction_error_raw': 'raw_error' } solana_event = SolanaEvent.from_json(data) assert solana_event.transaction == tx assert isinstance(solana_event.tx_error, InvalidSignatureError) assert solana_event.tx_error_raw == 'raw_error'
def _generate_tx(with_il: Optional[bool] = False) -> Tuple[solana.Transaction, Optional[model_pb2.InvoiceList]]: il = None instructions = [] if with_il: il = model_pb2.InvoiceList( invoices=[ model_pb2.Invoice( items=[ model_pb2.Invoice.LineItem(title='title1', description='desc1', amount=50, sku=b'somesku') ] ) ] ) fk = InvoiceList.from_proto(il).get_sha_224_hash() memo = AgoraMemo.new(1, TransactionType.P2P, 0, fk) instructions.append(solana.memo_instruction(base64.b64encode(memo.val).decode('utf-8'))) keys = [key.public_key for key in generate_keys(3)] instructions.append(solana.transfer( keys[0], keys[1], keys[2], 20, ), ) return solana.Transaction.new( _SIGNING_KEY.public_key, instructions ), il
def test_payments_from_transaction_with_invoice_list(self): 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) keys = [key.public_key for key in generate_keys(5)] token_program = keys[4] tx = solana.Transaction.new( keys[0], [ solana.memo_instruction(base64.b64encode(memo.val).decode('utf-8')), solana.transfer( keys[1], keys[2], keys[3], 20, token_program, ), solana.transfer( keys[2], keys[3], keys[1], 40, token_program, ), ] ) payments = ReadOnlyPayment.payments_from_transaction(tx, il) assert len(payments) == 2 assert payments[0].sender == keys[1] assert payments[0].destination == keys[2] assert payments[0].tx_type == TransactionType.P2P assert payments[0].quarks == 20 assert payments[0].invoice == Invoice.from_proto(il.invoices[0]) assert not payments[0].memo assert payments[1].sender == keys[2] assert payments[1].destination == keys[3] assert payments[1].tx_type == TransactionType.P2P assert payments[1].quarks == 40 assert payments[1].invoice == Invoice.from_proto(il.invoices[1]) assert not payments[1].memo
def _submit_solana_earn_batch_tx( self, batch: EarnBatch, service_config: tx_pb.GetServiceConfigResponse, commitment: Commitment, transfer_sender: Optional[PublicKey] = None, ) -> SubmitTransactionResult: token_program = PublicKey(service_config.token_program.value) subsidizer_id = (batch.subsidizer.public_key if batch.subsidizer else PublicKey(service_config.subsidizer_account.value)) transfer_sender = transfer_sender if transfer_sender else batch.sender.public_key instructions = [ transfer(transfer_sender, earn.destination, batch.sender.public_key, earn.quarks, token_program) for earn in batch.earns ] invoices = [earn.invoice for earn in batch.earns if earn.invoice] invoice_list = InvoiceList(invoices) if invoices else None if batch.memo: instructions = [memo_instruction(batch.memo)] + instructions elif self.app_index > 0: fk = invoice_list.get_sha_224_hash() if invoice_list else b'' agora_memo = AgoraMemo.new(1, TransactionType.EARN, self.app_index, fk) instructions = [ memo_instruction( base64.b64encode(agora_memo.val).decode('utf-8')) ] + instructions tx = solana.Transaction.new(subsidizer_id, instructions) if batch.subsidizer: signers = [batch.subsidizer, batch.sender] else: signers = [batch.sender] return self._sign_and_submit_solana_tx(signers, tx, commitment, invoice_list=invoice_list)
def test_from_json_full_kin_4(self): memo = AgoraMemo.new(1, TransactionType.P2P, 0, b'somefk') keys = [key.public_key for key in generate_keys(4)] token_program = keys[3] tx = solana.Transaction.new(keys[0], [ solana.memo_instruction( base64.b64encode(memo.val).decode('utf-8')), solana.transfer( keys[1], keys[2], keys[3], 20, token_program, ), ]) il = model_pb2.InvoiceList(invoices=[ model_pb2.Invoice(items=[ model_pb2.Invoice.LineItem(title='title1', description='desc1', amount=50, sku=b'somesku') ]) ]) data = { 'kin_version': 4, 'tx_id': base64.b64encode(b'txsig'), 'invoice_list': il.SerializeToString(), 'solana_event': { 'transaction': base64.b64encode(tx.marshal()).decode('utf-8'), 'transaction_error': 'bad_nonce', 'transaction_error_raw': 'raw_error', } } event = TransactionEvent.from_json(data) assert event.kin_version == 4 assert event.tx_id == b'txsig' assert len(event.invoice_list.invoices) == 1 assert len(event.invoice_list.invoices[0].items) == 1 line_item = event.invoice_list.invoices[0].items[0] assert line_item.title == 'title1' assert line_item.description == 'desc1' assert line_item.amount == 50 assert line_item.sku == b'somesku' assert not event.stellar_event assert event.solana_event.transaction == tx assert isinstance(event.solana_event.tx_error, BadNonceError) assert event.solana_event.tx_error_raw == 'raw_error'
def _submit_solana_payment_tx( self, payment: Payment, service_config: tx_pb.GetServiceConfigResponse, commitment: Commitment, transfer_sender: Optional[PublicKey] = None ) -> SubmitTransactionResult: token_program = PublicKey(service_config.token_program.value) subsidizer_id = (payment.subsidizer.public_key if payment.subsidizer else PublicKey( service_config.subsidizer_account.value)) instructions = [] invoice_list = None if payment.memo: instructions = [memo_instruction(payment.memo)] elif self.app_index > 0: if payment.invoice: invoice_list = InvoiceList(invoices=[payment.invoice]) fk = invoice_list.get_sha_224_hash() if payment.invoice else b'' memo = AgoraMemo.new(1, payment.tx_type, self.app_index, fk) instructions = [ memo_instruction(base64.b64encode(memo.val).decode('utf-8')) ] sender = transfer_sender if transfer_sender else payment.sender.public_key instructions.append( transfer(sender, payment.destination, payment.sender.public_key, payment.quarks, token_program)) tx = solana.Transaction.new(subsidizer_id, instructions) if payment.subsidizer: signers = [payment.subsidizer, payment.sender] else: signers = [payment.sender] return self._sign_and_submit_solana_tx(signers, tx, commitment, invoice_list)
def test_from_json_kin_4(self): il = model_pb2.InvoiceList( invoices=[ model_pb2.Invoice( items=[ model_pb2.Invoice.LineItem(title='title1', description='desc1', amount=50, sku=b'somesku') ] ) ] ) fk = InvoiceList.from_proto(il).get_sha_224_hash() memo = AgoraMemo.new(1, TransactionType.P2P, 0, fk) keys = [key.public_key for key in generate_keys(4)] token_program = keys[3] tx = solana.Transaction.new( keys[0], [ solana.memo_instruction(base64.b64encode(memo.val).decode('utf-8')), solana.transfer( keys[1], keys[2], keys[3], 20, token_program, ), ] ) data = { 'kin_version': 4, 'solana_transaction': base64.b64encode(tx.marshal()), 'invoice_list': base64.b64encode(il.SerializeToString()), } req = SignTransactionRequest.from_json(data, Environment.TEST) assert len(req.payments) == 1 assert req.payments[0].invoice == Invoice.from_proto(il.invoices[0]) assert req.kin_version == data['kin_version'] assert req.transaction == tx
def test_payments_from_transaction(self): keys = [key.public_key for key in generate_keys(5)] token_program = keys[4] tx = solana.Transaction.new( keys[0], [ solana.memo_instruction('somememo'), solana.transfer( keys[1], keys[2], keys[3], 20, token_program, ), solana.transfer( keys[2], keys[3], keys[1], 40, token_program, ), ] ) payments = ReadOnlyPayment.payments_from_transaction(tx) assert len(payments) == 2 assert payments[0].sender == keys[1] assert payments[0].destination == keys[2] assert payments[0].tx_type == TransactionType.UNKNOWN assert payments[0].quarks == 20 assert not payments[0].invoice assert payments[0].memo == 'somememo' assert payments[1].sender == keys[2] assert payments[1].destination == keys[3] assert payments[1].tx_type == TransactionType.UNKNOWN assert payments[1].quarks == 40 assert not payments[1].invoice assert payments[1].memo == 'somememo'
def test_payments_from_transaction_invalid(self): il = model_pb2.InvoiceList(invoices=[ model_pb2.Invoice( items=[ model_pb2.Invoice.LineItem(title='t1', amount=10), ] ), ]) fk = InvoiceList.from_proto(il).get_sha_224_hash() memo = AgoraMemo.new(1, TransactionType.P2P, 0, fk) keys = [key.public_key for key in generate_keys(5)] token_program = keys[4] tx = solana.Transaction.new( keys[0], [ solana.memo_instruction(base64.b64encode(memo.val).decode('utf-8')), solana.transfer( keys[1], keys[2], keys[3], 20, token_program, ), solana.transfer( keys[2], keys[3], keys[1], 40, token_program, ), ] ) # mismatching number of invoices and instructions with pytest.raises(ValueError): ReadOnlyPayment.payments_from_transaction(tx, il)
def test_from_proto_solana_text_memo(self): source, dest, token_program = [ key.public_key for key in generate_keys(3) ] tx = Transaction.new(PrivateKey.random().public_key, [ memo_instruction('somememo'), transfer(source, dest, PrivateKey.random().public_key, 20), ]) history_item = tx_pb.HistoryItem( transaction_id=model_pb.TransactionId(value=b'somehash'), cursor=tx_pb.Cursor(value=b'cursor1'), solana_transaction=model_pb.Transaction(value=tx.marshal(), ), payments=[ tx_pb.HistoryItem.Payment( source=model_pb.SolanaAccountId(value=source.raw), destination=model_pb.SolanaAccountId(value=dest.raw), 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 == source.raw assert payment.destination.raw == dest.raw assert payment.tx_type == TransactionType.UNKNOWN assert payment.quarks == 20 assert not payment.invoice assert payment.memo == 'somememo'
def test_from_proto_solana_agora_memo(self): acc1, acc2, token_program = [ key.public_key for key in generate_keys(3) ] il = model_pb_v3.InvoiceList(invoices=[ model_pb_v3.Invoice(items=[ model_pb_v3.Invoice.LineItem(title='t1', amount=10), ]), model_pb_v3.Invoice(items=[ model_pb_v3.Invoice.LineItem(title='t1', amount=15), ]), ]) fk = InvoiceList.from_proto(il).get_sha_224_hash() agora_memo = AgoraMemo.new(1, TransactionType.P2P, 0, fk) tx = Transaction.new(PrivateKey.random().public_key, [ memo_instruction(base64.b64encode(agora_memo.val).decode('utf-8')), transfer(acc1, acc2, PrivateKey.random().public_key, 10), transfer(acc2, acc1, PrivateKey.random().public_key, 15), ]) history_item = tx_pb.HistoryItem( transaction_id=model_pb.TransactionId(value=b'somehash'), cursor=tx_pb.Cursor(value=b'cursor1'), solana_transaction=model_pb.Transaction(value=tx.marshal(), ), payments=[ tx_pb.HistoryItem.Payment( source=model_pb.SolanaAccountId(value=acc1.raw), destination=model_pb.SolanaAccountId(value=acc2.raw), amount=10, ), tx_pb.HistoryItem.Payment( source=model_pb.SolanaAccountId(value=acc2.raw), destination=model_pb.SolanaAccountId(value=acc1.raw), amount=15, ), ], invoice_list=il, ) 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) == 2 payment1 = data.payments[0] assert payment1.sender.raw == acc1.raw assert payment1.destination.raw == acc2.raw assert payment1.tx_type == TransactionType.P2P 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.raw assert payment2.destination.raw == acc1.raw assert payment2.tx_type == TransactionType.P2P assert payment2.quarks == 15 assert (payment2.invoice.to_proto().SerializeToString() == il.invoices[1].SerializeToString()) assert not payment2.memo