Skip to content
Helpers

Sync

Bring the device up to date with Solana, bound and stop a sync, and keep it running in the background.

The private balance lives on the user's device. syncNoteStore brings it up to date with Solana and Nimbus's indexer. Why the device syncs explains the reason.

Every payment syncs before it starts. Between payments, syncing is up to you. In this guide, Alice's app syncs when she opens it, then every 15 seconds while the tab is visible.

Sync once

import {  } from "@umbra/nimbus-solana-web";

const  = await (, {});

switch (.) {
  case "ingested":
    .(`Synced through slot ${.}.`, .);
    break;
  case "unregistered":
    .("Register first. There is nothing to sync yet.");
    break;
  case "unavailable":
    .(`Stopped at ${.}. The next sync carries on.`);
    break;
}

The result

kindWhat happenedWhat to do
ingestedThe device took in everything through slot, in rounds rounds.Read the balance again.
unregisteredAlice has not registered, so there is nothing to read.Register first.
unavailableThe device's storage refused a step, or another tab kept writing to it.Sync again later. Nothing taken in is lost.

unavailable also carries step, the step that stopped, and detail. Both are for your logs.

A sync throws a NimbusSdkError when it cannot go on. The reason is service-unavailable when the indexer or the RPC cannot be reached. It is unreadable when either answers something that cannot be read.

What caughtUp means

A sync runs in rounds. Each round reads one page of everything new, up to pageRows rows.

caughtUp is true when the last round reached the end of everything new. It is false only when maxRounds ran out first. Sync again to read the rest.

Options

OptionDefaultWhat it does
maxRoundsno limitThe most rounds to run. A whole number of at least 1.
pageRows1000The rows asked for in each page, from 1 to 1000.
signalnoneAn AbortSignal that stops the sync between rounds.
onProgressnoneCalled after each round with its round, slot and caughtUp.

A maxRounds or pageRows outside its range throws a NimbusSdkError with reason misconfigured, before anything is fetched.

When the signal aborts, the sync stops between rounds. It rejects with the signal's reason, and what earlier rounds took in stays.

Sync in the background

This recipe syncs every 15 seconds while the tab is visible. It reads a few rounds at a time, never runs two syncs at once, and returns a function that stops it:

import {  } from "@umbra/nimbus-solana-web";

function (: NimbusSession): () => void {
  const  = new ();
  let  = false;

  const  = async (): <void> => {
    if ( || . !== "visible") return;
     = true;
    try {
      const  = await (
        ,
        {},
        { : 3, : . },
      );
      if (. === "ingested") await ();
    } catch () {
      if (!..) .();
    } finally {
       = false;
    }
  };

  void ();
  const  = (() => void (), 15_000);

  return () => {
    ();
    .();
  };
}

Call the stop function before you close the session. A sync that is still running then stops at the end of its round.

What a sync also does

  • It frees stopped payments. A payment whose tab closed before it sent anything holds part of the balance. A sync gives it back. See Reserved funds.
  • It serves every tab. Each tab of your app on the same site reads the same device storage. A sync in one tab updates the balance for all of them.

Two tabs syncing at once is safe, but wasted work. A step that keeps losing to the other tab returns unavailable, and the next sync finishes it.

Next

Last updated

On this page