Rising Tide Developers
SDKCore

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:

IntentWhat it does
mint-editionCollect an edition of a product (optionally with the feedback capability's note)
sentiment-editionCollect with a sentiment reading
submit-bracketSubmit bracket picks
transfer-editionTransfer an owned edition to another address
burn-editionBurn an owned edition
validate-ticketValidate a ticket at the door
game-actionOne action on a game lobby: join, leave, start, move, claim, claim-draw, use-bomb. See rtClient.games
bracket-actionOne 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.