Пример #1
0
    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
Пример #2
0
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,
    )
Пример #3
0
    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()])
Пример #4
0
    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)
Пример #5
0
    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()
Пример #6
0
    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()
Пример #7
0
    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()
Пример #8
0
    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
Пример #9
0
    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
Пример #10
0
    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
Пример #11
0
    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()
Пример #12
0
    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,
            )
        ])
Пример #13
0
    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'
Пример #14
0
    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()
Пример #15
0
    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() == []
Пример #16
0
    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
Пример #17
0
    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()
Пример #18
0
    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
Пример #19
0
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
Пример #21
0
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()}'
Пример #22
0
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()
Пример #23
0
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)
Пример #24
0
    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
Пример #25
0
    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)
Пример #26
0
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(
Пример #27
0
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"])
Пример #28
0
    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()
Пример #29
0
def generate_keys(amount) -> List[PrivateKey]:
    return [PrivateKey.random() for _ in range(amount)]
Пример #30
0
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'],