Skip to content
Helpers

History

Read the user's past payments a page at a time, tell deposits, withdrawals and Private Sends apart, and know what history cannot show.

readHistory reads one page of the user's past payments, newest first. Like the balance, it reads the device, not the network. It shows what the last sync took in.

In this guide, Alice's app lists her payments ten at a time. Bob paid her 5 USDC with a Private Send, and the app shows it as received.

Read a page

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

const  = await (, {}, { : 10 });

for (const  of .) {
  .(., .., ..);
}

Each item is one Solana transaction that touched Alice's private balance:

  • slot and signature say where it landed.
  • received lists what it paid into her private balance. Each entry's note.amount is the amount, and note.mintIdentifier names the token.
  • spent lists what it took out of her private balance.
  • record is kept for Alice's own transactions. It holds their public side, such as the wallet a deposit came from.
  • others holds the public side of someone else's transaction that paid her, when there is one.

Page through it

limit is the page size, from 1 to 100. It is 20 when you leave it out. Any other value throws a NimbusSdkError with reason misconfigured.

When page.next.kind is more, older items remain. Pass page.next.position back as after to read them:

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

switch (..) {
  case "more": {
    const  = await (
      ,
      {},
      { : 10, : .. },
    );
    .(..);
    break;
  }
  case "done":
    .("That was the oldest page.");
    break;
}

Pass the position back unchanged. Each page continues where the last one ended, without repeats.

Deposit, withdrawal or Private Send

The SDK does not label items. A transaction's public side decides what it was. Money in from a public wallet is a deposit. Money out to one is a withdrawal. A transaction with neither is a Private Send.

The example app labels items this way, in apps/nimbus-example/lib/activity.ts:

type  = HistoryPage["items"][number];

type  =
  | "deposit"
  | "withdrawal"
  | "deposit-and-withdrawal"
  | "private-send-sent"
  | "private-send-received"
  | "deposit-received";

function (: ):  {
  if (.. === "kept") {
    const  = ....;
    if (. === "known") {
      const  = .. > 0;
      const  = .. > 0;
      if ( && !) return "deposit";
      if ( && !) return "withdrawal";
      if () return "deposit-and-withdrawal";
    }
    return .. === 0 ? "deposit" : "private-send-sent";
  }
  if (.. > 0) return "private-send-sent";
  if (.. === "legs" && .... > 0) {
    return "deposit-received";
  }
  return "private-send-received";
}

Alice's own transactions carry their record. Its legs are the public money in (inflows) and out (outflows), each with an address, a token and an amount. When the network has not served them yet, legs.kind is missing.

Bob's Private Send to Alice has no record of hers, so it reads as private-send-received. When Bob deposits straight into Alice's private balance instead, others shows his wallet, and it reads as deposit-received.

Name the token

A received entry names its token by note.mintIdentifier, not by address. findMintByIdentifier turns it back into the token's address and decimals:

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

for (const  of .) {
  for (const {  } of .) {
    const  = (, {
      : .,
    });
    .(., ?., ?.);
  }
}

It returns nothing for a token the SDK's preset does not list.

What history can and cannot show

  • Only what this device has synced. A payment appears after the next sync takes it in.
  • Not who sent a Private Send. Bob's payment shows its amount and token. Nothing in it names Bob.
  • Not every slot yet. page.coverage gives, for each pool, the slot the history is complete through. Do not show anything after that slot as "nothing happened".
  • Payments still on their way. page.pendingOwn lists Alice's own payments that were sent but not yet taken in by a sync. It is the same on every page.

Next

Last updated

On this page