Skip to content Search Apps Documentation Source Content File Folder Download Copy Actions State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

Community realm. Read the code first. Community realm, deployed by its author. Read the code before you interact or send coins.

reimbursements package

Overview

Realm reimbursements is a claimant-initiated, approver-gated expense reimbursement desk in GNOT: an owner funds a pool and appoints an approver with a bounded, rate-limited, revocable authority to approve against it; anyone may then SUBMIT a request for a specific amount with a memo; and the approver either approves it — which settles the money into the claimant's credit immediately — or rejects it.

WHY THIS EXISTS (see DISCOVERY.md): request-then-approve is NOT new here, and an earlier draft of this comment wrongly claimed it was. Three realms in this portfolio already let a requester initiate and a second party gate before value moves — grants (applicants apply, the creator selects), bounties (a funder designates a winner) and bounty_panel (contributors submit, an M-of-N panel votes). The §7 sweep that found them is recorded in DISCOVERY.md. The claim this realm actually rests on is narrower, and all three parts are load-bearing:

  • THE REQUESTER PRICES IT. A grant or bounty amount is the funder's offer, fixed before anyone asks. A reimbursement amount is a cost the claimant already incurred, so the claimant names it and the approver's only lever is yes or no on that figure.
  • SETTLEMENT IS NON-EXCLUSIVE. Those three are competitive awards: escrow is reserved per item and exactly one requester wins. Here an unbounded number of requests settle against one SHARED, UN-ESCROWED pool, which is why a pending request is not a reservation (see below) — the divergence this realm is built on.
  • THE APPROVER IS RATE-LIMITED. In all three the selecting party may award whenever it likes. Here the approver is not the owner and holds a bounded, windowed, revocable spendbook authority, so an approver key cannot drain the pool.

The four other disbursement shapes here are further away still: treasury_board needs the PROPOSER to be a signer, so an outside claimant cannot ask; budgets grants authority up front with no per-item gate; invoices is a receivable nobody approves; payroll and vesting are employer-funded accrual on a schedule.

It is also, deliberately, the SECOND CONSUMER of spendbook, and the first with an INVERTED temporal order. budgets consumes authority at spend time by the spender. Here the spendbook "spender" is the APPROVER, and the authority is consumed at APPROVE time against a request a third party submitted. A primitive with one consumer is barely proven as a primitive; a second consumer that uses it the same way proves little more. This one exercises the opposite direction.

COMPOSITION: approval authority is delegated entirely to spendbook (anchored windows, lifetime caps, expiry, one-sided amendments, revocation), coin movement to coinio, per-claimant credit and the fee pot to feeledger, ordered storage to p/nt/avl/v0, and free-text render output to p/nt/markdown/sanitize/v0. This realm owns the pool accounting, the desk and request records, the conflict-of-interest rule, and the solvency rule.

A desk, and what an approval IS

A desk is one (owner, approver) pair with a bounded authority over the owner's pool. A request is one claimant's ask against one desk.

The DELIBERATE DIVERGENCE from budgets is at approval:

Example
1An approved reimbursement is a SETTLED OBLIGATION, not authority.

Approve moves the gross out of the owner's pool and into the claimant's ledger credit in the same call. The owner cannot then withdraw it out from under an approved claimant, and no second step can fail. budgets' rule — "a budget is authority, not a reservation" — is explicitly NOT inherited, because the two realms are answering different questions. A budget is an ongoing permission whose point is not pre-committing capital. An approved expense claim is a decision about a cost already incurred, and a decision that can evaporate is not a decision.

The realm therefore never holds a partially-committed state: a request is pending (nothing has moved) or settled (everything has moved).

A PENDING REQUEST IS NOT A LIABILITY

Stated plainly because the opposite is the natural assumption. Submitting reserves nothing, locks nothing, and is not a claim on the pool. Ten pending requests of 100 against a pool of 100 are all ten submittable; the approver can approve one of them. Liabilities() counts pooled funds and settled credit, and a pending request appears in neither. What a claimant can rely on is the moment of approval, which is atomic, and the Approvable view, which reports the honest figure before they are told yes.

THE APPROVER IS THE SPENDBOOK SPENDER

The desk's allowance is consumed by the GROSS approved amount, so it bounds the owner's total OUTFLOW per window rather than the claimant's receipt — the figure an owner actually cares about capping, and the same treatment budgets gives its fee. An approver with a PerPeriod of 1 GNOT can approve 1 GNOT of the owner's money per window no matter how many claimants ask, and no single compromised approver key can do more than its window allows before the owner revokes the desk.

SELF-APPROVAL IS PROHIBITED

Approve refuses when the request's claimant is the approving address. This is a real conflict-of-interest control and not a formality: an approver with a desk could otherwise reimburse themselves at will up to the window cap. The rule is per-APPROVAL, not per-desk, so an address cannot route its own claim through a second desk it also approves. An approver may still submit requests — to be approved by somebody else.

LIFECYCLE

Example
 1Fund (owner, +send)      : adds real coins to the caller's own pool.
 2                           Anyone may fund; funding makes you an
 3                           owner. Minimum MinFunding.
 4WithdrawPool (owner)     : pulls UNSPENT pool back out, any amount,
 5                           any time. Approved credit is already out
 6                           of the pool and unreachable.
 7WithdrawPoolAll (owner)  : the whole unspent pool.
 8OpenDesk (owner)         : appoints one approver with bounded
 9                           authority and returns the desk id. The
10                           approval fee is snapshotted here.
11AmendDesk (owner)        : changes the desk's terms. Tighter-or-equal
12                           applies now; looser waits for the next
13                           window boundary. periodLength is NOT a
14                           parameter — spendbook makes it immutable.
15CloseDesk (owner)        : immediate; the id is never reused.
16ReapDesk (ANYONE)        : removes an EXPIRED desk, freeing its slot.
17Submit (ANYONE)          : files a request against a desk for a
18                           specific amount with a memo, and returns
19                           the request id. Expires after RequestTTL
20                           blocks.
21Approve (APPROVER)       : settles the request — debits the owner's
22                           pool, credits the claimant net of the fee,
23                           consumes the desk's authority, removes the
24                           request.
25Reject (APPROVER)        : closes the request with a reason. Nothing
26                           moves. Allowed even after expiry.
27Retract (CLAIMANT)       : the claimant withdraws their own request.
28                           Nothing moves. Named Retract, not
29                           Withdraw, because every Withdraw* in this
30                           portfolio moves money and this moves none.
31ExpireRequest (ANYONE)   : removes a request past its expiry.
32Claim (CLAIMANT)         : pays the claimant's whole settled credit
33                           out. The portfolio's standard pull.
34WithdrawFees (ANYONE)    : pays the fee pot to the compile-time
35                           FeeCollector. Fixed destination.
36SweepSurplus (ANYONE)    : out-of-band coins to the FeeCollector,
37                           never touching tracked liabilities.

A CLOSED DESK LEAVES ITS REQUESTS UN-APPROVABLE

CloseDesk and ReapDesk remove the desk and its allowance. Requests filed against it remain as records and can never be approved — Approve panics on the missing desk. They can be Retracted by their claimant or, once past expiry, ExpireRequested by anyone.

There is deliberately NO CASCADE DELETE. Finding a closed desk's requests means iterating the request tree, which is unbounded work in a transaction whose gas the owner pays, and an owner who cannot close a desk because it has too many pending requests is a worse realm than one where closing leaves records to be swept. The condition is documented, visible in RequestInfo and on the request's render page, and self-clearing within RequestTTL.

AVAILABILITY BOUND, stated honestly

Submit is permissionless, so the request tree is fillable. The per-claimant and per-desk caps bound ONE address and ONE desk, and are defeated by many addresses — that is the correct way to read a per-identity cap on a permissionless chain, and budgets' own corrected comment (finding Y1) is this portfolio's record of getting it wrong the other way.

What genuinely helps here, and does not help in budgets, is that a request has a MANDATORY expiry: RequestTTL is a compile-time constant, every request carries submittedAt + RequestTTL, and ExpireRequest is permissionless with the freed storage deposit refunded to the sweeping transaction. So the fill is bounded in DURATION as well as priced in gas and storage, and it drains itself. budgets' grants with expiresAt == 0 can never be reaped by anyone, which is strictly worse. The residual is real: for RequestTTL blocks a filled tree blocks NEW requests. Every desk, pool, approval, credit and claim keeps working, and no value is at risk.

THERE IS NO ADMIN

The fee rate, the fee collector, the TTL, every bound and every cap are compile-time constants. No address can change terms, pause the realm, touch a pool it did not fund, approve at a desk it was not appointed to, or move a request it did not file. The deployer has no privilege of any kind after deployment.

MONETARY INVARIANT (conservation)

Let H be the ugnot held at this realm's address, P the sum of all owner pools (tracked O(1) as totalPooled), L the ledger's liabilities (settled claimant credit plus the fee pot), and S >= 0 the out-of-band surplus:

Example
1H == P + L + S

Every transition moves value between exactly two terms inside one transaction. Fund raises H and P together (coinio.Receive is the receipt-guaranteed shape). WithdrawPool debits P before the identical amount leaves H. Approve moves the gross out of P and into L, split into the claimant's credit and the fee — H does not move at all, which is why Approve has no payout to fail. Claim and WithdrawFees debit L before their payout. Submit, Reject, Retract and ExpireRequest move nothing in any term. Any panic aborts the whole transaction; this realm never issues or removes coins.

ONLY GNOT IS ACCEPTED

Fund rejects any envelope that is not exactly one positive ugnot coin (coinio.Receive). Every other entrypoint rejects attached coins outright rather than converting them into sweepable surplus.

AUTHORIZATION

Every identity is derived from the crossing entrypoint's cur.Previous().Address(). No function takes a caller identity as a parameter, so funding another owner's pool, approving at another address's desk, retracting another claimant's request, or claiming another claimant's credit is impossible by construction. This is spendbook consumer contract item 2, closed structurally.

The clock is runtime.ChainHeight(), never an argument — spendbook consumer contract item 1. A caller who could choose `now` could roll the approval window at will, and could also expire a request out from under its claimant or keep an expired one alive.

STORAGE

A pool entry is paid for by the owner's own funding transaction; a desk record and its allowance by the owner's OpenDesk; a request record by the claimant's Submit. CloseDesk, ReapDesk, Approve, Reject, Retract and ExpireRequest each remove a record, and the chain refunds the freed storage deposit to the transaction that frees it — which is the standing incentive to call ExpireRequest or ReapDesk on somebody else's stale record.

Functions

AmendDesk

func AmendDesk(cur realm, id int64, perPeriod, total, expiresAt int64) bool
Ask AI Claude ChatGPT

AmendDesk changes a desk's terms. Owner only. The returned bool reports whether the new terms are in force NOW (a tighter-or-equal amendment) or queued for the next window boundary (a looser one) — spendbook's one-sided rule, and the distinction worth knowing.

periodLength is NOT a parameter. spendbook makes it immutable because moving it would move every future boundary, which is an enlargement vector wearing a different hat; this realm reads the desk's own periodLength and passes it unchanged, so changing it is not merely refused, it is unexpressible.

Amending does not touch pending requests. Their fee was snapshotted at Submit and their amount is fixed; what changes is whether the approver still has the authority to settle them, which Approvable reports.

A QUEUED EXPIRY EXTENSION CAN BE LOST, AND THE DESK BECOMES REAPABLE IN THE MEANTIME. A widening amendment is queued rather than applied, and spendbook surfaces a queued term only through its internal at() accessor — which IsExpired does NOT use: it reads the live Terms.ExpiresAt directly. So between queueing and the next approval, IsDeskExpired and ReapDesk still read the OLD expiry. If the old expiry passes with no Approve and no restated AmendDesk in between, ANYONE may ReapDesk the desk and the queued extension dies with it. Restating the same amendment while the old expiry is still in the future makes it permanent, because spendbook writes Pending back to Terms on a spend or on a later amendment; restating it after the old expiry is refused with "allowance has expired".

NO FUNDS ARE AT RISK and that is structural, not incidental: dropDesk moves no coins, and the claimant pools are keyed by CLAIMANT ADDRESS rather than by desk, so a reap strands open requests and leaves every accrued balance claimable. The root cause is in spendbook, which is already live and immutable, so the repair belongs to a future /p/ version and not to this realm. See AUDIT.md Y1 and DEPLOY_READINESS.md.

Params

Command

# WARNING: This command is running in an INSECURE mode.
# It is strongly recommended to use a hardware device for signing
# and avoid trusting any computer connected to the internet,
# as your private keys could be exposed.

gnokey maketx call -pkgpath "gno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/reimbursements" -func "AmendDesk" -args $'' -args $'' -args $'' -args $'' -gas-fee 1000000ugnot -gas-wanted 1_000_000_000 -send "" -chainid "onyx-1" -remote "https://rpc.onyx.testnets.gno.land" ADDRESSgnokey query -remote "https://rpc.onyx.testnets.gno.land" auth/accounts/ADDRESS
gnokey maketx call -pkgpath "gno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/reimbursements" -func "AmendDesk" -args $'' -args $'' -args $'' -args $'' -gas-fee 1000000ugnot -gas-wanted 1_000_000_000 -send "" -broadcast=false ADDRESS > call.tx
gnokey sign -tx-path call.tx -chainid "onyx-1" -account-number ACCOUNTNUMBER -account-sequence SEQUENCENUMBER ADDRESS
gnokey broadcast -remote "https://rpc.onyx.testnets.gno.land" call.tx
  

Approvable

func Approvable(id int64) int64
Ask AI Claude ChatGPT

Approvable is the HONEST figure for a desk, and the one both an approver and a prospective claimant should read: the lesser of what the desk authorizes and what the owner's pool holds. This distinction is the realm's own — spendbook bounds permission and says so, never solvency.

Param

Command

gnokey query vm/qeval -remote "https://rpc.onyx.testnets.gno.land" -data "gno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/reimbursements.Approvable()"

Result

ApprovalBlocker

func ApprovalBlocker(id int64) string
Ask AI Claude ChatGPT

ApprovalBlocker returns the empty string when the request could be approved right now by its desk's approver, and otherwise the single reason it could not. It is the view a UI wants before showing an approve button, and an approver wants before paying gas for a call that will abort.

The reasons are reported in the same order Approve checks them, so this view and that entrypoint can never disagree about WHICH reason applies. It deliberately does NOT report "you are not the approver": the caller of a view is not the caller of the approval, so this answers about the request and the desk, not about whoever is asking.

Param

Command

gnokey query vm/qeval -remote "https://rpc.onyx.testnets.gno.land" -data "gno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/reimbursements.ApprovalBlocker()"

Result

Approve

func Approve(cur realm, reqID int64) int64
Ask AI Claude ChatGPT

Approve settles a request. APPROVER ONLY: the approver is the calling address, never an argument. The claimant is credited net of the fee and claims separately, which is this portfolio's standard pull shape.

The checks fail in this order, and the order matters:

  1. the desk must still exist (a closed or reaped desk strands its requests, by design);
  2. the caller must be that desk's approver;
  3. the caller must not be the request's own claimant (no self-approval);
  4. the request must not have expired;
  5. the owner's pool must cover the GROSS amount;
  6. the desk's spendbook authority must permit the gross amount.

Solvency (5) is checked BEFORE the allowance is consumed (6), so an approval refused for insolvency leaves the desk's window untouched rather than burning capacity on an approval that did not happen. This is budgets' ordering, kept for the same reason.

Param

Command

# WARNING: This command is running in an INSECURE mode.
# It is strongly recommended to use a hardware device for signing
# and avoid trusting any computer connected to the internet,
# as your private keys could be exposed.

gnokey maketx call -pkgpath "gno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/reimbursements" -func "Approve" -args $'' -gas-fee 1000000ugnot -gas-wanted 1_000_000_000 -send "" -chainid "onyx-1" -remote "https://rpc.onyx.testnets.gno.land" ADDRESSgnokey query -remote "https://rpc.onyx.testnets.gno.land" auth/accounts/ADDRESS
gnokey maketx call -pkgpath "gno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/reimbursements" -func "Approve" -args $'' -gas-fee 1000000ugnot -gas-wanted 1_000_000_000 -send "" -broadcast=false ADDRESS > call.tx
gnokey sign -tx-path call.tx -chainid "onyx-1" -account-number ACCOUNTNUMBER -account-sequence SEQUENCENUMBER ADDRESS
gnokey broadcast -remote "https://rpc.onyx.testnets.gno.land" call.tx
  

Claim

func Claim(cur realm) int64
Ask AI Claude ChatGPT

Claim pays the caller's entire settled credit out. CLAIMANT ONLY: the account is the calling address. Credit from a desk that has since been closed, expired or reaped is still claimable — it was settled under a live authority and this realm does not revisit that.

Command

# WARNING: This command is running in an INSECURE mode.
# It is strongly recommended to use a hardware device for signing
# and avoid trusting any computer connected to the internet,
# as your private keys could be exposed.

gnokey maketx call -pkgpath "gno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/reimbursements" -func "Claim" -gas-fee 1000000ugnot -gas-wanted 1_000_000_000 -send "" -chainid "onyx-1" -remote "https://rpc.onyx.testnets.gno.land" ADDRESSgnokey query -remote "https://rpc.onyx.testnets.gno.land" auth/accounts/ADDRESS
gnokey maketx call -pkgpath "gno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/reimbursements" -func "Claim" -gas-fee 1000000ugnot -gas-wanted 1_000_000_000 -send "" -broadcast=false ADDRESS > call.tx
gnokey sign -tx-path call.tx -chainid "onyx-1" -account-number ACCOUNTNUMBER -account-sequence SEQUENCENUMBER ADDRESS
gnokey broadcast -remote "https://rpc.onyx.testnets.gno.land" call.tx
  

CloseDesk

func CloseDesk(cur realm, id int64)
Ask AI Claude ChatGPT

CloseDesk ends an approver's authority immediately. Owner only. The id is never reused, so a closed desk cannot be resurrected.

Closing does NOT claw back credit already approved — that is the claimant's and stays claimable. It does NOT remove requests filed at this desk either: see the package doc, "a closed desk leaves its requests un-approvable". The count of those is reported in the event so the owner learns what they just stranded.

Param

Command

# WARNING: This command is running in an INSECURE mode.
# It is strongly recommended to use a hardware device for signing
# and avoid trusting any computer connected to the internet,
# as your private keys could be exposed.

gnokey maketx call -pkgpath "gno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/reimbursements" -func "CloseDesk" -args $'' -gas-fee 1000000ugnot -gas-wanted 1_000_000_000 -send "" -chainid "onyx-1" -remote "https://rpc.onyx.testnets.gno.land" ADDRESSgnokey query -remote "https://rpc.onyx.testnets.gno.land" auth/accounts/ADDRESS
gnokey maketx call -pkgpath "gno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/reimbursements" -func "CloseDesk" -args $'' -gas-fee 1000000ugnot -gas-wanted 1_000_000_000 -send "" -broadcast=false ADDRESS > call.tx
gnokey sign -tx-path call.tx -chainid "onyx-1" -account-number ACCOUNTNUMBER -account-sequence SEQUENCENUMBER ADDRESS
gnokey broadcast -remote "https://rpc.onyx.testnets.gno.land" call.tx
  

CreditOf

func CreditOf(addr address) int64
Ask AI Claude ChatGPT

CreditOf returns a claimant's settled-but-unclaimed credit.

Param

Command

gnokey query vm/qeval -remote "https://rpc.onyx.testnets.gno.land" -data "gno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/reimbursements.CreditOf()"

Result

DeskLabel

func DeskLabel(id int64) string
Ask AI Claude ChatGPT

DeskLabel returns a desk's raw label (unsanitized: callers rendering it into markdown must sanitize, as this realm's Render does).

Param

Command

gnokey query vm/qeval -remote "https://rpc.onyx.testnets.gno.land" -data "gno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/reimbursements.DeskLabel()"

Result

DeskUsage

func DeskUsage(id int64) (approvedWindow, approvedTotal, windowIndex, approvals, rejections, pending int64)
Ask AI Claude ChatGPT

DeskUsage returns a desk's consumption AT THE CURRENT HEIGHT: what the window the chain is in right now has approved, the lifetime gross, that window's index, how many approvals there have been, how many rejections, and how many requests are pending at the desk.

The two window figures are computed rather than read straight off the record, and that is the whole point of windowAt below: a window that has rolled with no approval since leaves Allowance.WindowIndex naming a window the chain has already left, and Allowance.SpentWindow holding the previous window's spend.

Param

Command

gnokey query vm/qeval -remote "https://rpc.onyx.testnets.gno.land" -data "gno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/reimbursements.DeskUsage()"

Result

DesksOf

func DesksOf(addr address) int64
Ask AI Claude ChatGPT

DesksOf returns how many live desks an owner currently holds.

Param

Command

gnokey query vm/qeval -remote "https://rpc.onyx.testnets.gno.land" -data "gno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/reimbursements.DesksOf()"

Result

ExpireRequest

func ExpireRequest(cur realm, reqID int64)
Ask AI Claude ChatGPT

ExpireRequest removes a request past its expiry, freeing its slot and its storage. ANYONE may call it, and the reasoning matches ReapDesk's: an expired request can never be approved, so removing it takes nothing from the claimant and grants nothing to the caller. The chain refunds the freed storage deposit to the expiring transaction, which is the standing incentive and the mechanism that drains the queue.

Param

Command

# WARNING: This command is running in an INSECURE mode.
# It is strongly recommended to use a hardware device for signing
# and avoid trusting any computer connected to the internet,
# as your private keys could be exposed.

gnokey maketx call -pkgpath "gno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/reimbursements" -func "ExpireRequest" -args $'' -gas-fee 1000000ugnot -gas-wanted 1_000_000_000 -send "" -chainid "onyx-1" -remote "https://rpc.onyx.testnets.gno.land" ADDRESSgnokey query -remote "https://rpc.onyx.testnets.gno.land" auth/accounts/ADDRESS
gnokey maketx call -pkgpath "gno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/reimbursements" -func "ExpireRequest" -args $'' -gas-fee 1000000ugnot -gas-wanted 1_000_000_000 -send "" -broadcast=false ADDRESS > call.tx
gnokey sign -tx-path call.tx -chainid "onyx-1" -account-number ACCOUNTNUMBER -account-sequence SEQUENCENUMBER ADDRESS
gnokey broadcast -remote "https://rpc.onyx.testnets.gno.land" call.tx
  

FeesAccrued

func FeesAccrued() int64
Ask AI Claude ChatGPT

FeesAccrued returns the fee pot: charged, not yet withdrawn.

Command

gnokey query vm/qeval -remote "https://rpc.onyx.testnets.gno.land" -data "gno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/reimbursements.FeesAccrued()"

Result

Fund

func Fund(cur realm) int64
Ask AI Claude ChatGPT

Fund adds the attached coins to the caller's own pool. Direct EOA calls with -send only (the receipt-guaranteed shape); exactly one positive ugnot coin, at least MinFunding. Anyone may fund; funding is what makes an address an owner.

Command

# WARNING: This command is running in an INSECURE mode.
# It is strongly recommended to use a hardware device for signing
# and avoid trusting any computer connected to the internet,
# as your private keys could be exposed.

gnokey maketx call -pkgpath "gno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/reimbursements" -func "Fund" -gas-fee 1000000ugnot -gas-wanted 1_000_000_000 -send "" -chainid "onyx-1" -remote "https://rpc.onyx.testnets.gno.land" ADDRESSgnokey query -remote "https://rpc.onyx.testnets.gno.land" auth/accounts/ADDRESS
gnokey maketx call -pkgpath "gno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/reimbursements" -func "Fund" -gas-fee 1000000ugnot -gas-wanted 1_000_000_000 -send "" -broadcast=false ADDRESS > call.tx
gnokey sign -tx-path call.tx -chainid "onyx-1" -account-number ACCOUNTNUMBER -account-sequence SEQUENCENUMBER ADDRESS
gnokey broadcast -remote "https://rpc.onyx.testnets.gno.land" call.tx
  

Height

func Height() int64
Ask AI Claude ChatGPT

Height returns the current chain height: the clock every window, expiry and TTL is measured against, and the one no caller can choose.

Command

gnokey query vm/qeval -remote "https://rpc.onyx.testnets.gno.land" -data "gno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/reimbursements.Height()"

Result

Held

func Held() int64
Ask AI Claude ChatGPT

Held returns H: the ugnot actually at this realm's address.

Command

gnokey query vm/qeval -remote "https://rpc.onyx.testnets.gno.land" -data "gno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/reimbursements.Held()"

Result

IsDeskExpired

func IsDeskExpired(id int64) bool
Ask AI Claude ChatGPT

IsDeskExpired reports whether a desk's authority has lapsed, which is also the condition under which anyone may ReapDesk it.

It reads the LIVE expiry only. A queued expiry extension reported by PendingTerms is NOT considered here, so this can read true while an amendment widening the window is still queued — see AmendDesk for the full disclosure and why no funds are at risk.

Param

Command

gnokey query vm/qeval -remote "https://rpc.onyx.testnets.gno.land" -data "gno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/reimbursements.IsDeskExpired()"

Result

IsRequestExpired

func IsRequestExpired(id int64) bool
Ask AI Claude ChatGPT

IsRequestExpired reports whether a request is past its expiry, which is both the condition under which Approve refuses and the condition under which anyone may ExpireRequest it.

Param

Command

gnokey query vm/qeval -remote "https://rpc.onyx.testnets.gno.land" -data "gno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/reimbursements.IsRequestExpired()"

Result

Liabilities

func Liabilities() int64
Ask AI Claude ChatGPT

Liabilities returns P + L — everything this realm owes. A pending request is not part of it.

Command

gnokey query vm/qeval -remote "https://rpc.onyx.testnets.gno.land" -data "gno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/reimbursements.Liabilities()"

Result

LiveDesks

func LiveDesks() int64
Ask AI Claude ChatGPT

LiveDesks returns how many desks are currently live, from the primitive's own count.

Command

gnokey query vm/qeval -remote "https://rpc.onyx.testnets.gno.land" -data "gno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/reimbursements.LiveDesks()"

Result

LiveRequests

func LiveRequests() int64
Ask AI Claude ChatGPT

LiveRequests returns how many requests are currently pending. A pending request may still be unapprovable — see ApprovalBlocker.

Command

gnokey query vm/qeval -remote "https://rpc.onyx.testnets.gno.land" -data "gno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/reimbursements.LiveRequests()"

Result

NumDesks

func NumDesks() int64
Ask AI Claude ChatGPT

NumDesks returns how many desks have ever been opened. Ids are never reused, so this only grows.

Command

gnokey query vm/qeval -remote "https://rpc.onyx.testnets.gno.land" -data "gno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/reimbursements.NumDesks()"

Result

NumRequests

func NumRequests() int64
Ask AI Claude ChatGPT

NumRequests returns how many requests have ever been filed. Ids are never reused, so this only grows.

Command

gnokey query vm/qeval -remote "https://rpc.onyx.testnets.gno.land" -data "gno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/reimbursements.NumRequests()"

Result

OpenDesk

func OpenDesk(cur realm, approver address, label string, perPeriod, periodLength, total, expiresAt int64) int64
Ask AI Claude ChatGPT

OpenDesk appoints an approver with a bounded authority over the caller's pool and returns the desk id. The caller becomes the desk's owner and must already have a funded pool — not because the desk reserves anything (it does not), but because a desk over an unfunded pool is an invitation to claimants to file requests nothing can settle, and this realm declines to record one.

Terms, all in the chain's own units:

Example
1perPeriod    the gross the approver may approve per window, at least
2             MinPerPeriod. Required.
3periodLength blocks per window. 0 means ONE LIFETIME WINDOW that never
4             refills; otherwise at least MinPeriodBlocks.
5total        lifetime cap across every window. 0 means unlimited.
6expiresAt    absolute block height at which the approver's authority
7             ends. 0 means no expiry.

Every bound above except the two realm minimums is validated and enforced by spendbook, and an invalid combination surfaces as that package's own sentinel error.

Params

Command

# WARNING: This command is running in an INSECURE mode.
# It is strongly recommended to use a hardware device for signing
# and avoid trusting any computer connected to the internet,
# as your private keys could be exposed.

gnokey maketx call -pkgpath "gno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/reimbursements" -func "OpenDesk" -args $'' -args $'' -args $'' -args $'' -args $'' -args $'' -gas-fee 1000000ugnot -gas-wanted 1_000_000_000 -send "" -chainid "onyx-1" -remote "https://rpc.onyx.testnets.gno.land" ADDRESSgnokey query -remote "https://rpc.onyx.testnets.gno.land" auth/accounts/ADDRESS
gnokey maketx call -pkgpath "gno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/reimbursements" -func "OpenDesk" -args $'' -args $'' -args $'' -args $'' -args $'' -args $'' -gas-fee 1000000ugnot -gas-wanted 1_000_000_000 -send "" -broadcast=false ADDRESS > call.tx
gnokey sign -tx-path call.tx -chainid "onyx-1" -account-number ACCOUNTNUMBER -account-sequence SEQUENCENUMBER ADDRESS
gnokey broadcast -remote "https://rpc.onyx.testnets.gno.land" call.tx
  

OpenRequestsAt

func OpenRequestsAt(deskID int64) int64
Ask AI Claude ChatGPT

OpenRequestsAt returns how many pending requests a desk has.

Param

Command

gnokey query vm/qeval -remote "https://rpc.onyx.testnets.gno.land" -data "gno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/reimbursements.OpenRequestsAt()"

Result

OpenRequestsOf

func OpenRequestsOf(addr address) int64
Ask AI Claude ChatGPT

OpenRequestsOf returns how many pending requests a claimant has.

Param

Command

gnokey query vm/qeval -remote "https://rpc.onyx.testnets.gno.land" -data "gno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/reimbursements.OpenRequestsOf()"

Result

PendingTerms

func PendingTerms(id int64) (perPeriod, total, expiresAt int64, pending bool)
Ask AI Claude ChatGPT

PendingTerms returns a queued loosening amendment on a desk and whether there is one. An amendment is queued only when it would widen the live window, and it takes effect at the next window boundary.

Param

Command

gnokey query vm/qeval -remote "https://rpc.onyx.testnets.gno.land" -data "gno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/reimbursements.PendingTerms()"

Result

PoolOf

func PoolOf(addr address) int64
Ask AI Claude ChatGPT

PoolOf returns an owner's unspent pool.

Param

Command

gnokey query vm/qeval -remote "https://rpc.onyx.testnets.gno.land" -data "gno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/reimbursements.PoolOf()"

Result

ReapDesk

func ReapDesk(cur realm, id int64)
Ask AI Claude ChatGPT

ReapDesk removes a desk whose authority has EXPIRED, freeing its slot and its storage. Anyone may call it, and the reasoning is spendbook's own: an expired allowance can never authorize another approval, so removing it takes nothing from the owner and grants nothing to the caller. The chain refunds the freed storage deposit to the reaping transaction, which is the standing incentive.

A desk with no expiry can never be reaped; only its owner can close it.

Param

Command

# WARNING: This command is running in an INSECURE mode.
# It is strongly recommended to use a hardware device for signing
# and avoid trusting any computer connected to the internet,
# as your private keys could be exposed.

gnokey maketx call -pkgpath "gno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/reimbursements" -func "ReapDesk" -args $'' -gas-fee 1000000ugnot -gas-wanted 1_000_000_000 -send "" -chainid "onyx-1" -remote "https://rpc.onyx.testnets.gno.land" ADDRESSgnokey query -remote "https://rpc.onyx.testnets.gno.land" auth/accounts/ADDRESS
gnokey maketx call -pkgpath "gno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/reimbursements" -func "ReapDesk" -args $'' -gas-fee 1000000ugnot -gas-wanted 1_000_000_000 -send "" -broadcast=false ADDRESS > call.tx
gnokey sign -tx-path call.tx -chainid "onyx-1" -account-number ACCOUNTNUMBER -account-sequence SEQUENCENUMBER ADDRESS
gnokey broadcast -remote "https://rpc.onyx.testnets.gno.land" call.tx
  

Reject

func Reject(cur realm, reqID int64, reason string)
Ask AI Claude ChatGPT

Reject closes a request without settling it. APPROVER ONLY. Nothing moves in any term of the invariant, and no authority is consumed — a rejection costs the desk's window nothing, which is deliberate: an approver must be able to say no as often as necessary.

Rejecting an EXPIRED request is allowed. The alternative would force an approver who wants the record to carry a reason to race the expiry, and the reason is the useful artifact: ExpireRequest emits no explanation.

Params

Command

# WARNING: This command is running in an INSECURE mode.
# It is strongly recommended to use a hardware device for signing
# and avoid trusting any computer connected to the internet,
# as your private keys could be exposed.

gnokey maketx call -pkgpath "gno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/reimbursements" -func "Reject" -args $'' -args $'' -gas-fee 1000000ugnot -gas-wanted 1_000_000_000 -send "" -chainid "onyx-1" -remote "https://rpc.onyx.testnets.gno.land" ADDRESSgnokey query -remote "https://rpc.onyx.testnets.gno.land" auth/accounts/ADDRESS
gnokey maketx call -pkgpath "gno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/reimbursements" -func "Reject" -args $'' -args $'' -gas-fee 1000000ugnot -gas-wanted 1_000_000_000 -send "" -broadcast=false ADDRESS > call.tx
gnokey sign -tx-path call.tx -chainid "onyx-1" -account-number ACCOUNTNUMBER -account-sequence SEQUENCENUMBER ADDRESS
gnokey broadcast -remote "https://rpc.onyx.testnets.gno.land" call.tx
  

Remaining

func Remaining(id int64) int64
Ask AI Claude ChatGPT

Remaining is the AUTHORITY figure for a desk: what its terms permit the approver to approve right now, ignoring whether the owner's pool can cover it.

Param

Command

gnokey query vm/qeval -remote "https://rpc.onyx.testnets.gno.land" -data "gno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/reimbursements.Remaining()"

Result

Render

func Render(path string) string
Ask AI Claude ChatGPT

Render shows the realm at "", a desk page at "desk/<id>" and a request page at "request/<id>". Labels and memos are free text and pass through the ecosystem sanitizer before hitting markdown.

Param

Command

gnokey query vm/qeval -remote "https://rpc.onyx.testnets.gno.land" -data "gno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/reimbursements.Render()"

Result

RequestMemo

func RequestMemo(id int64) string
Ask AI Claude ChatGPT

RequestMemo returns a request's raw memo (unsanitized: callers rendering it into markdown must sanitize, as this realm's Render does).

Param

Command

gnokey query vm/qeval -remote "https://rpc.onyx.testnets.gno.land" -data "gno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/reimbursements.RequestMemo()"

Result

Retract

func Retract(cur realm, reqID int64)
Ask AI Claude ChatGPT

Retract removes the caller's own pending request. CLAIMANT ONLY. Nothing moves.

Named Retract rather than Withdraw on purpose: every Withdraw* in this portfolio moves money, and this moves none. A claimant reading a function list should not have to open the source to learn which.

Param

Command

# WARNING: This command is running in an INSECURE mode.
# It is strongly recommended to use a hardware device for signing
# and avoid trusting any computer connected to the internet,
# as your private keys could be exposed.

gnokey maketx call -pkgpath "gno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/reimbursements" -func "Retract" -args $'' -gas-fee 1000000ugnot -gas-wanted 1_000_000_000 -send "" -chainid "onyx-1" -remote "https://rpc.onyx.testnets.gno.land" ADDRESSgnokey query -remote "https://rpc.onyx.testnets.gno.land" auth/accounts/ADDRESS
gnokey maketx call -pkgpath "gno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/reimbursements" -func "Retract" -args $'' -gas-fee 1000000ugnot -gas-wanted 1_000_000_000 -send "" -broadcast=false ADDRESS > call.tx
gnokey sign -tx-path call.tx -chainid "onyx-1" -account-number ACCOUNTNUMBER -account-sequence SEQUENCENUMBER ADDRESS
gnokey broadcast -remote "https://rpc.onyx.testnets.gno.land" call.tx
  

Submit

func Submit(cur realm, deskID int64, amount int64, memo string) int64
Ask AI Claude ChatGPT

Submit files a reimbursement request against a desk and returns the request id. ANYONE may submit: that is the point of the realm — the party who spent the money asks, and does not need to be a signer, a delegate, or known to the desk in advance.

Nothing is reserved and nothing moves. The amount and the fee are fixed here (the fee is snapshotted from the desk, so a later AmendDesk cannot change the terms of a request already filed), and the request expires at submittedAt + RequestTTL.

Submitting against a desk whose approver is the submitter is permitted and useless: Approve refuses self-approval, so such a request can only be rejected, retracted or expired. It is not refused here because an approver may legitimately submit at a desk they do not approve, and a check at Submit would have to guess which desk the claimant meant.

Params

Command

# WARNING: This command is running in an INSECURE mode.
# It is strongly recommended to use a hardware device for signing
# and avoid trusting any computer connected to the internet,
# as your private keys could be exposed.

gnokey maketx call -pkgpath "gno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/reimbursements" -func "Submit" -args $'' -args $'' -args $'' -gas-fee 1000000ugnot -gas-wanted 1_000_000_000 -send "" -chainid "onyx-1" -remote "https://rpc.onyx.testnets.gno.land" ADDRESSgnokey query -remote "https://rpc.onyx.testnets.gno.land" auth/accounts/ADDRESS
gnokey maketx call -pkgpath "gno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/reimbursements" -func "Submit" -args $'' -args $'' -args $'' -gas-fee 1000000ugnot -gas-wanted 1_000_000_000 -send "" -broadcast=false ADDRESS > call.tx
gnokey sign -tx-path call.tx -chainid "onyx-1" -account-number ACCOUNTNUMBER -account-sequence SEQUENCENUMBER ADDRESS
gnokey broadcast -remote "https://rpc.onyx.testnets.gno.land" call.tx
  

Surplus

func Surplus() int64
Ask AI Claude ChatGPT

Surplus returns H - (P + L) — out-of-band coins, sweepable.

Command

gnokey query vm/qeval -remote "https://rpc.onyx.testnets.gno.land" -data "gno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/reimbursements.Surplus()"

Result

SweepSurplus

func SweepSurplus(cur realm, denom string) int64
Ask AI Claude ChatGPT

SweepSurplus sends out-of-band coins to the FeeCollector: for the pool denom, everything above tracked liabilities; for any foreign denom, the full balance. Owner pools, claimant credit and the fee pot are untouchable by construction (coinio.Sweep refuses to dip below the reserve). Anyone may call it.

With nothing out of band this ABORTS ("coinio: no surplus to sweep for <denom>") rather than returning 0. That is the primitive's choice and the right one: a sweep is a transfer, and a transfer of nothing that reports success is how a caller comes to believe a balance was moved.

Param

Command

# WARNING: This command is running in an INSECURE mode.
# It is strongly recommended to use a hardware device for signing
# and avoid trusting any computer connected to the internet,
# as your private keys could be exposed.

gnokey maketx call -pkgpath "gno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/reimbursements" -func "SweepSurplus" -args $'' -gas-fee 1000000ugnot -gas-wanted 1_000_000_000 -send "" -chainid "onyx-1" -remote "https://rpc.onyx.testnets.gno.land" ADDRESSgnokey query -remote "https://rpc.onyx.testnets.gno.land" auth/accounts/ADDRESS
gnokey maketx call -pkgpath "gno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/reimbursements" -func "SweepSurplus" -args $'' -gas-fee 1000000ugnot -gas-wanted 1_000_000_000 -send "" -broadcast=false ADDRESS > call.tx
gnokey sign -tx-path call.tx -chainid "onyx-1" -account-number ACCOUNTNUMBER -account-sequence SEQUENCENUMBER ADDRESS
gnokey broadcast -remote "https://rpc.onyx.testnets.gno.land" call.tx
  

TotalPooled

func TotalPooled() int64
Ask AI Claude ChatGPT

TotalPooled returns the P term: unspent owner funds. Pending requests are NOT included; they are not liabilities.

Command

gnokey query vm/qeval -remote "https://rpc.onyx.testnets.gno.land" -data "gno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/reimbursements.TotalPooled()"

Result

UnclaimedCredit

func UnclaimedCredit() int64
Ask AI Claude ChatGPT

UnclaimedCredit returns the claimants' share of the L term: approved and not yet claimed.

Command

gnokey query vm/qeval -remote "https://rpc.onyx.testnets.gno.land" -data "gno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/reimbursements.UnclaimedCredit()"

Result

WithdrawFees

func WithdrawFees(cur realm) int64
Ask AI Claude ChatGPT

WithdrawFees pays the entire accrued fee pot to the compile-time FeeCollector. Anyone may call it: the destination is fixed, so there is nothing for a caller to steer.

Command

# WARNING: This command is running in an INSECURE mode.
# It is strongly recommended to use a hardware device for signing
# and avoid trusting any computer connected to the internet,
# as your private keys could be exposed.

gnokey maketx call -pkgpath "gno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/reimbursements" -func "WithdrawFees" -gas-fee 1000000ugnot -gas-wanted 1_000_000_000 -send "" -chainid "onyx-1" -remote "https://rpc.onyx.testnets.gno.land" ADDRESSgnokey query -remote "https://rpc.onyx.testnets.gno.land" auth/accounts/ADDRESS
gnokey maketx call -pkgpath "gno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/reimbursements" -func "WithdrawFees" -gas-fee 1000000ugnot -gas-wanted 1_000_000_000 -send "" -broadcast=false ADDRESS > call.tx
gnokey sign -tx-path call.tx -chainid "onyx-1" -account-number ACCOUNTNUMBER -account-sequence SEQUENCENUMBER ADDRESS
gnokey broadcast -remote "https://rpc.onyx.testnets.gno.land" call.tx
  

WithdrawPool

func WithdrawPool(cur realm, amount int64) int64
Ask AI Claude ChatGPT

WithdrawPool returns part of the caller's UNSPENT pool and reports the pool REMAINING afterwards.

Unlike budgets, this is not a hazard to a counterparty, and the reason is the divergence in the package doc: an approved reimbursement has already left the pool and sits in the ledger as the claimant's. What an owner can still do is empty the pool under a live desk, so that the approver's next Approve fails on solvency and pending requests cannot be settled. That is the owner declining to spend their own money, which is theirs to decline; CloseDesk is the clean way to end the relationship.

Param

Command

# WARNING: This command is running in an INSECURE mode.
# It is strongly recommended to use a hardware device for signing
# and avoid trusting any computer connected to the internet,
# as your private keys could be exposed.

gnokey maketx call -pkgpath "gno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/reimbursements" -func "WithdrawPool" -args $'' -gas-fee 1000000ugnot -gas-wanted 1_000_000_000 -send "" -chainid "onyx-1" -remote "https://rpc.onyx.testnets.gno.land" ADDRESSgnokey query -remote "https://rpc.onyx.testnets.gno.land" auth/accounts/ADDRESS
gnokey maketx call -pkgpath "gno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/reimbursements" -func "WithdrawPool" -args $'' -gas-fee 1000000ugnot -gas-wanted 1_000_000_000 -send "" -broadcast=false ADDRESS > call.tx
gnokey sign -tx-path call.tx -chainid "onyx-1" -account-number ACCOUNTNUMBER -account-sequence SEQUENCENUMBER ADDRESS
gnokey broadcast -remote "https://rpc.onyx.testnets.gno.land" call.tx
  

WithdrawPoolAll

func WithdrawPoolAll(cur realm) int64
Ask AI Claude ChatGPT

WithdrawPoolAll returns the caller's entire unspent pool and reports the amount WITHDRAWN.

The return values of the two withdraw entrypoints are deliberately asymmetric, which is worth naming rather than letting a caller discover: each returns the figure its caller does not already have. WithdrawPool was told the amount and wants to know what is left; WithdrawPoolAll knows what is left (nothing) and wants to know what it got. Returning the remainder here would hand every caller a constant 0.

Command

# WARNING: This command is running in an INSECURE mode.
# It is strongly recommended to use a hardware device for signing
# and avoid trusting any computer connected to the internet,
# as your private keys could be exposed.

gnokey maketx call -pkgpath "gno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/reimbursements" -func "WithdrawPoolAll" -gas-fee 1000000ugnot -gas-wanted 1_000_000_000 -send "" -chainid "onyx-1" -remote "https://rpc.onyx.testnets.gno.land" ADDRESSgnokey query -remote "https://rpc.onyx.testnets.gno.land" auth/accounts/ADDRESS
gnokey maketx call -pkgpath "gno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/reimbursements" -func "WithdrawPoolAll" -gas-fee 1000000ugnot -gas-wanted 1_000_000_000 -send "" -broadcast=false ADDRESS > call.tx
gnokey sign -tx-path call.tx -chainid "onyx-1" -account-number ACCOUNTNUMBER -account-sequence SEQUENCENUMBER ADDRESS
gnokey broadcast -remote "https://rpc.onyx.testnets.gno.land" call.tx