Skip to content
Implements limitless advanced queries to Stellar Horizon nodes (sources)
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.
web @ 025fcdb

loopcall / ReadmeContributingChangelog


Licence Build Coverage Dependencies Vulnerabilities Downloads Bundle

Implements limitless advanced queries to Stellar Horizon nodes.


Loopcall is a tiny library that enables unlimited complex queries to Horizon nodes. It takes a CallBuilder and accepts a few optional parameters. It returns an array of records similar to the ones returned by



  • NPM: npm install @cosmic-plus/loopcall
  • Yarn: yarn add @cosmic-plus/loopcall

In your script: const loopcall = require("@cosmic-plus/loopcall")


bower install cosmic-plus-loopcall

In your HTML page:

<script src="./bower_components/cosmic-plus-loopcall/loopcall.js"></script>


In your HTML page:

<script src=""></script>

Note: For production release it is advised to serve your copy of the library.



loopcall(callBuilder, [options]) ⇒ Array

Fetch more than 200 records

To get an arbitrary amount of record:

const callBuilder = server.operations().order("asc")
const the2000FirstOperations = await loopcall(callBuilder, { limit: 2000 })

To get all existing records (take care with that one!):

const callBuilder = server.transactions().forAccount("GDE...YBX")
const allTransactions = await loopcall(callBuilder)

Conditional Break

To stop fetching records when a condition is met:

const callBuilder = server.transactions().forAccount("GDE...YBX")
const thisYearTransactions = await loopcall(callBuilder, {
  breaker: record => record.created_at.substr(0, 4) < 2018

breaker is a Function that is called over each fetched record. Once it returns true, the fetching loop breaks and the record that triggered the break is discarded.

Conditional Filtering

To filter records by condition:

const callBuilder = server.transactions().forAccount("GDE...YBX")
const transactionsWithoutMemo = await loopcall(callBuilder, {
  filter: record => !record.memo

filter is a Function that is called over each fetched record. When provided, the records are added to the query results only when it returns true.

Iterating over records on-the-fly

In some situations waiting for the result to be concatenated is not an option. filter offers the possibility of iterating over records while they are fetched:

const callBuilder = server.transactions()

async function showTxUntilScreenIsFilled(record) {
  await endOfPageReached()

loopcall(callBuilder, { filter: showTxUntilScreenIsFilled })

This example shows a part of the code to implement unlimited scrolling on a webpage showing the last transactions on a Stellar network.

Combining parameters

All those parameters may be combined together:

const callBuilder = server.operations().order("asc")

function iterateOver1000RecordsMax() {
  let counter = 0
  return function() {
    if (counter > 1000) return true

const the20firstAccountCreations = await loopcall(callBuilder, {
  limit: 20,
  breaker: iterateOver1000RecordsMax(),
  filter: record => record.type === "create_account"

When both are provided, breaker is called before filter.

Param Type Description
callBuilder CallBuilder A CallBuilder object
[options] Object
[options.limit] Integer The maximum number of record to return
[options.filter] function A function that accepts a record argument. It is called with each fetched record. If it returns a true value, the record is added to returned records, else it is discarded.
[options.breaker] function A function that accepts a record argument. It is called with each fetched record. If it returns a true value, the loop ends and the array of the filtered records is returned.


Organization: | @GitHub | @NPM

Follow: Reddit | Twitter | Medium | Codepen

Talk: Telegram | Keybase

You can’t perform that action at this time.