コード例 #1
0
    def test_transaction_duplicate_keys(self):
        payer, program = generate_keys(2)
        keys = generate_keys(4)
        data = bytes([1, 2, 3])

        # Key[0]: ReadOnlySigner -> WritableSigner
        # Key[1]: ReadOnly       -> ReadOnlySigner
        # Key[2]: Writable       -> Writable       (ReadOnly,noop)
        # Key[3]: WritableSigner -> WritableSigner (ReadOnly,noop)

        tx = Transaction.new(
            payer.public_key,
            [
                Instruction(
                    program.public_key,
                    data,
                    [
                        AccountMeta.new_read_only(keys[0].public_key, True),  # 0 ReadOnlySigner
                        AccountMeta.new_read_only(keys[1].public_key, False),  # 1 ReadOnly
                        AccountMeta.new(keys[2].public_key, False),  # Writable
                        AccountMeta.new(keys[3].public_key, True),  # WritableSigner
                        # Upgrade keys [0] and [1]
                        AccountMeta.new(keys[0].public_key, False),  # Writable (promote to WritableSigner)
                        AccountMeta.new_read_only(keys[1].public_key, True),  # Signer (promote to ReadOnlySigner)
                        # 'Downgrade' keys [2] and [3] (should be noop)
                        AccountMeta.new_read_only(keys[2].public_key, False),  # ReadOnly; still Writable
                        AccountMeta.new_read_only(keys[3].public_key, False)  # Readonly; still a WritableSigner
                    ],
                ),
            ]
        )

        # Intentionally sign out of order to ensure ordering is fixed
        tx.sign([keys[0], keys[1], keys[3], payer])

        assert len(tx.signatures) == 4
        assert len(tx.message.accounts) == 6
        assert tx.message.header.num_signatures == 3
        assert tx.message.header.num_read_only_signed == 1
        assert tx.message.header.num_read_only == 1

        message = tx.message.marshal()
        for idx, key in enumerate([payer, keys[0], keys[3], keys[1]]):
            assert key.public_key.verify(message, tx.signatures[idx])

        expected_keys = [payer, keys[0], keys[3], keys[1], keys[2], program]
        for idx, account in enumerate(expected_keys):
            assert tx.message.accounts[idx] == account.public_key

        assert tx.message.instructions[0].program_index == 5
        assert tx.message.instructions[0].data == data
        assert tx.message.instructions[0].accounts == bytes([1, 3, 4, 2, 1, 3, 4, 2])
コード例 #2
0
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
コード例 #3
0
    def test_create_associated_account(self):
        keys = [key.public_key for key in generate_keys(3)]

        expected_addr = get_associated_account(keys[1], keys[2])

        instruction, addr = create_associated_token_account(
            keys[0], keys[1], keys[2])
        assert addr == expected_addr

        assert len(instruction.data) == 0
        assert len(instruction.accounts) == 7

        assert instruction.accounts[0].is_signer
        assert instruction.accounts[0].is_writable
        assert not instruction.accounts[1].is_signer
        assert instruction.accounts[1].is_writable

        for i in range(2, len(instruction.accounts)):
            assert not instruction.accounts[i].is_signer
            assert not instruction.accounts[i].is_writable

        assert instruction.accounts[4].public_key == system.PROGRAM_KEY
        assert instruction.accounts[5].public_key == PROGRAM_KEY
        assert instruction.accounts[6].public_key == system.RENT_SYS_VAR

        tx = Transaction.unmarshal(
            Transaction.new(keys[0], [instruction]).marshal())
        decompiled = decompile_create_associated_account(tx.message, 0)
        assert decompiled.subsidizer == keys[0]
        assert decompiled.owner == keys[1]
        assert decompiled.mint == keys[2]
コード例 #4
0
    def test_errors_from_solana_tx(self, instruction_index, exp_op_index, exp_payment_index):
        keys = [pk.public_key for pk in generate_keys(4)]
        tx = solana.Transaction.new(
            keys[0],
            [
                memo.memo_instruction('data'),
                token.transfer(keys[1], keys[2], keys[1], 100),
                token.set_authority(keys[1], keys[1], token.AuthorityType.CLOSE_ACCOUNT, keys[3])
            ]
        )
        tx_id = b'tx_sig'

        errors = TransactionErrors.from_solana_tx(tx, model_pbv4.TransactionError(
            reason=model_pbv4.TransactionError.Reason.INSUFFICIENT_FUNDS,
            instruction_index=instruction_index,
        ), tx_id)
        assert isinstance(errors.tx_error, InsufficientBalanceError)
        assert len(errors.op_errors) == 3
        for i in range(0, len(errors.op_errors)):
            if i == exp_op_index:
                assert isinstance(errors.op_errors[i], InsufficientBalanceError)
            else:
                assert not errors.op_errors[i]

        if exp_payment_index > -1:
            assert len(errors.payment_errors) == 1
            for i in range(0, len(errors.payment_errors)):
                if i == exp_payment_index:
                    assert isinstance(errors.payment_errors[i], InsufficientBalanceError)
                else:
                    assert not errors.payment_errors[i]
        else:
            assert not errors.payment_errors
コード例 #5
0
    def test_transaction_invalid_accounts(self):
        keys = generate_keys(2)
        tx = Transaction.new(
            keys[0].public_key,
            [Instruction(
                keys[1].public_key,
                bytes([1, 2, 3]),
                [
                    AccountMeta.new(keys[0].public_key, True)
                ],
            )],
        )
        tx.message.instructions[0].program_index = 2  # invalid index
        with pytest.raises(ValueError):
            Transaction.unmarshal(tx.marshal())

        tx = Transaction.new(
            keys[0].public_key,
            [Instruction(
                keys[1].public_key,
                bytes([1, 2, 3]),
                [
                    AccountMeta.new(keys[0].public_key, True)
                ],
            )],
        )
        tx.message.instructions[0].accounts = bytes([2])  # invalid index
        with pytest.raises(ValueError):
            Transaction.unmarshal(tx.marshal())
コード例 #6
0
    def test_create_without_account_holder_auth(self):
        keys = [priv.public_key for priv in generate_keys(3)]

        create_instructions, addr = self._generate_create(keys[0], keys[1], keys[2])
        create_assoc_instruction, assoc = token.create_associated_token_account(keys[0], keys[1], keys[2])
        txs = [
            solana.Transaction.new(
                keys[0],
                create_instructions[:3],
            ),
            solana.Transaction.new(
                keys[0],
                [
                    create_assoc_instruction,
                    token.set_authority(assoc, assoc, token.AuthorityType.CLOSE_ACCOUNT, new_authority=keys[0]),
                ]
            )
        ]

        for idx, tx in enumerate(txs):
            creations, payments = parse_transaction(tx)
            assert len(creations) == 1
            assert len(payments) == 0

            if idx == 0:
                # Randomly generated in _generate_create
                assert creations[0].owner
                assert creations[0].address == addr
            else:
                assert creations[0].owner == keys[1]
                assert creations[0].address == assoc
コード例 #7
0
ファイル: test_events.py プロジェクト: abuhabban/kin-python
    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'
コード例 #8
0
ファイル: test_payment.py プロジェクト: abuhabban/kin-python
    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
コード例 #9
0
def _generate_create_tx() -> Tuple[solana.Transaction, PublicKey, PublicKey]:
    keys = [key.public_key for key in generate_keys(2)]
    create_assoc_instruction, assoc = token.create_associated_token_account(
        _SIGNING_KEY.public_key, keys[0], keys[1])
    return solana.Transaction.new(_SIGNING_KEY.public_key, [
        create_assoc_instruction,
        token.set_authority(assoc,
                            assoc,
                            token.AuthorityType.CLOSE_ACCOUNT,
                            new_authority=_SIGNING_KEY.public_key),
    ]), keys[0], assoc
コード例 #10
0
ファイル: test_events.py プロジェクト: abuhabban/kin-python
    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'
コード例 #11
0
    def test_transaction_single_instruction(self):
        payer, program = generate_keys(2)
        keys = generate_keys(4)
        data = bytes([1, 2, 3])

        tx = Transaction.new(
            payer.public_key,
            [Instruction(
                program.public_key,
                data,
                [
                    AccountMeta.new_read_only(keys[0].public_key, True),
                    AccountMeta.new_read_only(keys[1].public_key, False),
                    AccountMeta.new(keys[2].public_key, False),
                    AccountMeta.new(keys[3].public_key, True),
                ],
            )],
        )

        tx.sign([keys[0], keys[3], payer])

        assert len(tx.signatures) == 3
        assert len(tx.message.accounts) == 6
        assert tx.message.header.num_signatures == 2
        assert tx.message.header.num_read_only_signed == 1
        assert tx.message.header.num_read_only == 2

        message = tx.message.marshal()

        assert payer.public_key.verify(message, tx.signatures[0])
        assert keys[3].public_key.verify(message, tx.signatures[1])
        assert keys[0].public_key.verify(message, tx.signatures[2])

        expected_keys = [payer, keys[3], keys[0], keys[2], keys[1], program]
        for idx, key in enumerate(expected_keys):
            assert tx.message.accounts[idx] == key.public_key

        assert tx.message.instructions[0].program_index == 5
        assert tx.message.instructions[0].data == data
        assert tx.message.instructions[0].accounts == bytes([2, 4, 3, 1])
コード例 #12
0
    def test_transfers_with_invoices(self):
        keys = [priv.public_key for priv in generate_keys(5)]

        # Single memo
        memo_instruction, il = self._get_invoice_memo_instruction(TransactionType.SPEND, 10, 2)
        tx = solana.Transaction.new(
            keys[0],
            [
                memo_instruction,
                token.transfer(keys[1], keys[2], keys[3], 10),
                token.transfer(keys[2], keys[3], keys[4], 20)
            ],
        )
        creations, payments = parse_transaction(tx, il)
        assert len(creations) == 0

        for i in range(2):
            assert payments[i].sender == keys[1 + i]
            assert payments[i].destination == keys[2 + i]
            assert payments[i].tx_type == TransactionType.SPEND
            assert payments[i].quarks == (1 + i) * 10
            assert payments[i].invoice == Invoice.from_proto(il.invoices[i])
            assert not payments[i].memo

        # Multiple memos
        memo_instruction_1, il1 = self._get_invoice_memo_instruction(TransactionType.SPEND, 10, 1)
        memo_instruction_2, il2 = self._get_invoice_memo_instruction(TransactionType.P2P, 10, 1)

        tx = solana.Transaction.new(
            keys[0],
            [
                memo_instruction_1,
                token.transfer(keys[1], keys[2], keys[3], 10),
                memo_instruction_2,
                token.transfer(keys[2], keys[3], keys[4], 20),
            ],
        )
        creations, payments = parse_transaction(tx, il1)
        assert len(creations) == 0

        expected_invoices = [il1.invoices[0], None]
        expected_types = [TransactionType.SPEND, TransactionType.P2P]
        for i in range(2):
            assert payments[i].sender == keys[1 + i]
            assert payments[i].destination == keys[2 + i]
            assert payments[i].tx_type == expected_types[i]
            assert payments[i].quarks == (1 + i) * 10
            if expected_invoices[i]:
                assert payments[i].invoice == Invoice.from_proto(expected_invoices[i])
            else:
                assert not payments[i].invoice
            assert not payments[i].memo
コード例 #13
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
コード例 #14
0
 def test_transaction_missing_blockhash(self):
     payer, program = generate_keys(2)
     tx = Transaction.new(
         payer.public_key,
         [Instruction(
             program.public_key,
             bytes([1, 2, 3]),
             [
                 AccountMeta.new(payer.public_key, True),
             ],
         )],
     )
     assert Transaction.unmarshal(tx.marshal()) == tx
コード例 #15
0
ファイル: test_program.py プロジェクト: abuhabban/kin-python
    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]
コード例 #16
0
    def test_from_json_invalid(self):
        with pytest.raises(ValueError) as e:
            CreateAccountRequest.from_json({})
        assert 'solana_transaction' in str(e)

        keys = [key.public_key for key in generate_keys(4)]
        tx = solana.Transaction.new(keys[0], [
            token.transfer(
                keys[1],
                keys[2],
                keys[3],
                20,
            ),
        ])

        with pytest.raises(ValueError) as e:
            CreateAccountRequest.from_json(
                {'solana_transaction': base64.b64encode(tx.marshal())})
        assert 'unexpected payments' in str(e)

        tx = solana.Transaction.new(keys[0], [])
        with pytest.raises(ValueError) as e:
            CreateAccountRequest.from_json(
                {'solana_transaction': base64.b64encode(tx.marshal())})
        assert 'expected exactly 1 creation' in str(e)

        create_assoc_instruction1, assoc1 = token.create_associated_token_account(
            keys[0], keys[1], keys[2])
        create_assoc_instruction2, assoc2 = token.create_associated_token_account(
            keys[0], keys[1], keys[2])
        tx = solana.Transaction.new(keys[0], [
            create_assoc_instruction1,
            token.set_authority(assoc1,
                                assoc1,
                                token.AuthorityType.CLOSE_ACCOUNT,
                                new_authority=keys[0]),
            create_assoc_instruction2,
            token.set_authority(assoc2,
                                assoc2,
                                token.AuthorityType.CLOSE_ACCOUNT,
                                new_authority=keys[0]),
        ])
        with pytest.raises(ValueError) as e:
            CreateAccountRequest.from_json(
                {'solana_transaction': base64.b64encode(tx.marshal())})
        assert 'expected exactly 1 creation' in str(e)
コード例 #17
0
    def test_with_invalid_instructions(self):
        keys = [priv.public_key for priv in generate_keys(5)]
        invalid_instructions = [
            token.set_authority(keys[1], keys[2], AuthorityType.ACCOUNT_HOLDER, new_authority=keys[3]),
            token.initialize_account(keys[1], keys[2], keys[3]),
            system.create_account(keys[1], keys[2], keys[3], 10, 10),
        ]

        for i in invalid_instructions:
            tx = solana.Transaction.new(
                keys[0],
                [
                    token.transfer(keys[1], keys[2], keys[3], 10),
                    i,
                ]
            )

            with pytest.raises(ValueError):
                parse_transaction(tx)
コード例 #18
0
    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
コード例 #19
0
    def test_transfers_no_invoices(self):
        keys = [priv.public_key for priv in generate_keys(5)]

        tx = solana.Transaction.new(
            keys[0],
            [
                token.transfer(keys[1], keys[2], keys[3], 10),
                token.transfer(keys[2], keys[3], keys[4], 20),
            ],
        )
        creations, payments = parse_transaction(tx)
        assert len(creations) == 0

        for i in range(2):
            assert payments[i].sender == keys[1 + i]
            assert payments[i].destination == keys[2 + i]
            assert payments[i].tx_type == TransactionType.UNKNOWN
            assert payments[i].quarks == (1 + i) * 10
            assert not payments[i].invoice
            assert not payments[i].memo
コード例 #20
0
    def test_all(self, grpc_channel, executor):
        resolver = TokenAccountResolver(
            account_stub=account_pb_grpc.AccountStub(grpc_channel))

        owner, token1, token2 = [key.public_key for key in generate_keys(3)]
        future = executor.submit(resolver.resolve_token_accounts, owner)

        md, request, rpc = grpc_channel.take_unary_unary(
            account_pb.DESCRIPTOR.services_by_name['Account'].
            methods_by_name['ResolveTokenAccounts'])
        rpc.terminate(
            account_pb.ResolveTokenAccountsResponse(token_accounts=[
                model_pb.SolanaAccountId(value=key.raw)
                for key in [token1, token2]
            ]), (), grpc.StatusCode.OK, '')

        assert future.result() == [token1, token2]

        # ensure it's cached
        assert resolver.resolve_token_accounts(owner) == [token1, token2]
コード例 #21
0
    def test_create_account(self):
        public_keys = [key.public_key for key in generate_keys(3)]
        instruction = create_account(public_keys[0], public_keys[1],
                                     public_keys[2], 12345, 67890)

        assert len(instruction.data) == 52
        assert instruction.data[0:4] == Command.CREATE_ACCOUNT.to_bytes(
            4, 'little')
        assert instruction.data[4:12] == (12345).to_bytes(8, 'little')
        assert instruction.data[12:20] == (67890).to_bytes(8, 'little')
        assert instruction.data[20:] == public_keys[2].raw

        tx = Transaction.unmarshal(
            Transaction.new(public_keys[0], [instruction]).marshal())
        decompiled = decompile_create_account(tx.message, 0)
        assert decompiled.funder == public_keys[0]
        assert decompiled.address == public_keys[1]
        assert decompiled.owner == public_keys[2]
        assert decompiled.lamports == 12345
        assert decompiled.size == 67890
コード例 #22
0
ファイル: test_program.py プロジェクト: abuhabban/kin-python
    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)

        assert instruction.data[0] == Command.TRANSFER
        assert instruction.data[1:] == (123456789).to_bytes(8, 'little')

        assert not instruction.accounts[0].is_signer
        assert instruction.accounts[0].is_writable
        assert not instruction.accounts[1].is_signer
        assert instruction.accounts[1].is_writable
        assert instruction.accounts[2].is_signer
        assert instruction.accounts[2].is_writable

        tx = Transaction.unmarshal(Transaction.new(public_keys[0], [instruction]).marshal())
        decompiled = decompile_transfer(tx.message, 0, _token_program)
        assert decompiled.source == public_keys[0]
        assert decompiled.dest == public_keys[1]
        assert decompiled.owner == public_keys[2]
        assert decompiled.amount == 123456789
コード例 #23
0
ファイル: test_payment.py プロジェクト: abuhabban/kin-python
    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'
コード例 #24
0
    def test_create_without_close_authority(self):
        keys = [priv.public_key for priv in generate_keys(3)]

        create_instructions, addr = self._generate_create(keys[0], keys[1], keys[2])
        create_assoc_instruction, assoc = token.create_associated_token_account(keys[0], keys[1], keys[2])
        txs = [
            solana.Transaction.new(
                keys[0],
                create_instructions[:2],
            ),
            solana.Transaction.new(
                keys[0],
                [
                    create_assoc_instruction,
                ],
            )
        ]

        for tx in txs:
            with pytest.raises(ValueError) as e:
                parse_transaction(tx)
            assert 'SetAuthority(Close)' in str(e)
コード例 #25
0
    def test_get_tx_id(self):
        envelope = _generate_envelope()
        data = {
            'kin_version': 3,
            'envelope_xdr': envelope.xdr(),
        }

        req = SignTransactionRequest.from_json(data, Environment.TEST)
        assert req.get_tx_id() == envelope.hash_meta()

        envelope = _generate_kin_2_envelope()
        data = {
            'kin_version': 2,
            'envelope_xdr': envelope.xdr(),
        }

        req = SignTransactionRequest.from_json(data, Environment.TEST)
        assert req.get_tx_id() == envelope.hash_meta()

        keys = generate_keys(4)
        public_keys = [key.public_key for key in keys]
        token_program = public_keys[3]

        tx = solana.Transaction.new(
            public_keys[0],
            [
                solana.transfer(
                    public_keys[1],
                    public_keys[2],
                    public_keys[3],
                    20,
                    token_program,
                ),
            ]
        )
        tx.sign([keys[0]])

        req = SignTransactionRequest.from_json(data, Environment.TEST)
        assert req.get_tx_hash() == envelope.hash_meta()
コード例 #26
0
ファイル: test_payment.py プロジェクト: abuhabban/kin-python
    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)
コード例 #27
0
ファイル: test_program.py プロジェクト: abuhabban/kin-python
    def test_set_authority(self):
        public_keys = [key.public_key for key in generate_keys(3)]

        # With no new authority
        instruction = set_authority(public_keys[0], public_keys[1], AuthorityType.AccountHolder, _token_program)

        assert instruction.data[0] == Command.SET_AUTHORITY
        assert instruction.data[1] == AuthorityType.AccountHolder
        assert instruction.data[2] == 0

        tx = Transaction.unmarshal(Transaction.new(public_keys[0], [instruction]).marshal())
        decompiled = decompile_set_authority(tx.message, 0, _token_program)
        assert decompiled.account == public_keys[0]
        assert decompiled.current_authority == public_keys[1]
        assert decompiled.authority_type == AuthorityType.AccountHolder
        assert not decompiled.new_authority

        # With new authority
        instruction = set_authority(public_keys[0], public_keys[1], AuthorityType.CloseAccount, _token_program,
                                    new_authority=public_keys[2])

        assert instruction.data[0] == Command.SET_AUTHORITY
        assert instruction.data[1] == AuthorityType.CloseAccount
        assert instruction.data[2] == 1
        assert instruction.data[3:] == public_keys[2].raw

        assert not instruction.accounts[0].is_signer
        assert instruction.accounts[0].is_writable
        assert instruction.accounts[1].is_signer
        assert not instruction.accounts[1].is_writable

        tx = Transaction.unmarshal(Transaction.new(public_keys[0], [instruction]).marshal())
        decompiled = decompile_set_authority(tx.message, 0, _token_program)
        assert decompiled.account == public_keys[0]
        assert decompiled.current_authority == public_keys[1]
        assert decompiled.authority_type == AuthorityType.CloseAccount
        assert decompiled.new_authority == public_keys[2]
コード例 #28
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'
コード例 #29
0
    def test_from_json_with_tx_event(self):
        keys = [key.public_key for key in generate_keys(3)]
        tx = solana.Transaction.new(
            keys[0],
            [
                solana.transfer(
                    keys[1],
                    keys[1],
                    keys[2],
                    20,
                ),
            ]
        )

        event = Event.from_json({
            'transaction_event': {
                'tx_id': base64.b64encode(b'txsig'),
                'solana_event': {
                    'transaction': base64.b64encode(tx.marshal()).decode('utf-8'),
                }
            }
        })
        assert event.transaction_event.tx_id == b'txsig'
        assert event.transaction_event.solana_event
コード例 #30
0
    def test_no_accounts(self, grpc_channel, executor):
        resolver = TokenAccountResolver(
            account_stub=account_pb_grpc.AccountStub(grpc_channel))

        account = generate_keys(1)[0].public_key
        future = executor.submit(resolver.resolve_token_accounts, account)

        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() == []

        # ensure not cached
        future = executor.submit(resolver.resolve_token_accounts, account)
        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() == []