rtClient.commands
The one command surface - submit a state-changing intent, get an acceptance back.
rtClient.commands.submit(intent) is the single place a client dispatches a state change
to the chain. It validates the intent (a bad input rejects synchronously, before any
broadcast), signs and broadcasts on the resolved auth path - the Privy sign route or the
user's own wallet via BYOW - and guarantees a PendingTransaction is registered on
both paths.
The result is an acceptance, never the entity. Send a command; render a query. The SDK never polls for confirmation - the pending-aware read model surfaces the entity when the chain does.
rtClient.commands.submit(intent)
CommandIntent is a discriminated union on kind:
| Intent | What it does |
|---|---|
mint-edition | Collect an edition of a product (optionally with the feedback capability's note) |
sentiment-edition | Collect with a sentiment reading |
submit-bracket | Submit bracket picks |
transfer-edition | Transfer an owned edition to another address |
burn-edition | Burn an owned edition |
validate-ticket | Validate a ticket at the door |
game-action | One action on a game lobby: join, leave, start, move, claim, claim-draw, use-bomb. See rtClient.games |
bracket-action | One action on a tournament: lock, unlock, enter-results, clear-result, play-in-result, clear-play-in, finalize-scores, claim-prize, withdraw-pool. See rtClient.brackets |
Every intent carries the target, the signer address, the network, and a CommandAuth
describing the auth path: { method: "privy", token } or { method: "wallet" }. The React hook
useCommand(rtClient, { getPrivyToken }) from @rising-tide/ui/react fills auth in for you. CommandResult is either
{ accepted: true, txId, correlationId } or { accepted: false, reason, code? } -
branch on code first (it is the server's RisingTideError.code, e.g.
APP_ACCESS_REQUIRED) and fall back to reason for display.
const result = await rtClient.commands.submit({
kind: "mint-edition",
page: product,
ownerAddress: user.stxAddress,
currency: "sBTC",
network: "testnet",
auth: { method: "privy", token: await getAccessToken() },
});
if (!result.accepted) {
if (result.code === "APP_ACCESS_REQUIRED") showLockedState();
else toast.error(result.reason);
return;
}
// Broadcast accepted - close the flow. The read model shows the edition when it confirms.
closeOnBroadcast(result.txId);Client flows close on broadcast: no client-side chain polling, ever. The server and the chainhook own confirmation.