gen v0.14.0 —
get-account’s response no longer exposes a flat token_holder_component_id; the holder lives under result.account.components[] with component_type_index == 2. The CLI tab below uses wallet transfer, which wraps the build / sign / submit primitive and resolves the holder for you. The Rust SDK tab shows the primitive directly, because ActivationPayload::builder() still gives you full control over each call.Prerequisites · Your first account + Fund from the faucet done.
$ALICE is funded. You’re back on
local (or still on DevNet — either works).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.
- Local
- DevNet
Make sure a local validator is running (
gen service validator local --embedded-config in another terminal), then:Set up a second account
We need a recipient. Repeat lesson 1 with a new name:Steps
- CLI
- Rust SDK
Send 0.5 USDG from alice to bob
The CLI ships Flags:
wallet transfer as a one-liner that wraps the build /
sign / submit primitive internally — it resolves both accounts’ token-
holder components, encodes the transfer_with_confirmation call,
signs it with the source wallet, and submits the activation.--to "$BOB"— recipient account ingrd@...form (NOT a token-holder component; the CLI resolves that for you).--amount— subunits, same convention as the faucet (1_000_000_000subunits = 1 USDG).--yes— skip the interactive confirmation prompt (useful in scripts).
What just happened
You executed the only write pattern the Grid has:Receipt ·
1 activation · 0.001¢ USDG · ~10 ms · And it’ll cost
0.001¢ next month, next quarter, next year. The price doesn’t move because the
unit is USDG, not GEN.The non-volatility moment, plainly
Imagine you’re building an agent that does 1 000 transfers per day. On chains that price gas in native token:- A 3× price spike means a 3× cost spike, with no warning.
- You can either over-provision (waste capital) or under-provision (your agent stalls).
- You spend engineering time building “wait for cheap gas” heuristics.
1 000 × 0.001¢ = 1¢ per day. That number does
not move. Budgeting becomes arithmetic, not forecasting.
From the Rust tab
The CLI tab and the Rust tab hit the same JSON-RPC. Two things the Rust path lets you control thatwallet transfer doesn’t:
Authenticating to DevNet
DevNet’s RPC requires a bearer token. Build aClientConfig so every request
carries the Authorization header:
The SdkError variants you’ll see in production
sign_and_submit_and_wait_activation_with_options returns Result<TraceOutcome, SdkError>.
The variants worth branching on:
SdkError::Transport(_)— endpoint unreachable, TLS failed, or timeout. Retry with backoff, or fail over to a backup endpoint.SdkError::Server { .. }— endpoint replied with HTTP error.401/403means the JWT is missing or expired (rotate it).429means rate-limited (back off).SdkError::ActivationPolling(_)— submit succeeded but the trace took too long to finalize. Re-fetch byactivation_idinstead of resubmitting; duplicate submissions cost gas and may be rejected oncevalid_until_blocklapses.SdkError::EddsaSigner(_)— the signer failed (KMS down, key locked, hardware wallet timeout). The original error is preserved as thesource.- Activation finalized with non-success status. This is not an
Err; the call returnsOk(outcome)with the failure recorded in the trace (insufficient balance, contract-side error, etc.). Always inspectoutcomebefore treating the transfer as done.
Troubleshooting
`InsufficientBalance` despite a healthy balance
`InsufficientBalance` despite a healthy balance
Check that
--amount in subunits is what you think it is. 1 USDG is
1_000_000_000 subunits — easy to lose a zero.`UnknownFunction: transfer_with_confirmation`
`UnknownFunction: transfer_with_confirmation`
You resolved the holder component for a contract that doesn’t expose that
function. The default token-holder used by the faucet does — but custom
token contracts may use a different name.
client get-account shows the
available methods per component.What’s next
Deploy a contract from ABI
Push, deploy, and install the
simple-token contract you built in the
Contract Development workshop.
