def test_find_program_address_ref(self, program_id, expected):
        """Test with addresses generated by rust impl
        """
        pid = PublicKey.from_base58(program_id)
        exp = PublicKey.from_base58(expected)

        actual = find_program_address(pid, ['Lil\''.encode(), 'Bits'.encode()])
        assert actual == exp
Beispiel #2
0
    def test_get_associated_account(self):
        # Values generated from taken from spl code.
        wallet = PublicKey.from_base58(
            '4uQeVj5tqViQh7yWWGStvkEG1Zmhx6uasJtWCJziofM')
        mint = PublicKey.from_base58(
            '8opHzTAnfzRpPEx21XtnrVTX28YQuCpAjcn1PczScKh')

        expected = PublicKey.from_base58(
            'H7MQwEzt97tUJryocn3qaEoy2ymWstwyEk1i9Yv3EmuZ')

        actual = get_associated_account(wallet, mint)
        assert actual == expected
Beispiel #3
0
from typing import NamedTuple

from agora.keys import PublicKey
from agora.solana.instruction import Instruction
from agora.solana.transaction import Message

# The address of the memo program that should be used.
# todo: lock this in, or make configurable
PROGRAM_KEY = PublicKey.from_base58(
    'Memo1UhkJRfHyvLMcVucJwxXeuD728EqVDDwQDxFMNo')


# Reference: https://github.com/solana-labs/solana-program-library/blob/master/memo/program/src/entrypoint.rs
def memo_instruction(data: str) -> Instruction:
    return Instruction(
        PROGRAM_KEY,
        bytes(data, 'utf-8'),
    )


class DecompiledMemo(NamedTuple):
    data: bytes


def decompile_memo(m: Message, index: int) -> DecompiledMemo:
    if index >= len(m.instructions):
        raise ValueError(f"instruction doesn't exist at {index}")

    i = m.instructions[index]

    if m.accounts[i.program_index] != PROGRAM_KEY:
Beispiel #4
0
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:
            print(f'op_error={repr(op_error)}')
Beispiel #5
0
# todo: lock in token program key and remove token_program parameters
from enum import IntEnum
from typing import NamedTuple, Optional

from agora.keys import PublicKey, ED25519_PUB_KEY_SIZE
from agora.solana.instruction import Instruction, AccountMeta
from agora.solana.transaction import Message

# Reference: https://github.com/solana-labs/solana-program-library/blob/11b1e3eefdd4e523768d63f7c70a7aa391ea0d02/token/program/src/state.rs#L125  # noqa: E501
ACCOUNT_SIZE = 165

# RentSysVar points to the system variable "Rent"
#
# Source: https://github.com/solana-labs/solana/blob/f02a78d8fff2dd7297dc6ce6eb5a68a3002f5359/sdk/src/sysvar/rent.rs#L11
_RENT_SYS_VAR = PublicKey.from_base58('SysvarRent111111111111111111111111111111111')


class Command(IntEnum):
    INITIALIZE_MINT = 0
    INITIALIZE_ACCOUNT = 1
    INITIALIZE_MULTISIG = 2
    TRANSFER = 3
    APPROVE = 4
    REVOKE = 5
    SET_AUTHORITY = 6
    MINT_TO = 7
    BURN = 8
    CLOSE_ACCOUNT = 9
    FREEZE_ACCOUNT = 10
    THAW_ACCOUNT = 11
    TRANSFER_2 = 12
Beispiel #6
0
# todo: lock in token program key and remove token_program parameters
from enum import IntEnum
from typing import NamedTuple, Optional

from agora.keys import PublicKey, ED25519_PUB_KEY_SIZE
from agora.solana import system
from agora.solana.instruction import Instruction, AccountMeta
from agora.solana.transaction import Message

# Reference: https://github.com/solana-labs/solana-program-library/blob/11b1e3eefdd4e523768d63f7c70a7aa391ea0d02/token/program/src/state.rs#L125  # noqa: E501
ACCOUNT_SIZE = 165

PROGRAM_KEY = PublicKey.from_base58(
    "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA")


class Command(IntEnum):
    INITIALIZE_MINT = 0
    INITIALIZE_ACCOUNT = 1
    INITIALIZE_MULTISIG = 2
    TRANSFER = 3
    APPROVE = 4
    REVOKE = 5
    SET_AUTHORITY = 6
    MINT_TO = 7
    BURN = 8
    CLOSE_ACCOUNT = 9
    FREEZE_ACCOUNT = 10
    THAW_ACCOUNT = 11
    TRANSFER_2 = 12
    APPROVE_2 = 13
from agora.keys import PrivateKey, PublicKey
from agora.model import Earn, Invoice, LineItem
from agora.model.earn import EarnBatch
from agora.utils import kin_to_quarks

ap = argparse.ArgumentParser()
ap.add_argument('-s', '--sender', required=True, help='The base58-encoded private seed of the sender account')
ap.add_argument('-d', '--destinations', required=True,
                help='A comma-delimited list of base58-encoded account 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_base58(args['sender'])
destinations = [PublicKey.from_base58(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(EarnBatch(source, earns))
if batch_result.tx_error:
    print(f'{batch_result.tx_id} failed with error {repr(batch_result.tx_error)}')

    if batch_result.earn_errors:
        for e in batch_result.earn_errors:
            print(f'earn {e.earn_index} failed with error {repr(e.error)}')
else:
    print(f'{batch_result.tx_id} submitted')

# Send an earn batch of earns with 1 Kin each, with invoices
earns = [Earn(dest, kin_to_quarks('1'), invoice=Invoice([LineItem(f'Payment {idx}', kin_to_quarks('1'))]))
from typing import List

import base58
import pytest

from agora.keys import PublicKey, PrivateKey
from agora.solana.address import create_program_address, MAX_SEED_LENGTH, InvalidPublicKeyError, find_program_address

_PROGRAM_ID = PublicKey.from_base58(
    'BPFLoader1111111111111111111111111111111111')
# The typo here was taken directly from the Solana test case,
# which was used to derive the expected outputs.
_PUBLIC_KEY = base58.b58decode('SeedPubey1111111111111111111111111111111111')


class TestCreateProgramAddress:
    def test_create_program_address_max_seed_length(self):
        max_seed = bytes(MAX_SEED_LENGTH)
        exceeded_seed = bytes(MAX_SEED_LENGTH + 1)

        with pytest.raises(ValueError):
            create_program_address(_PROGRAM_ID, [exceeded_seed])

        with pytest.raises(ValueError):
            create_program_address(_PROGRAM_ID,
                                   ['short seed'.encode(), exceeded_seed])

        assert create_program_address(_PROGRAM_ID, [max_seed])

    @pytest.mark.parametrize('expected, seeds', [
        ('3gF2KMe9KiC6FNVBmfg9i267aMPvK37FewCip4eGBFcT', [bytes(),
Beispiel #9
0
from typing import NamedTuple, Tuple

from agora.keys import PublicKey
from agora.solana import system
from agora.solana.address import find_program_address
from agora.solana.instruction import Instruction, AccountMeta
from agora.solana.transaction import Message
from .program import PROGRAM_KEY

ASSOCIATED_TOKEN_ACCOUNT_PROGRAM_KEY = PublicKey.from_base58(
    'ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL')


def get_associated_account(wallet: PublicKey, mint: PublicKey) -> PublicKey:
    return find_program_address(
        ASSOCIATED_TOKEN_ACCOUNT_PROGRAM_KEY,
        [
            wallet.raw,
            PROGRAM_KEY.raw,
            mint.raw,
        ],
    )


def create_associated_token_account(
    subsidizer: PublicKey,
    wallet: PublicKey,
    mint: PublicKey,
) -> Tuple[Instruction, PublicKey]:
    addr = get_associated_account(wallet, mint)
    return Instruction(
Beispiel #10
0
try:
    client.create_account(sender)
    print('account created')
except AccountExistsError:
    print(f'account {sender_addr} already exists')

print(f'balance: {client.get_balance(sender.public_key)}')

print(f'requesting airdrop for {sender_addr}')
airdrop_resp = client._internal_client.request_airdrop(sender.public_key, int(3e5))

print(f'funded {sender_addr}')

# use airdrop source as destination for the following transactions
airdrop_source = PublicKey.from_base58("DemXVWQ9DXYsGFpmjFXxki3PE1i3VoHQtqxXQFx38pmU")

# Send a payment of 1 Kin
tx_id = submit_payment(Payment(sender, airdrop_source, TransactionType.NONE, int(1e5)))
print(f'submitted: {base58.b58encode(tx_id)}')

tx_data = client.get_transaction(tx_id)
print(repr(tx_data))

# Send a payment of 1 Kin with a text memo
tx_id = submit_payment(Payment(sender, airdrop_source, TransactionType.NONE, int(1e5), memo='somememo'))
print(f'submitted: {base58.b58encode(tx_id)}')

tx_data = client.get_transaction(tx_id)
print(repr(tx_data))