Add stamps
See Fromboxes
for what stamps are and why prepayment is required. This page covers the
sithbit frombox stamp command.
sithbit frombox stamp <from> [to_address] \
[--keypair <keypair>] \
[--stamps <count>] \
[--max-price <lamports> | --no-max-price] \
[--skip-preflight]
Adding stamps prepays postage into a frombox — creating the
frombox on the spot if it does not exist yet (see
Creating the frombox on first purchase).
This command buys <count> stamps at the frombox’s current
per-stamp price and adds them to the balance.
Anyone can add stamps — a sender buying their own postage to reach a recipient, or the recipient prefunding a sender so their mail stays free. The signer is the payer.
Arguments and flags
<from>— the sender’s “from” address (alias, wallet address, or keypair path). Hashed client-side; only the hash reaches the chain.[to_address]— the recipient whose frombox is being funded. Defaults to your own address.--keypair <keypair>(short-k) — the payer’s keypair; defaults to the CLI’s configured key.--stamps <count>(short-p) — how many stamps to buy. Defaults to1.--max-price <lamports>— the highest per-stamp price this purchase will accept. Defaults to the price quoted from the chain, so you never pay more than you were shown; pass a higher figure to pre-authorize a rise you are willing to absorb. See The price can move under you.--no-max-price— buy at whatever the price turns out to be, with no guard. Mutually exclusive with--max-price.--skip-preflight(short-s) — skip the RPC pre-flight simulation.
The frombox does not need to exist first: if it is absent this command creates it (see Creating the frombox on first purchase). Adding stamps never changes the price; run update for that.
Example
Top up a sender’s frombox by 10 stamps:
sithbit frombox stamp [email protected] --stamps 10
Purchasing 10 stamps for frombox 7XkQ…Qp9 <From:[email protected] To:9aBc…prj>
Protocol fee: waived (owner purchase)
Purchased 10 stamps
see https://explorer.solana.com/tx/…?cluster=devnet
When the recipient pays for their own mailbox’s frombox the per-stamp
protocol fee is waived, as shown. A third party funding a frombox to someone
else instead sees the fee it will pay, e.g.
Protocol fee: 1000000 lamports (100000 per stamp).
Creating the frombox on first purchase
When the target frombox does not exist yet, frombox stamp opens it in the
same transaction instead of failing. The CLI checks the chain for the frombox
PDA; if it is absent it
submits a single CreateFrombox carrying your requested stamp count rather
than an AddStamps against a missing account. That one instruction allocates
the account and credits the stamps at once — the fee and postage are identical
to buying the same stamps on an existing frombox, so a first purchase and a
top-up cost the same (no separate create step, and no double charge).
The trustless webmail compose rides this same create-or-top-up decision for its inline Prepay & send: when a send finds no frombox, the card quotes the purchase (postage + surcharge + the live protocol fee) and re-sends the held draft once the stamps confirm. The webmail Balances pane rides the identical decision for its own stamp purchases, and now supports both signing flavors as well — the in-page wallet signs directly, an external Phantom/Ledger wallet approves the same purchase built unsigned.
A newly created frombox’s per-stamp price is set to the recipient mailbox’s
current default postage — scaled by the payer’s on-chain sender reputation
when the create is a third party’s (see
Reputation-scaled first contact below).
Buying stamps never sets a custom price; to give a
trusted sender a cheaper rate the recipient runs
sithbit frombox update afterwards, or sets the price
up front before any stamps are bought — see
Setting a price before the frombox exists.
Reputation-scaled first contact
A third party’s first purchase toward a recipient — the create-if-absent
path above, buying at the mailbox’s default postage — is priced by
reputation-scaled first-contact
pricing:
the default steps down with the payer wallet’s cumulative
distinct-recipient postage spend, never below the tuned floor (10% of the
default by default), and never below one lamport for a nonzero price. The
same purchase also records its escrowed postage onto the payer’s
sender-reputation account, so every first contact a sender pays for makes
the next one cheaper. Only the default is scaled: a price the recipient
set with frombox update applies verbatim, and an
owner purchase (the recipient prefunding a sender) pays the raw default
and records nothing.
The CLI builds this automatically. A third-party create carries the
reputation tail by default — a 9-account CreateFrombox form: the
legacy six accounts, the operator pair (the recipient’s mailbox PDA
fills both slots when no operator split
resolves), and the payer’s sender-reputation PDA, lazily created
rent-exempt on first use. When the payer holds a verified-sender
attestation for the from address’s domain,
the CLI detects it on-chain and appends it as a tenth account, which
prices the first contact at the floor immediately — attested
organizations skip the spend ladder. (A wallet-literal or domainless
from address has no domain to attest, so the lookup is skipped.) Owner
purchases and top-ups of an existing frombox stay on their legacy account
lists: reputation is earned and priced at first contact, never on a
top-up.
The tail never carries a guessed account: a present-but-invalid attestation fails the transaction (error 19 for another wallet’s attestation, error 17 for a bad derivation) rather than silently repricing, so only a confirmed on-chain record is ever included.
Looking up a wallet’s reputation
sithbit postoffice reputation <WALLET>
Read-only, ships in every build. It prints the wallet’s recorded cumulative postage spend and the effective first-contact rate that spend earns, in basis points of a recipient’s default postage — computed through the same on-chain rule the program applies, tuned floor included. A wallet with no reputation account reads as zero spend at the full 10,000 bps (the common negative answer, not an error):
sithbit postoffice reputation mAiLiLdgjgGdWoCZkpW3cj7JLAC56qb4NErFyQFWNJg
MX operators can query the same figures over gRPC — the
gateway’s GetSenderReputation
RPC answers with identical semantics.
Tuning the floor
The delegate tunes the discount’s floor with:
sithbit postmaster fee reputation-floor <BPS> \
[--keypair <delegate keypair>] \
[--skip-preflight]
The value is basis points of a mailbox’s default postage, hard-capped
on-chain at 10,000 bps (100% — a floor that high disables the discount
entirely); an over-cap value refuses with custom error 102
(ReputationFloorAboveCap). Zero resets to the protocol default of
1,000 bps (10%): like the other tunable rates, a zero stores the “unset”
sentinel, and a postoffice account that predates the field reads back the
default (the setter grows the legacy account in place). See the
tunable-constants table.
The prepayment rule
A third party’s first purchase toward someone else’s frombox must buy at
least one stamp: running frombox stamp --stamps 0 as anyone other than
the recipient fails, since the on-chain CreateFrombox guard refuses a
zero-stamp create from a non-owner payer. The only way to open a stampless
frombox is for the recipient (the mailbox owner) to do it while setting the
price — see
Setting a price before the frombox exists.
The price can move under you
The recipient owns the per-stamp price and can change it at any moment — including between the instant this command quotes you a price and the instant your transaction is confirmed. A purchase carrying no ceiling simply pays whatever price it finds on arrival.
So the command sets one for you. By default it pins the ceiling to the price it just quoted, and prints the figure alongside the fee preview:
Protocol fee: 30000 lamports (greater of 10000 flat per stamp and 250 bps of postage)
Slippage guard: max 1000000 lamports per stamp (quote-pinned)
If the price has risen past that ceiling by the time the transaction lands,
the program refuses the purchase with custom error 107
(PriceExceedsMax) and your postage stays in your wallet. Nothing is
partially spent — buy again at the new price if you still want the stamps.
Two ways to change that posture:
--max-price <lamports>sets the ceiling yourself. Use it to pre-authorize a rise (“I’ll pay up to 2 SOL a stamp, whatever it says today”) so a modest increase does not bounce your purchase.--no-max-priceremoves the guard entirely, restoring the older pay-whatever behavior.
The ceiling is checked against the per-stamp price, not the total, and
it applies to both purchase paths — a top-up compares it against the
frombox’s stored required_postage, while a
first purchase compares it
against the effective first-contact price after
reputation scaling. Because reputation
scaling only ever prices at or below the mailbox’s default postage, the
quoted default is a safe ceiling for a first purchase.
On-chain effect
The AddStamps instruction transfers postage from the payer into the
frombox account and increments its stamp count. For each stamp bought the
payer deposits:
- the per-stamp price (
required_postage); plus - a settlement surcharge (
10000lamports) that reimburses the sender’s laterSendMailandDeleteMailsignatures.
On top of that it collects the flat per-stamp protocol fee to the postoffice, waived when the payer is the recipient wallet — see Economics.
On a first purchase the command runs CreateFrombox instead: it does
everything AddStamps does (crediting the stamps and charging the same
per-stamp fee) and additionally allocates the account and funds its
rent-exemption reserve, storing the mailbox’s default_postage — scaled
by the payer’s sender reputation on a
third-party create — as the new frombox’s required_postage, and
recording the escrowed postage onto the payer’s sender-reputation
account.
Stamps are prepaid postage, not a fee charged per send. When a message is delivered, the frombox’s stored balance is split evenly across its remaining stamps: one stamp’s share is moved into the message account to fund the delivery, and the stamp count drops by one. That escrowed postage is settled when the message is deleted (a share to the recipient’s MX operator, the remainder as the recipient’s postage income) — so the price you set is really the value backing each stamp, refundable as a deposit rather than spent as a toll. See the stamp lifecycle for the full settlement path.
If you prepaid more postage than you ended up needing, you can take the unspent remainder back — see Reclaiming unspent stamps. When a frombox is no longer needed at all, see Closing accounts, where the recipient closes it and reclaims its rent and remaining stamp value.