Skip to main content
An intent in Kimia is a small state machine that records a user’s goal “deposit 1,000 USDC and lock at least 25% APY for 30 days”, and verifies, after the fact, that the underlying multi-step flow achieved it. The intent-router does not execute the trades. It only watches and attests. This is deliberate: transaction size limits on Solana make it hard to do the whole flow atomically, so Kimia splits it across three transactions and uses the session account to guarantee the end-to-end invariant.

The session state machine

  create_session


   ┌────────┐
   │Created │
   └────┬───┘
        │ record_step1 (verified vault share delivery)

 ┌──────────────┐
 │Step1Complete │
 └──────┬───────┘
        │ record_step2 (verified PT + YT minted)

 ┌──────────────┐
 │Step2Complete │
 └──────┬───────┘
        │ record_step3 (verified swap — asserts achieved_rate ≥ target_rate)

 ┌──────────────┐
 │  Completed   │
 └──────────────┘
At any point, close_session returns rent and aborts the flow.

What gets verified

Each record_step* instruction takes the pre/post balances of the relevant token accounts and asserts:
  • Step 1: The user received at least the vault shares the vault promised.
  • Step 2: PT and YT were minted 1:1 against the escrowed shares.
  • Step 3: The AMM swap actually sold PT for underlying, and the implied annualized rate clears the user’s target.
The step-3 rate calculation is: discount=pt_soldunderlying_received\text{discount} = \text{pt\_sold} - \text{underlying\_received} achieved_rate=discount×ONE×SECONDS_PER_YEARunderlying_received×duration\text{achieved\_rate} = \frac{\text{discount} \times \text{ONE} \times \text{SECONDS\_PER\_YEAR}}{\text{underlying\_received} \times \text{duration}} The router then requires achieved_ratetarget_rate\text{achieved\_rate} \geq \text{target\_rate}, reverting otherwise. If the AMM moved against the user between their first deposit and the swap, the router will refuse to complete the session, the user keeps their tokens and can choose to unwind manually.

Why a separate program?

  • Client UX. The frontend can walk the user through three wallet prompts without needing to batch everything into one compute-limited tx.
  • Safety. A naïve “send three txs in order” flow gives no on-chain proof that all three succeeded. The session account is that proof, any integrator can read it and know the user’s outcome.
  • Auditability. Every intent emits IntentCreated, IntentStep1Recorded, IntentStep2Recorded, and IntentFulfilled events with the achieved rate.

intent-router reference

Accounts, instructions, rate formula.

Lock a fixed rate

End-to-end walkthrough with code.