4

I am trying to get all of the transactions on a Coinbase account, which requires pagination. The documentation is sparse on how to do this in Python, but I have managed to make it work:

client = Client(keys['apiKey'], keys['apiSecret'])
accounts = client.get_accounts()

for account in accounts.data:
    txns = client.get_transactions(account.id, limit=25)
    while True: 
        for tx in txns.data:
            print(tx.id)

        if txns.pagination.next_uri != None:
            starting_after_guid = re.search('starting_after=([0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12})', txns.pagination.next_uri, re.I)[1]
            txns = client.get_transactions(account.id, limit=25, starting_after=starting_after_guid)
        else:
            break

The pagination object only contains next_uri everything else is null/None--it is supposed to contain a dict that includes starting_after among other helpful data. The regex search seems silly, but it works.

Is there a better way?

Travis P
  • 644
  • 6
  • 19

4 Answers4

3

This just takes the other answers a bit further and creates a generic function so you can use it for most paginated methods in the api.

from coinbase.wallet.client import Client


client = Client(API_KEY, SECRET)

def _get_paginated_items(api_method, limit=100):
    """Generic getter for paginated items"""
    all_items = []
    starting_after = None
    while True:
        items = api_method(limit=limit, starting_after=starting_after)
        if items.pagination.next_starting_after is not None:
            starting_after = items.pagination.next_starting_after
            all_items += items.data
        else:
            all_items += items.data
            break
    return all_items


def get_accounts(client, limit=100):
    return _get_paginated_items(client.get_accounts, limit)


def get_transactions(account, limit=100):
    return _get_paginated_items(account.get_transactions, limit)

# Use them.
accounts = get_accounts(client)
for account in accounts:
    transactions = get_transactions(account)
    # etc...
getup8
  • 6,949
  • 1
  • 27
  • 31
2

This is how it can work without regex:

_cb = Client(keys['apiKey'], keys['apiSecret'])
accounts = client.get_accounts()

for account in accounts.data:
    """ Gets the transactions history from coinbase """
    all_txns = []
    starting_after = None
    while True:
        txns = _cb.get_transactions(account['id'], limit=100, starting_after=starting_after)
        if txns.pagination.next_starting_after is not None:
            starting_after = txns.pagination.next_starting_after
            for tx in txns.data:
                all_txns.append(tx)
            time.sleep(1)  # Let's not hit the rate limiting
        else:
            for tx in txns.data:
                all_txns.append(tx)
            break

Notice that next_starting_after is taken from the transaction and used as starting_after parameter for the next query.

tlex
  • 21
  • 2
1

Above snippet encountered error. This works

client = Client(keys['apiKey'], keys['apiSecret'])
accounts = client.get_accounts()

for account in accounts.data:
    txns = client.get_transactions(account.id, limit=25)
    while True:
        for tx in txns.data:
            print(tx.id)

        if txns.pagination.next_uri != None:
            starting_after_guid = re.search('starting_after=(.*)', str(txns.pagination.next_uri), re.I).group(1)
            txns = client.get_transactions(account.id, limit=25, starting_after=starting_after_guid)
        else:
            break
Troy
  • 11
  • 1
0

Here's my code with iterators:

from coinbase.wallet.client import Client


API_KEY = '***************'
API_SECRET = '***************************'


def get_accounts_iterator(client, limit=25):
    starting_after = None
    
    while True:
        accounts = client.get_accounts(limit=limit, starting_after=starting_after)
        for account in accounts.data:
            yield account
        
        if accounts.pagination.next_starting_after is None:
            break
        
        starting_after = accounts.pagination.next_starting_after


def get_transactions_iterator(client, account_id, limit=25):
    starting_after = None
    
    while True:
        txs = client.get_transactions(account_id, limit=limit, starting_after=starting_after)
        for tx in txs.data:
            yield tx
        
        if txs.pagination.next_starting_after is None:
            break
        
        starting_after = txs.pagination.next_starting_after


def main():
    client = Client(API_KEY, API_SECRET)
    
    for account in get_accounts_iterator(client):
        if float(account.get('balance',{}).get('amount',0))==0:
            continue
        
        print(account.balance.currency, account.balance.amount)
        
        for tx in get_transactions_iterator(client, account.id):
            print(tx.amount.amount)


if __name__ == '__main__':
    main()
palawer
  • 125
  • 1
  • 9