InstructionCatalogue

The protocol's eleven built-in instructions with availability READ off the live deployment — where "we could not look" and "this deployment cannot serve it" stay two different answers.

import { InstructionCatalogue } from '@flarekit-dev/react-ui'

InstructionCatalogue is capability discovery, not a menu. The rows are the eleven instructions the Smart Accounts controller can dispatch — the protocol's vocabulary — and each row's availability is read off the deployment in front of you rather than declared here.

Four availability answers, and the difference between the last two is the whole point:

  • Available — this deployment can serve it.
  • Superseded — the protocol moved on. The three legacy collateral-reservation commands (0x00, 0x10, 0x20) are redirected to FAssets minting by the deployment's own documentation, which the kit already drives at MintFXRP. They are catalogued for completeness and are never composable.
  • Not served here — the read succeeded and the deployment registers no vault of the type the instruction needs. A claim about the deployment.
  • Unknown — the state needed to decide could not be read. Not a claim about anything.

Collapsing unknown into Not served here would tell someone their deployment lacks a vault when in truth an RPC call failed. Collapsing superseded into either would blame the deployment for a protocol decision.

Live#

The preview runs the gallery's own states. The Coston2 rows are the deployment read live on 2026-08-13: eight available, three superseded, and every fee the controller's own 1000 drops. The mainnet rows are the same read against Flare mainnet, where four ids — 0x00, 0x02, 0x10 and 0x20 — charge 950000 drops against a 500000 default, which is exactly why a fee is never substituted.

mock kit
Coston2Mock · the 2026-08-13 Coston2 runs
Instructions this deployment can serve
InstructionValue fieldFeeAvailability
0x00 FXRP · collateralReservationReserves FAsset collateral with an agent vault, the first half of the legacy minting flow.Superseded: the deployment directs minting to FAssets direct minting, which the kit already drives. This command is catalogued for completeness and is never composable.Agent vault ids 1lots1000 dropsSuperseded
0x01 FXRP · transferTransfers FAsset from the personal account to an EVM recipient carried in the reference.drops1000 dropsAvailable
0x02 FXRP · redeemRedeems whole FAsset lots back to native XRP, paying the executor from the dispatch value.lots1000 dropsAvailable
0x10 Firelight · collateralReservationAndDepositReserves collateral and deposits the minted FAsset into a Firelight vault, in one command.Superseded: the deployment directs minting to FAssets direct minting, which the kit already drives. This command is catalogued for completeness and is never composable.Controller vault ids 1Agent vault ids 1lots1000 dropsSuperseded
0x11 Firelight · depositDeposits FAsset from the personal account into a Firelight vault, issuing shares to it.Controller vault ids 1drops1000 dropsAvailable
0x12 Firelight · redeemRedeems Firelight vault shares held by the personal account.Controller vault ids 1shares1000 dropsAvailable
0x13 Firelight · claimWithdrawClaims a matured Firelight withdrawal for the given period index.Controller vault ids 1withdrawal period1000 dropsAvailable
0x20 Upshift · collateralReservationAndDepositReserves collateral and deposits the minted FAsset into an Upshift vault, in one command.Superseded: the deployment directs minting to FAssets direct minting, which the kit already drives. This command is catalogued for completeness and is never composable.Controller vault ids 4, 2, 3Agent vault ids 1lots1000 dropsSuperseded
0x21 Upshift · depositDeposits FAsset from the personal account into an Upshift vault, issuing shares to it.Controller vault ids 4, 2, 3drops1000 dropsAvailable
0x22 Upshift · requestRedeemRequests redemption of Upshift vault shares — a request, not an instant exit.Controller vault ids 4, 2, 3shares1000 dropsAvailable
0x23 Upshift · claimClaims a matured Upshift redemption for the given yyyymmdd date.Controller vault ids 4, 2, 3claim date (yyyymmdd)1000 dropsAvailable
These vault ids are the controller’s own
Vault ids come from the deployed controller, not from the kit’s vault registry. On this network the two namespaces disagree, so an id taken from the wrong one names a different vault.

Usage#

The catalogue is derived from the deployment read useSmartAccount already performs, so there is no second fetch. Hand the rows straight through.

import { smartAccountsFor } from '@flarekit-dev/contracts'
import { useSmartAccount } from '@flarekit-dev/react'
import { InstructionCatalogue } from '@flarekit-dev/react-ui'
import '@flarekit-dev/react-ui/styles.css'

export function Catalogue({ xrplOwner, publicClient, onSelect }) {
  const { catalogue, loading } = useSmartAccount({
    deployment: smartAccountsFor('coston2'),
    xrplOwner,
    publicClient, // keyless throughout: nothing here signs
  })

  return (
    <InstructionCatalogue
      rows={catalogue}
      loading={loading}
      networkLabel="Coston2"
      onSelect={onSelect}
    />
  )
}

Props#

PropTypeDefaultDescription
rowsreadonly InstructionRow[]Always the full vocabulary, from `buildInstructionCatalogue`. Omitted entirely means no read has been attempted yet, which the table states in words rather than rendering as an empty deployment.
loadingbooleanfalseTrue while the deployment read is in flight. Skeleton rows appear only when there are no rows yet, so a refresh never blanks a catalogue already on screen.
networkLabelstringThe network the rows were read from, shown above the table. Network is configuration, so this is a label, not a switch.
mockLabelstringThe mock-mode label, shown as a chip beside the network. Present only when the host is in mock mode; never a fallback.
onSelect(instructionId: number) => voidCalled with the instruction id when a row is chosen. Offered ONLY for rows the deployment can actually serve — superseded, unavailable and unknown rows render as text, so the table cannot hand a composer an instruction that could not dispatch. Omit it and every row is text.
theme'light' | 'dark'Overrides the inherited theme. Normally left unset — the table follows data-theme.
classNamestringExtra class on the outer element, so a host layout can place the table.

What it renders#

Four columns — instruction, value field, fee, availability — and the sentences a table cell cannot hold.

The instruction cell carries the id as the byte that actually travels (0x11, always two digits), the controller's own action name under its instruction type, a sentence describing what the personal account would do, and, where the instruction targets one, the vault ids this controller registers.

The value field column names what the reference's 80-bit value counts, because the same field means five different things across the eleven rows: drops, lots, shares, a Firelight withdrawal period, or an Upshift claim date (yyyymmdd). A period index and a date are identifiers, not quantities, and rendering them as bare numbers in a fee-shaped column would make 20260813 look like an amount.

The fee is the controller's own getInstructionFee(id) in drops. An unread fee is . It is never the default: on Flare mainnet four ids charge 950000 against a 500000 default, so a substituted number would quote a payment 450000 drops short of what the controller requires — with the XRP already gone.

Below the table sit the notes that belong to the whole table rather than to a row: that vault ids come from the controller's namespace and not from the kit's own vault registry (the two disagree on these networks, so an id taken from the wrong one names a different vault), the one reason every row shares when they all share one, and a statement that unknown rows are undetermined rather than unavailable.

The list is never empty and never filtered down to the composable rows. An instruction hidden because this deployment cannot serve it would read as an instruction the protocol does not have.

States#

Every state in the switcher above is imported from packages/react-ui/gallery/, one source of truth for both the gallery and these docs:

  • coston2 — the live deployment: eight available, three superseded, every fee the controller's own 1000 drops, and the Firelight and Upshift vault ids it registers.
  • mainnet — the read lens, showing the fee divergence the no-fallback rule exists for: 950000 drops on 0x00, 0x02, 0x10 and 0x20 against a 500000 default on the rest.
  • unknown — the controller could not be read. Every row is Unknown, the vocabulary is still listed, every fee is , and nothing is claimed about the deployment. The reason is stated once beneath the table rather than eleven times inside it.
  • not-served — no observed deployment produces this, because both live networks register vaults of both types. It is driven from a controller with an empty vault registry, because a state has to be visible to be checked, and the gallery case says so on its own label.
  • loading — the deployment read is in flight. Skeleton rows; neither an empty catalogue nor a failure is claimed yet.

Mock to live#

buildInstructionCatalogue(settings) is the only thing that builds a row, and the preview above runs it over the settings the live deployments returned. Going live means handing it settings your own client read:

// From this…
const rows = buildInstructionCatalogue(OBSERVED_SETTINGS)

// …to this. The component does not change.
const { catalogue } = useSmartAccount({ deployment, xrplOwner, publicClient })

What it will not do#

It will not quote the default fee for an instruction whose own fee did not read, and it will not render an unread fee as 0. It will not hide a row it cannot serve, offer a superseded or unknown row as selectable, or report a failed read as a deployment that lacks a vault. It renders no availability it did not get from the deployment.