예제 #1
0
    def payments_from_envelope(
        cls,
        envelope: te.TransactionEnvelope,
        invoice_list: Optional[model_pb2.InvoiceList] = None
    ) -> List['ReadOnlyPayment']:
        """Returns a list of read only payments from a transaction envelope.

        :param envelope: A :class:`TransactionEnvelope <kin_base.transaction_envelope.TransactionEnvelope>.
        :param invoice_list: (optional) A protobuf invoice list associated with the transaction.
        :return: A List of :class:`ReadOnlyPayment <ReadOnlyPayment>` objects.
        """
        if invoice_list and invoice_list.invoices and len(
                invoice_list.invoices) != len(envelope.tx.operations):
            raise ValueError(
                "number of invoices ({}) does not match number of transaction operations ({})"
                .format(len(invoice_list.invoices),
                        len(envelope.tx.operations)))

        tx = envelope.tx

        text_memo = None
        agora_memo = None
        if isinstance(tx.memo, memo.HashMemo):
            try:
                agora_memo = AgoraMemo.from_base_memo(tx.memo, False)
            except ValueError:
                pass
        elif isinstance(tx.memo, memo.TextMemo):
            text_memo = tx.memo

        payments = []
        for idx, op in enumerate(envelope.tx.operations):
            # Currently, only payment operations are supported in this method. Eventually, create account and merge
            # account operations could potentially be supported, but currently this is primarily only used for payment
            # operations
            if not isinstance(op, operation.Payment):
                continue

            inv = invoice_list.invoices[
                idx] if invoice_list and invoice_list.invoices else None

            payments.append(
                ReadOnlyPayment(
                    sender=PublicKey.from_string(
                        op.source if op.source else tx.source.decode()),
                    destination=PublicKey.from_string(op.destination),
                    tx_type=agora_memo.tx_type()
                    if agora_memo else TransactionType.UNKNOWN,
                    quarks=kin_to_quarks(op.amount),
                    invoice=Invoice.from_proto(inv) if inv else None,
                    memo=text_memo.text.decode() if text_memo else None,
                ))

        return payments
예제 #2
0
 def _set_successful_get_account_info_response(
     channel: grpc_testing.Channel, pk: PrivateKey, sequence: int, balance: int = kin_to_quarks("1000")
 ) -> account_pb.GetAccountInfoRequest:
     resp = account_pb.GetAccountInfoResponse(
         result=account_pb.GetAccountInfoResponse.Result.OK,
         account_info=account_pb.AccountInfo(
             account_id=model_pb2.StellarAccountId(
                 value=pk.public_key.stellar_address
             ),
             sequence_number=sequence,
             balance=balance,
         )
     )
     return TestAgoraClient._set_get_account_info_response(channel, resp)
예제 #3
0
    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()}'
    )
for result in batch_result.failed:
    print(
        f'Failed to send 1 kin to {result.earn.destination.stellar_address} in transaction {result.tx_id.hex()} '
        f'(error: {repr(result.error)})')

# Send an earn batch of earns with 1 Kin each, with invoices
예제 #4
0
 def test_kin_to_quarks(self):
     assert kin_to_quarks("0.000009") == 0
     assert kin_to_quarks("0.00015") == 15
     assert kin_to_quarks("5") == 500000
     assert kin_to_quarks("5.1") == 510000
     assert kin_to_quarks("5.123459") == 512345
예제 #5
0
    def payments_from_envelope(
        cls,
        envelope: te.TransactionEnvelope,
        invoice_list: Optional[model_pb2.InvoiceList] = None,
        kin_version: Optional[int] = 3,
    ) -> List['ReadOnlyPayment']:
        """Returns a list of read only payments from a transaction envelope.

        :param envelope: A :class:`TransactionEnvelope <kin_base.transaction_envelope.TransactionEnvelope>.
        :param invoice_list: (optional) A protobuf invoice list associated with the transaction.
        :param kin_version: (optional) The version of Kin to parse payments for.
        :return: A List of :class:`ReadOnlyPayment <ReadOnlyPayment>` objects.
        """
        if invoice_list and invoice_list.invoices and len(
                invoice_list.invoices) != len(envelope.tx.operations):
            raise ValueError(
                f'number of invoices ({len(invoice_list.invoices)}) does not match number of transaction '
                f'operations ({len(envelope.tx.operations)})')

        tx = envelope.tx

        text_memo = None
        agora_memo = None
        if isinstance(tx.memo, memo.HashMemo):
            try:
                agora_memo = AgoraMemo.from_base_memo(tx.memo, False)
            except ValueError:
                pass
        elif isinstance(tx.memo, memo.TextMemo):
            text_memo = tx.memo

        payments = []
        for idx, op in enumerate(envelope.tx.operations):
            # Currently, only payment operations are supported in this method. Eventually, create account and merge
            # account operations could potentially be supported, but currently this is primarily only used for payment
            # operations
            if not isinstance(op, operation.Payment):
                continue

            # Only Kin payment operations are supported in this method.
            if kin_version == 2 and (op.asset.type != 'credit_alphanum4'
                                     or op.asset.code != 'KIN'):
                continue

            inv = invoice_list.invoices[
                idx] if invoice_list and invoice_list.invoices else None

            # Inside the kin_base module, the base currency has been 'scaled' by a factor of 100 from
            # Stellar (i.e., the smallest denomination used is 1e-5 instead of 1e-7). However, Kin 2 uses the minimum
            # Stellar denomination of 1e-7.
            #
            # When parsing an XDR transaction, `kin_base` assumes a smallest denomination of 1e-5. Therefore, for Kin 2
            # transactions, we must divide the resulting amounts by 100 to account for the 100x scaling factor.
            payments.append(
                ReadOnlyPayment(
                    sender=PublicKey.from_string(
                        op.source if op.source else tx.source.decode()),
                    destination=PublicKey.from_string(op.destination),
                    tx_type=agora_memo.tx_type()
                    if agora_memo else TransactionType.UNKNOWN,
                    quarks=int(kin_to_quarks(op.amount) / 100)
                    if kin_version == 2 else kin_to_quarks(op.amount),
                    invoice=Invoice.from_proto(inv) if inv else None,
                    memo=text_memo.text.decode() if text_memo else None,
                ))

        return payments
예제 #6
0
                '--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)}')

# Send a payment of 1 Kin with a text memo
payment = Payment(source,
예제 #7
0
retry_config = RetryConfig(max_retries=0,
                           min_delay=0,
                           max_delay=0,
                           max_nonce_refreshes=0)
client = Client(Environment.TEST, 1,
                retry_config=retry_config)  # 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("{} succeeded, {} failed".format(len(batch_result.succeeded),
                                       len(batch_result.failed)))
for result in batch_result.succeeded:
    print("Sent 1 kin to {} in transaction {}".format(
        result.earn.destination.stellar_address,
        result.tx_hash.hex(),
    ))
for result in batch_result.failed:
    print("Failed to send 1 kin to {} in transaction {} (error: {})".format(
        result.earn.destination.stellar_address,
        result.tx_hash.hex(),
        repr(result.error),
    ))
예제 #8
0
import argparse

from agora.client import Client, Environment
from agora.keys import PublicKey
from agora.utils import kin_to_quarks

ap = argparse.ArgumentParser()
ap.add_argument(
    '-s',
    '--destination',
    required=True,
    help=
    'The base58-encoded Kin token account address of the airdrop destination account'
)
args = vars(ap.parse_args())

client = Client(Environment.TEST, 1)  # 1 is the test app index

dest = PublicKey.from_base58(args['destination'])

print(f'requesting airdrop for {dest.to_base58()}')
# Note: the airdrop service is only available when using Environment.TEST.
airdrop_resp = client.request_airdrop(dest, kin_to_quarks("5"))

print(f'funded {dest.to_base58()} with {5} Kin')

# The client should be closed once it is no longer needed.
client.close()
예제 #9
0
 def submit_payment(self, sender: PrivateKey, destination: PublicKey,
                    amount: str, tx_type: TransactionType,
                    memo: Optional[str]):
     payment = Payment(sender, destination, tx_type, kin_to_quarks(amount),
                       memo)
     return self.client.submit_payment(payment)
예제 #10
0
 def request_airdrop(self, public_key: PublicKey, amount: str):
     return self.client.request_airdrop(public_key, kin_to_quarks(amount))