Progress
Every payment reports its stages through onProgress. Here is every stage, which payments report it, and a message to show.
A payment takes a few seconds, and most of that is the proof. Pass onProgress to show your user
what is happening meanwhile.
How onProgress works
Every payment function takes an onProgress option. The SDK calls it once per stage, with an event
whose stage names it. The event also carries what that stage produced, such as the fees or a
transaction signature.
If your callback throws, the SDK drops the error and carries on. If it returns a promise, the SDK does not wait for it. Your callback cannot stop a payment.
Every stage
The messages are the ones the example app shows.
| Stage | Reported by | Message to show |
|---|---|---|
synced | deposit, Private Send, withdraw | Brought this device up to date with Solana. |
prepared | every payment | Prepared on this device. |
endorsed | register, deposit | The committee approved the transaction. |
proved | register, deposit, Private Send, withdraw | The privacy work on this device finished. |
funding-signed | deposit, from a wallet that signs only version 0 | Your wallet signed the transfer that funds the deposit. |
funding-sent | deposit, from a wallet that signs only version 0 | Sent the funding transfer to Solana. |
funding-confirmed | deposit, from a wallet that signs only version 0 | The funding transfer landed. |
signed | register, deposit, refund | Your wallet signed the transaction. |
sent | register, deposit, refund | Sent the transaction to Solana. |
confirmed | register, deposit, refund | The transaction landed on Solana. |
merge-prepared | Private Send, withdraw | Combining part of your private balance so one payment can cover the amount. |
merge-relayed | Private Send, withdraw | The relayer accepted the combining step. |
merge-settled | Private Send, withdraw | The combining step finished. |
relayed | Private Send, withdraw | The relayer accepted the transaction and will send it. |
settled | Private Send, withdraw | Followed the payment until Solana settled it. |
"Refund" here is refundStrandedDeposit. A few stages do not always come, or come in a different
order:
endorsedandprovedrun at the same time, so they can arrive in either order.- A registration with nothing left to send stops after
prepared. - A transaction that fails, expires or is still pending stops at
sent. The result says where it ended up. - The merge stages come before the payment's own, once per merge. Each carries a
mergenumber, from 1. settledcomes only when the SDK follows the payment, which it does unless you passfollow: false.
A message for every stage
Each payment's stages form a union on stage. A switch over all of them is checked by TypeScript.
If the SDK adds a stage, this stops compiling until you give it a message.
type =
|
|
|
|
|
| SyncedStage
| SettledStage;
function (: ): string {
switch (.) {
case "synced":
return "Brought this device up to date with Solana.";
case "prepared":
return "Prepared on this device.";
case "endorsed":
return "The committee approved the transaction.";
case "proved":
return "The privacy work on this device finished.";
case "funding-signed":
return "Your wallet signed the transfer that funds the deposit.";
case "funding-sent":
return "Sent the funding transfer to Solana.";
case "funding-confirmed":
return "The funding transfer landed.";
case "signed":
return "Your wallet signed the transaction.";
case "sent":
return "Sent the transaction to Solana.";
case "confirmed":
return "The transaction landed on Solana.";
case "merge-prepared":
return `Combining part of your private balance, step ${.}.`;
case "merge-relayed":
return `The relayer accepted combining step ${.}.`;
case "merge-settled":
return `Combining step ${.} finished.`;
case "relayed":
return "The relayer accepted the transaction and will send it.";
case "settled":
return "Followed the payment until Solana settled it.";
}
}A progress list in React
This component runs a deposit and lists each stage as it arrives:
import { } from "react";
import type { } from "react";
import { } from "@umbra/nimbus-solana-web";
export function ({
,
,
}: {
: DepositContext;
: ;
}): {
const [, ] = <readonly string[]>([]);
const [, ] = (false);
async function (): <void> {
([]);
(true);
try {
await (
,
{
: ,
: 25_000_000n,
: ..,
},
{
: () => {
(() => [..., ()]);
},
},
);
} finally {
(false);
}
}
return (
<>
< ="button" ={} ={() => void ()}>
Deposit 25 USDC
</>
{ && <>Keep this tab open until the deposit finishes.</>}
<>
{.((, ) => (
< ={}>{}</>
))}
</>
</>
);
}The button stays disabled while the deposit runs, so your user cannot start a second one. The
result's kind still says how it ended. Show it as the deposit guide does.
Last updated