Instructions
The sandbox_ghi program exposes six public instructions. Below is the full spec for each — required accounts, arguments, on-chain checks, and what gets emitted.
stake_nft
Locks an Agent NFT in the staking contract. Creates a StakeAccount PDA and transfers custody of the NFT to the program.
Accounts
| Account | Type | Writable | Signer | Description |
|---|---|---|---|---|
owner | Signer | — | ✓ | NFT owner |
nft_mint | Mint | — | — | Agent NFT mint |
owner_nft_ata | TokenAccount | ✓ | — | Owner's NFT token account |
vault_nft_ata | TokenAccount | ✓ | — | Program vault for NFT custody |
stake_account | StakeAccount (PDA) | ✓ | — | Created by this instruction |
mining_pool | MiningPool (PDA) | ✓ | — | total_staked incremented |
token_program | Program | — | — | SPL Token |
system_program | Program | — | — |
Arguments
None. Tier is read from the NFT's on-chain metadata (Metaplex attribute field).
On-Chain Checks
- NFT must be a verified Sandbox GHI collection member
- Owner must hold the NFT (balance = 1)
- No existing
StakeAccountfor this mint + owner pair
Emits
emit!(StakeEvent {
owner: ctx.accounts.owner.key(),
nft_mint: ctx.accounts.nft_mint.key(),
tier,
timestamp: Clock::get()?.unix_timestamp,
});unstake_nft
Returns the NFT to the owner and auto-claims all pending $GHI rewards. Closes the StakeAccount.
Accounts
| Account | Type | Writable | Signer | Description |
|---|---|---|---|---|
owner | Signer | — | ✓ | Must match stake_account.owner |
nft_mint | Mint | — | — | |
owner_nft_ata | TokenAccount | ✓ | — | Receives NFT back |
vault_nft_ata | TokenAccount | ✓ | — | Releases NFT from custody |
stake_account | StakeAccount (PDA) | ✓ | — | Closed — rent returned to owner |
mining_pool | MiningPool (PDA) | ✓ | — | total_staked decremented |
ghi_vault | TokenAccount (PDA) | ✓ | — | Source of reward tokens |
owner_ghi_ata | TokenAccount | ✓ | — | Created if needed; receives rewards |
ghi_mint | Mint | — | — | $GHI SPL mint |
token_program | Program | — | — | |
system_program | Program | — | — | |
associated_token_program | Program | — | — |
Flow
1. calculate_rewards(stake_account, mining_pool, now)
2. transfer NFT: vault_nft_ata → owner_nft_ata
3. mint_to / transfer: ghi_vault → owner_ghi_ata (reward amount)
4. close stake_account (rent → owner)
5. pool.total_staked -= 1If rewards are zero (staked for less than 1 second), the token transfer is skipped. No error is thrown.
claim_rewards
Claims pending $GHI without unstaking. Updates last_claimed timestamp.
Accounts
| Account | Type | Writable | Signer | Description |
|---|---|---|---|---|
owner | Signer | — | ✓ | |
stake_account | StakeAccount (PDA) | ✓ | — | last_claimed updated |
mining_pool | MiningPool (PDA) | — | — | Read-only (epoch data) |
ghi_vault | TokenAccount (PDA) | ✓ | — | |
owner_ghi_ata | TokenAccount | ✓ | — | |
ghi_mint | Mint | — | — | |
token_program | Program | — | — | |
associated_token_program | Program | — | — |
On-Chain Checks
stake_account.owner == owner.key()- Pending rewards > 0 (otherwise:
ErrorCode::NothingToClaim)
deploy_agent
Creates an AgentAccount and funds it with $GHI for task execution. The NFT must be staked to deploy an agent.
Accounts
| Account | Type | Writable | Signer | Description |
|---|---|---|---|---|
owner | Signer | ✓ | ✓ | |
nft_mint | Mint | — | — | |
stake_account | StakeAccount (PDA) | — | — | Must exist (NFT must be staked) |
agent_account | AgentAccount (PDA) | ✓ | — | Created here |
owner_ghi_ata | TokenAccount | ✓ | — | Source of $GHI budget |
agent_ghi_ata | TokenAccount | ✓ | — | Agent's own ATA (created here) |
ghi_mint | Mint | — | — | |
token_program | Program | — | — | |
system_program | Program | — | — | |
associated_token_program | Program | — | — |
Arguments
| Arg | Type | Description |
|---|---|---|
task_type | TaskType | Monitor / Trader / Optimizer / Custom |
ghi_budget | u64 | $GHI to allocate (raw units, min: 1_000_000 = 1 $GHI) |
On-Chain Checks
- NFT must be staked (
stake_accountmust exist) - No existing
agent_accountfor this mint + owner pair - Legendary holders bypass the minimum budget requirement
submit_task_result
Called by the off-chain agent executor (program authority) to record task completion and award reputation. This instruction is not callable by users.
Accounts
| Account | Type | Writable | Signer | Description |
|---|---|---|---|---|
authority | Signer | — | ✓ | Must match mining_pool.authority |
agent_account | AgentAccount (PDA) | ✓ | — | Reputation updated |
agent_ghi_ata | TokenAccount | ✓ | — | Budget debited |
task_recipient | TokenAccount | ✓ | — | Receives $GHI for completed task |
Arguments
| Arg | Type | Description |
|---|---|---|
task_weight | u8 | 1–10 (set by protocol per task type) |
completion_bonus | u8 | 100 = on-time, 50 = late, 0 = failed |
ghi_cost | u64 | $GHI deducted from agent budget |
close_agent
Stops the agent, returns remaining $GHI budget to owner, and closes the AgentAccount.
Accounts
| Account | Type | Writable | Signer | Description |
|---|---|---|---|---|
owner | Signer | — | ✓ | |
agent_account | AgentAccount (PDA) | ✓ | — | Closed; rent → owner |
agent_ghi_ata | TokenAccount | ✓ | — | Remaining budget returned |
owner_ghi_ata | TokenAccount | ✓ | — | |
token_program | Program | — | — |
On-Chain Checks
agent_account.owner == owner.key()