Actions
Guide to using Action intents for generic Solana program interaction — DeFi, staking, NFT minting, governance, and any on-chain operation not covered by Payment or Ticket intents.
When to Use Action Intents
Action intents are for any Solana program call that doesn't transfer value (use Payment) or represent an entitlement (use Ticket). Examples:
- Calling a Jupiter swap
- Staking tokens in a liquid staking protocol
- Minting an NFT
- Voting in a DAO governance proposal
- Interacting with a dev-owned Solana program
Data Payload
pub struct FreeFormPayload {
pub kind: String, // e.g. "jupiter_swap", "stake_deposit", "nft_mint"
pub data: Vec<u8>, // Serialized application-specific fields
}
The SDK does not parse or validate the contents of data. Your application defines the schema and the exit target performs validation.
Trust Tiers
Actions support two trust tiers:
| Tier | Behavior | Use Case |
|---|---|---|
Unsigned | No cryptographic signature; fingerprinted via content hash | Low-stakes actions: move avatar, save game state |
Signed | Ed25519 signature + per-key nonce replay protection | High-stakes actions: spend tokens, trade items, claim rewards |
Choose the appropriate tier for each action kind. The trust tier lint system warns when high-stakes kinds are registered as Unsigned.
Creating an Action Intent
Expo SDK
import { createIntent } from '@zypp-labs/expo-sdk';
// Unsigned action (low-stakes)
const { intentId } = createIntent('move_avatar', '{"x":10,"y":20}');
// Signed action (high-stakes) — requires trust tier parameter
const { intentId: signedId } = createIntent('swap_tokens', JSON.stringify({
fromMint: 'So11111111111111111111111111111111111111112',
toMint: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
amount: 100_000_000,
}), 'Signed');
Unity SDK
// Unsigned
var intent = ZyppSdk.CreateIntent("move_avatar", "{\"x\":10}", ZyppTrustTier.Unsigned);
// Signed
var signedIntent = ZyppSdk.CreateIntent("swap_tokens", swapPayload, ZyppTrustTier.Signed);
Rust Core
use zypp_labs_core::types::*;
let action = Intent::new(
uuid::Uuid::new_v4(),
IntentType::Action,
IntentPayload::Action(FreeFormPayload {
kind: String::from("jupiter_swap"),
data: bincode::serde::encode_to_vec(&swap_params, bincode::config::standard()).unwrap(),
}),
TrustTier::Signed,
Some(crypto_envelope),
);
Settlement Routing
Action intents route to one of two exit targets:
- Developer Backend — your server validates and records the action
- Developer Solana Program — a dev-owned program, such as an ephemeral rollup or custom program
// Settle via developer backend
settle(intentId, 'https://api.myapp.com/actions', 1);
// Settle via dev Solana program
settle(intentId, 'https://rpc.devnet.solana.com', 2);
The caller must provide the exit target explicitly — there is no SDK default.
Composing Multiple Actions
Action intents can batch multiple instructions in a single intent for atomic execution:
// Multiple actions in sequence
const actions = [
{ kind: 'approve', data: { spender, amount } },
{ kind: 'swap', data: { fromMint, toMint, amount } },
{ kind: 'deposit', data: { protocol, amount } },
];
Trust Tier Lint
Register action kinds with their expected trust tier to catch misconfigurations at development time:
import { registerKind, lint } from '@zypp-labs/expo-sdk';
// Register kinds with expected trust tiers
const warnings = registerKind({
kind: 'swap_tokens',
intent_type: 'Action',
trust_tier: 'Signed',
fields: []
});
// Audit all registered kinds and queued intents
const lintWarnings = lint();
if (lintWarnings.length > 0) {
console.warn('Trust tier issues found:', lintWarnings);
}
High-stakes action kinds matching patterns like "spend", "trade", "claim", "stake", "transfer" registered as Unsigned emit warnings at registration time.
Error Handling
| Error | Cause | Action |
|---|---|---|
TrustTierTooLow | Intent tier below kind requirement | Re-create with Signed tier |
ValidationError | Backend rejected the action | Check backend validation rules |
DuplicateInLocalQueue | Same action already queued | Check queue before retrying |
Next Steps
- Set up the Expo SDK for mobile action intents
- Configure Settlement for your exit target
- Browse Examples for action implementations