def test_get_transaction(self, grpc_channel, executor, no_retry_client): source, dest = [key.public_key for key in generate_keys(2)] transaction_id = b'someid' future = executor.submit(no_retry_client.get_transaction, transaction_id) agora_memo = AgoraMemo.new(1, TransactionType.SPEND, 0, b'') tx = Transaction.new(PrivateKey.random().public_key, [ memo.memo_instruction( base64.b64encode(agora_memo.val).decode('utf-8')), token.transfer(source, dest, PrivateKey.random().public_key, 100), ]) resp = tx_pb_v4.GetTransactionResponse( state=tx_pb_v4.GetTransactionResponse.State.SUCCESS, item=tx_pb_v4.HistoryItem( transaction_id=model_pb_v4.TransactionId( value=transaction_id, ), solana_transaction=model_pb_v4.Transaction( value=tx.marshal(), ), payments=[ tx_pb_v4.HistoryItem.Payment( source=model_pb_v4.SolanaAccountId(value=source.raw), destination=model_pb_v4.SolanaAccountId( value=dest.raw), amount=100, ) ], invoice_list=model_pb_v3.InvoiceList(invoices=[ model_pb_v3.Invoice(items=[ model_pb_v3.Invoice.LineItem(title='t1', amount=15), ]), ])), ) req = self._set_get_transaction_resp(grpc_channel, resp) assert req.transaction_id.value == transaction_id tx_data = future.result() assert tx_data.tx_id == transaction_id assert tx_data.transaction_state == TransactionState.SUCCESS assert len(tx_data.payments) == 1 assert not tx_data.error p = tx_data.payments[0] assert p.sender.raw == source.raw assert p.destination.raw == dest.raw assert p.tx_type == TransactionType.SPEND assert p.quarks == 100 assert p.invoice.to_proto().SerializeToString( ) == resp.item.invoice_list.invoices[0].SerializeToString() assert not p.memo
def gen_account_id() -> xdr_type.AccountID: private_key = PrivateKey.random() return xdr_type.AccountID( type=xdr_const.PUBLIC_KEY_TYPE_ED25519, ed25519=private_key.public_key.raw, )
def test_create_program_address_invalid(self, mocker): invalid_key = PrivateKey.random().public_key.raw mock_hashlib = mocker.patch('agora.solana.address.hashlib') mock_hashlib.sha256.return_value.digest.return_value = invalid_key with pytest.raises(InvalidPublicKeyError): create_program_address(_PROGRAM_ID, ['Lil\''.encode(), 'Bits'.encode()])
def test_sign(self): resp = SignTransactionResponse(_generate_envelope()) private_key = PrivateKey.random() resp.sign(private_key) # kp.verify throws an error if the signature doesn't match private_key.public_key.verify(resp.envelope.hash_meta(), resp.envelope.signatures[-1].signature)
def test_random(self): priv = PrivateKey.random() kp = Keypair.from_seed(priv.stellar_seed) assert priv.public_key.stellar_address == kp.address().decode() assert priv.public_key.raw == kp.raw_public_key() assert priv.stellar_seed == kp.seed().decode() assert priv.raw == kp.raw_seed()
def test_kin_keypair_compat(self): kp = Keypair.random() pub = PublicKey(kp.raw_public_key()) assert pub.stellar_address == kp.address().decode() assert pub.raw == kp.raw_public_key() priv = PrivateKey(kp.raw_seed()) assert priv.stellar_seed == kp.seed().decode() assert priv.raw == kp.raw_seed()
def test_get_account_info_not_found(self, grpc_channel, executor, no_retry_client): private_key = PrivateKey.random() future = executor.submit(no_retry_client.get_solana_account_info, private_key.public_key) resp = account_pb_v4.GetAccountInfoResponse( result=account_pb_v4.GetAccountInfoResponse.Result.NOT_FOUND) req = self._set_get_account_info_resp(grpc_channel, resp) assert req.account_id.value == private_key.public_key.raw with pytest.raises(AccountNotFoundError): future.result()
def test_from_string(self): address = "GCABWU4FHL3RGOIWCX5TOVLIAMLEU2YXXLCMHVXLDOFHKLNLGCSBRJYP" seed = "SCZ4KGTCMAFIJQCCJDMMKDFUB7NYV56VBNEU7BKMR4PQFUETJCWLV6GN" pub = PublicKey.from_string(address) assert pub.stellar_address == address priv = PrivateKey.from_string(seed) assert priv.stellar_seed == seed # Test invalid cases with pytest.raises(ValueError): PublicKey.from_string('invalidlength') with pytest.raises(ValueError): PublicKey.from_string(seed) # not an address with pytest.raises(ValueError): PrivateKey.from_string('invalidlength') with pytest.raises(ValueError): PrivateKey.from_string(address) # not a seed
def _generate_create( subsidizer: PublicKey, wallet: PublicKey, mint: PublicKey ) -> Tuple[List[solana.Instruction], PublicKey]: addr = token.get_associated_account(wallet, mint) pub = PrivateKey.random().public_key instructions = [ system.create_account(subsidizer, addr, token.PROGRAM_KEY, 10, token.ACCOUNT_SIZE), token.initialize_account(addr, mint, pub), token.set_authority(addr, pub, token.AuthorityType.CLOSE_ACCOUNT, subsidizer), token.set_authority(addr, pub, token.AuthorityType.ACCOUNT_HOLDER, wallet) ] return instructions, addr
def test_request_airdrop(self, grpc_channel, executor, no_retry_client): public_key = PrivateKey.random().public_key future = executor.submit(no_retry_client.request_airdrop, public_key, 100) tx_sig = b'somesig' resp = airdrop_pb_v4.RequestAirdropResponse( result=airdrop_pb_v4.RequestAirdropResponse.Result.OK, signature=model_pb_v4.TransactionSignature(value=tx_sig)) req = self._set_request_airdrop_resp(grpc_channel, resp) assert req.account_id.value == public_key.raw assert req.quarks == 100 assert future.result() == tx_sig
def test_request_airdrop_not_found(self, grpc_channel, executor, no_retry_client): public_key = PrivateKey.random().public_key future = executor.submit(no_retry_client.request_airdrop, public_key, 100) resp = airdrop_pb_v4.RequestAirdropResponse( result=airdrop_pb_v4.RequestAirdropResponse.Result.NOT_FOUND) req = self._set_request_airdrop_resp(grpc_channel, resp) assert req.account_id.value == public_key.raw assert req.quarks == 100 with pytest.raises(AccountNotFoundError): future.result()
def _gen_create_tx(): private_key = PrivateKey.random() create_instruction, addr = token.create_associated_token_account( _subsidizer, private_key.public_key, _token) return solana.Transaction.new(_subsidizer, [ create_instruction, token.set_authority( addr, private_key.public_key, token.AuthorityType.CLOSE_ACCOUNT, new_authority=_subsidizer, ) ])
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_request_airdrop_insufficient_kin(self, grpc_channel, executor, no_retry_client): public_key = PrivateKey.random().public_key future = executor.submit(no_retry_client.request_airdrop, public_key, 100) resp = airdrop_pb_v4.RequestAirdropResponse( result=airdrop_pb_v4.RequestAirdropResponse.Result.INSUFFICIENT_KIN ) req = self._set_request_airdrop_resp(grpc_channel, resp) assert req.account_id.value == public_key.raw assert req.quarks == 100 with pytest.raises(InsufficientBalanceError): future.result()
def test_no_account_retry(self, grpc_channel, executor): resolver = TokenAccountResolver( account_stub=account_pb_grpc.AccountStub(grpc_channel), retry_strategies=[LimitStrategy(3)]) owner = PrivateKey.random() future = executor.submit(resolver.resolve_token_accounts, owner) for _ in range(3): md, request, rpc = grpc_channel.take_unary_unary( account_pb.DESCRIPTOR.services_by_name['Account']. methods_by_name['ResolveTokenAccounts']) rpc.terminate(account_pb.ResolveTokenAccountsResponse(), (), grpc.StatusCode.OK, '') assert future.result() == []
def test_get_account_info(self, grpc_channel, executor, no_retry_client): private_key = PrivateKey.random() future = executor.submit(no_retry_client.get_solana_account_info, private_key.public_key) resp = account_pb_v4.GetAccountInfoResponse( account_info=account_pb_v4.AccountInfo( account_id=model_pb_v4.SolanaAccountId( value=private_key.public_key.raw), balance=10, )) req = self._set_get_account_info_resp(grpc_channel, resp) assert req.account_id.value == private_key.public_key.raw account_info = future.result() assert account_info.account_id == private_key.public_key assert account_info.balance == 10
def test_create_account_errors(self, grpc_channel, executor, no_retry_client, result, error_type): private_key = PrivateKey.random() no_retry_client._response_cache.clear_all() future = executor.submit(no_retry_client.create_solana_account, private_key) self._set_get_service_config_resp(grpc_channel) self._set_get_recent_blockhash_resp(grpc_channel) self._set_get_min_balance_response(grpc_channel) resp = account_pb_v4.CreateAccountResponse(result=result) req = self._set_create_account_resp(grpc_channel, resp) tx = Transaction.unmarshal(req.transaction.value) assert len(tx.signatures) == 2 assert tx.signatures[0] == bytes(SIGNATURE_LENGTH) assert private_key.public_key.verify(tx.message.marshal(), tx.signatures[1]) sys_create = decompile_create_account(tx.message, 0) assert sys_create.funder == _subsidizer assert sys_create.address == private_key.public_key assert sys_create.owner == _token_program assert sys_create.lamports == _min_balance assert sys_create.size == token.ACCOUNT_SIZE token_init = decompile_initialize_account(tx.message, 1, _token_program) assert token_init.account == private_key.public_key assert token_init.mint == _token assert token_init.owner == private_key.public_key token_set_auth = decompile_set_authority(tx.message, 2, _token_program) assert token_set_auth.account == private_key.public_key assert token_set_auth.current_authority == private_key.public_key assert token_set_auth.authority_type == token.AuthorityType.CloseAccount assert token_set_auth.new_authority == _subsidizer with pytest.raises(error_type): future.result()
def test_transaction_cross_impl(self): pk = PrivateKey(bytes([48, 83, 2, 1, 1, 48, 5, 6, 3, 43, 101, 112, 4, 34, 4, 32, 255, 101, 36, 24, 124, 23, 167, 21, 132, 204, 155, 5, 185, 58, 121, 75])) program_id = PublicKey(bytes([2, 2, 2, 4, 5, 6, 7, 8, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 8, 7, 6, 5, 4, 2, 2, 2])) to = PublicKey(bytes([1, 1, 1, 4, 5, 6, 7, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 7, 6, 5, 4, 1, 1, 1])) tx = Transaction.new( pk.public_key, [ Instruction( program_id, bytes([1, 2, 3]), [AccountMeta.new(pk.public_key, True), AccountMeta.new(to, False)], ), ], ) tx.sign([pk]) generated = base64.b64decode(_RUST_GENERATED_ADJUSTED) assert tx.marshal() == generated assert Transaction.unmarshal(generated) == tx
from agora.utils import kin_to_quarks ap = argparse.ArgumentParser() ap.add_argument('-s', '--sender', required=True, help='The private seed of the sender account') ap.add_argument('-d', '--destination', required=True, help='The public address of the destination account') args = vars(ap.parse_args()) client = Client(Environment.TEST, 1) # 1 is the test app index source = PrivateKey.from_base58(args['sender']) dest = PublicKey.from_base58(args['destination']) # Send a payment of 1 Kin payment = Payment(source, dest, TransactionType.EARN, kin_to_quarks('1')) try: tx_id = client.submit_payment(p) print( f'transaction successfully submitted with hash: {base58.b58encode(tx_id)}' ) except Error as e: print(f'transaction failed: {repr(e)}') if isinstance(e, TransactionErrors): print( f'tx_error={repr(e.tx_error)}, len(op_errors)={len(e.op_errors)}') for op_error in e.op_errors:
import base64 from typing import Optional, Tuple import pytest from agoraapi.common.v3 import model_pb2 from agora import solana from agora.error import InvoiceErrorReason from agora.keys import PrivateKey from agora.model import AgoraMemo, TransactionType from agora.model.invoice import Invoice, InvoiceList from agora.webhook.sign_transaction import SignTransactionRequest, SignTransactionResponse from tests.utils import generate_keys _SIGNING_KEY = PrivateKey.random() class TestSignTransactionRequest: def test_from_json_kin_4(self): tx, il = _generate_tx(True) data = { 'solana_transaction': base64.b64encode(tx.marshal()), 'invoice_list': base64.b64encode(il.SerializeToString()), } req = SignTransactionRequest.from_json(data) assert len(req.payments) == 1 assert req.payments[0].invoice == Invoice.from_proto(il.invoices[0]) assert req.transaction == tx
ap.add_argument('-s', '--sender', required=True, help='The private seed of the sender account') ap.add_argument( '-d', '--destinations', required=True, help= 'A comma-delimited list of account public addresses to send earns to (e.g. add1,addr2,add3' ) args = vars(ap.parse_args()) client = Client(Environment.TEST, 1) # 1 is the test app index source = PrivateKey.from_string(args['sender']) destinations = [ PublicKey.from_string(addr) for addr in args['destinations'].split(',') ] # Send an earn batch with 1 Kin each earns = [ Earn(dest, kin_to_quarks('1')) for idx, dest in enumerate(destinations) ] batch_result = client.submit_earn_batch(source, earns) print( f'{len(batch_result.succeeded)} succeeded, {len(batch_result.failed)} failed' ) for result in batch_result.succeeded: print( f'Sent 1 kin to {result.earn.destination.stellar_address} in transaction {result.tx_id.hex()}'
import argparse from agora.client import Client, RetryConfig, Environment from agora.error import AccountExistsError from agora.keys import PrivateKey ap = argparse.ArgumentParser() ap.add_argument('-s', '--seed', required=True, help='The private seed of the account to create') args = vars(ap.parse_args()) client = Client(Environment.TEST, 1) # 1 is the test app index private_key = PrivateKey.from_string(args['seed']) print( f'creating account with address {private_key.public_key.stellar_address}') try: client.create_account(private_key) print('account created') except AccountExistsError: print(f'account {private_key.public_key.stellar_address} already exists') client.close()
from agora.keys import PrivateKey from agora.solana.token import Command, initialize_account, decompile_initialize_account, transfer, decompile_transfer from agora.solana.token.program import set_authority, AuthorityType, decompile_set_authority from agora.solana.transaction import Transaction from tests.utils import generate_keys _token_program = PrivateKey.random().public_key class TestTokenProgram: def test_initialize_account(self): public_keys = [key.public_key for key in generate_keys(3)] instruction = initialize_account(public_keys[0], public_keys[1], public_keys[2], _token_program) assert instruction.data == bytes([Command.INITIALIZE_ACCOUNT]) assert instruction.accounts[0].is_signer assert instruction.accounts[0].is_writable for i in range(1, 4): assert not instruction.accounts[i].is_signer assert not instruction.accounts[i].is_writable tx = Transaction.unmarshal(Transaction.new(public_keys[0], [instruction]).marshal()) decompiled = decompile_initialize_account(tx.message, 0, _token_program) assert decompiled.account == public_keys[0] assert decompiled.mint == public_keys[1] assert decompiled.owner == public_keys[2] def test_transfer(self): public_keys = [key.public_key for key in generate_keys(3)] instruction = transfer(public_keys[0], public_keys[1], public_keys[2], 123456789, _token_program)
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
def test_resolve_token_accounts(self, grpc_channel, executor, no_retry_client): owner = PrivateKey.random().public_key close_authority = PrivateKey.random().public_key token_accounts = [priv.public_key for priv in generate_keys(2)] # account info not requested, only IDs available future = executor.submit(no_retry_client.resolve_token_accounts, owner, False) resp = account_pb_v4.ResolveTokenAccountsResponse(token_accounts=[ model_pb_v4.SolanaAccountId(value=token_account.raw) for token_account in token_accounts ]) req = self._set_resolve_token_accounts_resp(grpc_channel, resp) assert req.account_id.value == owner.raw assert not req.include_account_info token_account_infos = future.result() assert len(token_account_infos) == 2 for idx, token_account in enumerate(token_accounts): account_info = token_account_infos[idx] assert account_info.account_id == token_account assert not account_info.balance assert not account_info.owner assert not account_info.close_authority # account info not requested, account infos available future = executor.submit(no_retry_client.resolve_token_accounts, owner, False) resp = account_pb_v4.ResolveTokenAccountsResponse( token_account_infos=[ account_pb_v4.AccountInfo( account_id=model_pb_v4.SolanaAccountId( value=token_account.raw), ) for token_account in token_accounts ], token_accounts=[ model_pb_v4.SolanaAccountId(value=token_account.raw) for token_account in token_accounts ]) req = self._set_resolve_token_accounts_resp(grpc_channel, resp) assert req.account_id.value == owner.raw assert not req.include_account_info token_account_infos = future.result() assert len(token_account_infos) == 2 for idx, token_account in enumerate(token_accounts): account_info = token_account_infos[idx] assert account_info.account_id == token_account assert not account_info.balance assert not account_info.owner assert not account_info.close_authority # account info requested future = executor.submit(no_retry_client.resolve_token_accounts, owner, True) resp = account_pb_v4.ResolveTokenAccountsResponse(token_account_infos=[ account_pb_v4.AccountInfo( account_id=model_pb_v4.SolanaAccountId( value=token_account.raw), balance=10 + idx, owner=model_pb_v4.SolanaAccountId(value=owner.raw, ), close_authority=model_pb_v4.SolanaAccountId( value=close_authority.raw)) for idx, token_account in enumerate(token_accounts) ], ) req = self._set_resolve_token_accounts_resp(grpc_channel, resp) assert req.account_id.value == owner.raw assert req.include_account_info token_account_infos = future.result() assert len(token_account_infos) == 2 for idx, token_account in enumerate(token_accounts): account_info = token_account_infos[idx] assert account_info.account_id == token_account assert account_info.balance == 10 + idx assert account_info.owner == owner assert account_info.close_authority == close_authority # account info requested but not available future = executor.submit(no_retry_client.resolve_token_accounts, owner, True) resp = account_pb_v4.ResolveTokenAccountsResponse(token_accounts=[ model_pb_v4.SolanaAccountId(value=token_account.raw) for token_account in token_accounts ], ) req = self._set_resolve_token_accounts_resp(grpc_channel, resp) assert req.account_id.value == owner.raw assert req.include_account_info with pytest.raises(Error) as e: future.result() assert 'account info' in str(e)
import json import token from typing import List from agora import solana from agora.client import Environment from agora.error import WebhookRequestError, InvoiceErrorReason from agora.keys import PrivateKey from agora.solana import token from agora.webhook.create_account import CreateAccountRequest, CreateAccountResponse from agora.webhook.events import Event from agora.webhook.handler import WebhookHandler from agora.webhook.sign_transaction import SignTransactionRequest, SignTransactionResponse from tests.utils import generate_keys _TEST_PRIVATE_KEY = PrivateKey.random() class TestWebhookHandler: def test_is_valid_signature(self): secret = 'secret' handler = WebhookHandler(Environment.TEST, secret=secret) req_body = 'somebody' sig = base64.b64encode( hmac.new(secret.encode(), req_body.encode(), hashlib.sha256).digest()) assert handler.is_valid_signature(req_body, sig) other_sig = base64.b64encode(
from flask import Flask, request from agora.client import Environment from agora.error import InvoiceErrorReason from agora.keys import PrivateKey from agora.webhook.events import Event from agora.webhook.handler import WebhookHandler, AGORA_HMAC_HEADER, APP_USER_ID_HEADER, APP_USER_PASSKEY_HEADER from agora.webhook.sign_transaction import SignTransactionRequest, SignTransactionResponse logging.basicConfig(level=logging.DEBUG) app = Flask(__name__) webhook_secret = os.environ.get("WEBHOOK_SECRET") webhook_seed = os.environ.get("WEBHOOK_SEED") webhook_private_key = PrivateKey.from_string(webhook_seed) webhook_handler = WebhookHandler(Environment.TEST, webhook_secret) @app.route('/events', methods=['POST']) def events(): status_code, body = webhook_handler.handle_events( _handle_events, request.headers.get(AGORA_HMAC_HEADER), request.data.decode('utf-8'), ) return body, status_code @app.route('/sign_transaction', methods=["POST"])
def test_create_account_no_service_subsidizer(self, grpc_channel, executor, no_retry_client): private_key = PrivateKey.random() no_retry_client._response_cache.clear_all() future = executor.submit(no_retry_client.create_solana_account, private_key) md, request, rpc = grpc_channel.take_unary_unary( tx_pb_v4.DESCRIPTOR.services_by_name['Transaction']. methods_by_name['GetServiceConfig']) rpc.terminate( tx_pb_v4.GetServiceConfigResponse( token=model_pb_v4.SolanaAccountId(value=_token.raw), token_program=model_pb_v4.SolanaAccountId( value=_token_program.raw), ), (), grpc.StatusCode.OK, '') TestInternalClientV4._assert_metadata(md) with pytest.raises(NoSubsidizerError): future.result() subsidizer = PrivateKey.random() future = executor.submit(no_retry_client.create_solana_account, private_key, subsidizer=subsidizer) self._set_get_recent_blockhash_resp(grpc_channel) self._set_get_min_balance_response(grpc_channel) req = self._set_create_account_resp( grpc_channel, account_pb_v4.CreateAccountResponse()) tx = Transaction.unmarshal(req.transaction.value) assert len(tx.signatures) == 2 assert subsidizer.public_key.verify(tx.message.marshal(), tx.signatures[0]) assert private_key.public_key.verify(tx.message.marshal(), tx.signatures[1]) sys_create = decompile_create_account(tx.message, 0) assert sys_create.funder == subsidizer.public_key assert sys_create.address == private_key.public_key assert sys_create.owner == _token_program assert sys_create.lamports == _min_balance assert sys_create.size == token.ACCOUNT_SIZE token_init = decompile_initialize_account(tx.message, 1, _token_program) assert token_init.account == private_key.public_key assert token_init.mint == _token assert token_init.owner == private_key.public_key token_set_auth = decompile_set_authority(tx.message, 2, _token_program) assert token_set_auth.account == private_key.public_key assert token_set_auth.current_authority == private_key.public_key assert token_set_auth.authority_type == token.AuthorityType.CloseAccount assert token_set_auth.new_authority == subsidizer.public_key assert not future.result()
def generate_keys(amount) -> List[PrivateKey]: return [PrivateKey.random() for _ in range(amount)]
from agora.solana.system import decompile_create_account from agora.solana.token import decompile_initialize_account, transfer, decompile_set_authority from agora.solana.transaction import HASH_LENGTH, SIGNATURE_LENGTH from agora.utils import user_agent from agora.version import VERSION from tests.utils import generate_keys _recent_blockhash = bytes(HASH_LENGTH) _recent_blockhash_resp = tx_pb_v4.GetRecentBlockhashResponse( blockhash=model_pb_v4.Blockhash(value=_recent_blockhash)) _min_balance = 2039280 _min_balance_resp = tx_pb_v4.GetMinimumBalanceForRentExemptionResponse( lamports=_min_balance) _subsidizer = PrivateKey.random().public_key _token = PrivateKey.random().public_key _token_program = PrivateKey.random().public_key _service_config_resp = tx_pb_v4.GetServiceConfigResponse( subsidizer_account=model_pb_v4.SolanaAccountId(value=_subsidizer.raw), token=model_pb_v4.SolanaAccountId(value=_token.raw), token_program=model_pb_v4.SolanaAccountId(value=_token_program.raw), ) @pytest.fixture(scope='class') def grpc_channel(): return grpc_testing.channel([ account_pb_v4.DESCRIPTOR.services_by_name['Account'], airdrop_pb_v4.DESCRIPTOR.services_by_name['Airdrop'], tx_pb_v4.DESCRIPTOR.services_by_name['Transaction'],