Skip to main content

Whitelist categories

Every transfer must go to a whitelisted address. The Enclz program rejects transfers to anything else. There are three kinds of whitelist entry, each represented by a WhitelistEntry PDA with seed ["whitelist", group_pubkey, target_address].

Typeentry_typeTTLAmount capAuto-void
Intra-group agent0noneunlimitedno
External recipient1requiredrequiredyes — when amount consumed
Protocol2noneunlimitedno

The fact that the entry exists is what authorizes a transfer. Closing the entry de-authorizes it.

Intra-group agent (type 0)​

Auto-added when an agent is created. Lets agents within the same group transfer to each other without manual approval. Permanent — no TTL, no amount cap. Removed only when the agent is removed from the group.

Use case: agent-to-agent micropayments inside a fleet (one agent pays another for a sub-task).

External recipient (type 1)​

Manually added by the orchestrator. Carries:

  • ttl_expires_at — Unix timestamp; transfers after this fail with whitelist_expired
  • approved_amount — total cumulative amount allowed across all transfers to this recipient
  • amount_used — running total, incremented by every successful transfer

When amount_used >= approved_amount, the program closes the WhitelistEntry PDA in the same transaction that consumed the last unit (auto-void). The slot rent is returned to the orchestrator. Future transfers to that recipient fail with whitelist_violation until the orchestrator re-creates the entry with a fresh TTL and budget.

This is the mechanic that makes Enclz different from a "wallet with a budget":

  • A budget you set in software can be bypassed by software.
  • An auto-voiding entry on-chain is verifiable by anyone with a Solana RPC, including the agent itself, including auditors, including a future regulator.

Use case: paying a third-party API. "This Helius endpoint can receive up to $5 from this agent over the next 7 days. After that, the orchestrator must explicitly re-approve."

Protocol (type 2)​

For transfers to program addresses (DEX routers, lending pools). Permanent — no TTL, no amount cap, since these are routing endpoints, not value sinks. Per-tx and daily caps still apply through the agent's own policy ceiling, so a compromised agent can't drain via protocol calls either.

Use case: enabling Jupiter swaps, Kamino deposits, Drift withdrawals. The orchestrator whitelists the protocol's program ID once.

The DEX swap router is auto-added at group initialization (initialize_group), so swaps work immediately after provisioning without an extra step.

Which category to use​

Sending to another agent in your group? → intra-group (auto-added)
Sending to an external API or person? → external (TTL + cap)
Calling a DeFi protocol? → protocol (permanent)

If the address doesn't fit any category, it doesn't get whitelisted. The agent can never send to it.

Whitelist lifecycle (external entries)​

[orchestrator signs add_to_whitelist]
│
▼
[entry exists, amount_used = 0]
│
│ agent transfers $X to this recipient
▼
[amount_used += X]
│
│ if amount_used >= approved_amount:
▼
[program closes entry on-chain in the same tx]
│
▼
[entry is gone — future transfers fail with whitelist_violation]
│
│ orchestrator must sign add_to_whitelist again to re-approve
▼
[fresh entry, amount_used = 0]

Or, if the TTL passes first:

[entry exists, amount_used < approved_amount]
│
│ now > ttl_expires_at
▼
[transfer attempts return whitelist_expired]
│
│ orchestrator can renew (renew_whitelist_entry) or remove + recreate
▼
[fresh TTL]

In both cases the orchestrator's signature is required to re-authorize the recipient.