Skip to main content
You have a live simple-token contract from the previous chapter. Now you’ll call it — both read-only (view) and state-changing (the build-and-sign pattern from Transfer between accounts). Two modalities, full coverage.
Prerequisites · Deploy from ABI done. $CONTRACT, $ROOT_COMPONENT_ID, and $HOLDER_COMPONENT_ID are set, plus the ABIs at $ARTIFACTS/simple_token_*.abi.json. Alice’s holder was initialized with a wallet balance of 12 in the Adding Functionality chapter.

Running against local or DevNet

Pick the tab for the environment you’re targeting and paste once. The commands further down the lesson use $SERVER_URL and (on DevNet) the persisted auth header, so they don’t need per-environment edits.
Make sure a local validator is running (gen service validator local --embedded-config in another terminal), then:
export SERVER_URL="http://127.0.0.1:30001"

Reading state with view

Reads on the Grid are free and don’t touch the activation pipeline. They go to any RPC node, return immediately, and have no on-chain footprint. simple-token’s holder exposes a get_balance() view method (added in Adding Functionality):
"$GEN" client --rpc-url "$SERVER_URL" --json view \
  --component-id "$HOLDER_COMPONENT_ID" \
  --method get_balance
Should return 12. You can list all of a component’s view methods straight from its ABI:
jq -r '.methods[] | select(.access_modifier == "view") | .name' \
  "$ARTIFACTS/simple_token_1_holder.abi.json"
Receipt · 0 activations · 0.000¢ USDG · ~5 ms · Reads don’t cost anything. Build them into your hot path freely.

Writing state with build-activation + sign-and-submit

Writes use the same exact pattern as the Transfer between accounts lesson. That is the point — once you’ve internalized one write flow, you’ve internalized all of them. For a write we need a recipient. Install a second holder on bob’s account (repeat the install step from the previous chapter with --account "$BOB"), then call transfer() to move 3 from alice’s holder to bob’s:
BOB_HOLDER_JSON=$("$GEN" client --rpc-url "$SERVER_URL" --json install \
  --wallet alice \
  --contract "$CONTRACT" \
  --account "$BOB" \
  --component-type-index 1)

BOB_HOLDER_COMPONENT_ID=$(jq -r '.result.component_id' <<<"$BOB_HOLDER_JSON")
1

Build the write request

TRANSFER_REQUEST=$(jq -nc \
  --arg component_id "$HOLDER_COMPONENT_ID" \
  --arg recipient "$BOB_HOLDER_COMPONENT_ID" \
  --argjson amount 3 \
  '{
    component_id: $component_id,
    function: "transfer",
    params: { amount: $amount, recipient: $recipient }
  }')
Same JSON shape as the standalone transfer. Only function and params change between “transfer USDG”, “transfer simple-token”, or any other write you’d build.
2

Build the unsigned activation

BUILD_JSON=$("$GEN" client --rpc-url "$SERVER_URL" --json build-activation \
  --wallet alice \
  --request "$TRANSFER_REQUEST")

UNSIGNED=$(jq -r '.result.unsigned_activation_hex' <<<"$BUILD_JSON")
3

Sign and submit

"$GEN" wallet --rpc-url "$SERVER_URL" --json sign-and-submit-activation alice \
  --unsigned-activation "$UNSIGNED" \
  --no-wait
4

Verify with view

"$GEN" client --rpc-url "$SERVER_URL" --json view \
  --component-id "$HOLDER_COMPONENT_ID" \
  --method get_balance
# alice's balance → 9

"$GEN" client --rpc-url "$SERVER_URL" --json view \
  --component-id "$BOB_HOLDER_COMPONENT_ID" \
  --method get_balance
# bob's balance → 15  (he started at 12 too, since install() initializes wallet_balance: 12)
Receipt · 1 activation · 0.001¢ USDG · ~10 ms · A write is a write. The contract function doesn’t change the price.
The read and write share the same ABI fetch and arg encoding — only the payload type (ViewPayload vs ActivationPayload) and whether you sign differ. That is the entire interface, in either environment.

What just happened

You confirmed the entire Grid call surface from a developer’s perspective is exactly two things:
What you want to doHow you do itCost
Read stateclient view --component-id ... --method ...free
Change statebuild-activationsign-and-submit-activation1 activation
That’s the whole API. Every contract you’ll ever write or call on the Grid lives inside that table.

The throughput claim, plainly

The validator pipeline has been benchmarked past 1,000,000 activations per second on a 10-node cluster. The implication for you, the application developer, is simple: the chain is not your bottleneck. If your design requires:
  • Every HTTP request to mint an on-chain receipt → fine.
  • Every agent reasoning step to record a verifiable trace → fine.
  • Every user keystroke in a multiplayer experience to be on-chain → unusual, but fine.
These would be absurd elsewhere. They are routine here. Build accordingly.
The performance figures above are design targets the validator architecture is engineered to hit. They are not guarantees about any specific deployment — production envelope depends on cluster sizing.