{
  "address": "GYy4kM6GHhpgLCUscuABbzkD2ZbJ2fneYryaZ6Ch7fFU",
  "metadata": {
    "name": "privacy_pool",
    "version": "0.1.0",
    "spec": "0.1.0",
    "description": "Veilo - Privacy Layer on Solana"
  },
  "instructions": [
    {
      "name": "add_merkle_tree",
      "discriminator": [199, 97, 38, 35, 140, 113, 187, 30],
      "accounts": [
        {
          "name": "config",
          "writable": true,
          "pda": {
            "seeds": [
              {
                "kind": "const",
                "value": [
                  112, 114, 105, 118, 97, 99, 121, 95, 99, 111, 110, 102, 105,
                  103, 95, 118, 51
                ]
              },
              {
                "kind": "arg",
                "path": "mint_address"
              }
            ]
          }
        },
        {
          "name": "note_tree",
          "writable": true,
          "pda": {
            "seeds": [
              {
                "kind": "const",
                "value": [
                  112, 114, 105, 118, 97, 99, 121, 95, 110, 111, 116, 101, 95,
                  116, 114, 101, 101, 95, 118, 51
                ]
              },
              {
                "kind": "arg",
                "path": "mint_address"
              },
              {
                "kind": "arg",
                "path": "tree_id"
              }
            ]
          }
        },
        {
          "name": "relayer",
          "docs": [
            "Relayer who can add trees (must be registered in config.relayers)"
          ],
          "writable": true,
          "signer": true
        },
        {
          "name": "system_program",
          "address": "11111111111111111111111111111111"
        }
      ],
      "args": [
        {
          "name": "_mint_address",
          "type": "pubkey"
        },
        {
          "name": "tree_id",
          "type": "u16"
        }
      ]
    },
    {
      "name": "add_relayer",
      "discriminator": [184, 240, 94, 199, 19, 71, 21, 192],
      "accounts": [
        {
          "name": "config",
          "writable": true,
          "pda": {
            "seeds": [
              {
                "kind": "const",
                "value": [
                  112, 114, 105, 118, 97, 99, 121, 95, 99, 111, 110, 102, 105,
                  103, 95, 118, 51
                ]
              },
              {
                "kind": "arg",
                "path": "mint_address"
              }
            ]
          }
        },
        {
          "name": "admin",
          "docs": [
            "has_one = admin ensures this matches config.admin.",
            "When using Squads, the vault PDA signs after multisig approval."
          ],
          "signer": true,
          "relations": ["config"]
        }
      ],
      "args": [
        {
          "name": "_mint_address",
          "type": "pubkey"
        },
        {
          "name": "new_relayer",
          "type": "pubkey"
        }
      ]
    },
    {
      "name": "fund_native_source",
      "docs": [
        "Option B: Create executor PDA + WSOL ATA and transfer swap_amount from vault.",
        "Must be invoked as the FIRST instruction in an atomic transaction whose SECOND",
        "instruction is `transact_swap`.  Both instructions are sent together so that",
        "failure in `transact_swap` reverts the vault debit atomically.",
        "",
        "Only for native SOL source pools.  SPL-source swaps use `transact_swap` directly."
      ],
      "discriminator": [247, 142, 43, 167, 56, 52, 137, 118],
      "accounts": [
        {
          "name": "executor",
          "docs": [
            "Executor PDA — created here, validated in the following transact_swap instruction."
          ],
          "writable": true,
          "pda": {
            "seeds": [
              {
                "kind": "const",
                "value": [
                  115, 119, 97, 112, 95, 101, 120, 101, 99, 117, 116, 111, 114
                ]
              },
              {
                "kind": "arg",
                "path": "source_mint"
              },
              {
                "kind": "arg",
                "path": "dest_mint"
              },
              {
                "kind": "arg",
                "path": "input_nullifier_0"
              },
              {
                "kind": "account",
                "path": "relayer"
              }
            ]
          }
        },
        {
          "name": "executor_source_token",
          "docs": [
            "Executor's WSOL ATA — created here, funded with swap_amount from source vault.",
            "This is executor_source_token for the following transact_swap instruction."
          ],
          "writable": true,
          "pda": {
            "seeds": [
              {
                "kind": "account",
                "path": "executor"
              },
              {
                "kind": "const",
                "value": [
                  6, 221, 246, 225, 215, 101, 161, 147, 217, 203, 225, 70, 206,
                  235, 121, 172, 28, 180, 133, 237, 95, 91, 55, 145, 58, 140,
                  245, 133, 126, 255, 0, 169
                ]
              },
              {
                "kind": "account",
                "path": "source_mint_account"
              }
            ],
            "program": {
              "kind": "const",
              "value": [
                140, 151, 37, 143, 78, 36, 137, 241, 187, 61, 16, 41, 20, 142,
                13, 131, 11, 90, 19, 153, 218, 255, 16, 132, 4, 142, 123, 216,
                219, 233, 248, 89
              ]
            }
          }
        },
        {
          "name": "source_vault",
          "docs": [
            "Source vault PDA (native SOL pool — program-owned, stores raw lamports)."
          ],
          "writable": true,
          "pda": {
            "seeds": [
              {
                "kind": "const",
                "value": [
                  112, 114, 105, 118, 97, 99, 121, 95, 118, 97, 117, 108, 116,
                  95, 118, 51
                ]
              },
              {
                "kind": "arg",
                "path": "source_mint"
              }
            ]
          }
        },
        {
          "name": "source_config",
          "docs": [
            "Source pool config — checked for vault_bump and relayer authorisation."
          ],
          "pda": {
            "seeds": [
              {
                "kind": "const",
                "value": [
                  112, 114, 105, 118, 97, 99, 121, 95, 99, 111, 110, 102, 105,
                  103, 95, 118, 51
                ]
              },
              {
                "kind": "arg",
                "path": "source_mint"
              }
            ]
          }
        },
        {
          "name": "source_mint_account",
          "docs": [
            "WSOL mint (So111…1112) — required for executor_source_token ATA constraint.",
            "Must equal effective_mint(source_mint), i.e., source_mint must be native SOL."
          ]
        },
        {
          "name": "relayer",
          "docs": [
            "Relayer — pays rent for created accounts, must be whitelisted in source pool."
          ],
          "writable": true,
          "signer": true
        },
        {
          "name": "instructions_sysvar",
          "docs": [
            "with a `transact_swap` call in the same transaction, preventing standalone",
            "vault-drain calls with arbitrary nullifiers."
          ],
          "address": "Sysvar1nstructions1111111111111111111111111"
        },
        {
          "name": "token_program",
          "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
        },
        {
          "name": "system_program",
          "address": "11111111111111111111111111111111"
        },
        {
          "name": "associated_token_program",
          "address": "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL"
        }
      ],
      "args": [
        {
          "name": "source_mint",
          "type": "pubkey"
        },
        {
          "name": "dest_mint",
          "type": "pubkey"
        },
        {
          "name": "input_nullifier_0",
          "type": {
            "array": ["u8", 32]
          }
        },
        {
          "name": "swap_amount",
          "type": "u64"
        }
      ]
    },
    {
      "name": "initialize",
      "discriminator": [175, 175, 109, 31, 13, 152, 155, 237],
      "accounts": [
        {
          "name": "config",
          "writable": true,
          "pda": {
            "seeds": [
              {
                "kind": "const",
                "value": [
                  112, 114, 105, 118, 97, 99, 121, 95, 99, 111, 110, 102, 105,
                  103, 95, 118, 51
                ]
              },
              {
                "kind": "arg",
                "path": "mint_address"
              }
            ]
          }
        },
        {
          "name": "vault",
          "writable": true,
          "pda": {
            "seeds": [
              {
                "kind": "const",
                "value": [
                  112, 114, 105, 118, 97, 99, 121, 95, 118, 97, 117, 108, 116,
                  95, 118, 51
                ]
              },
              {
                "kind": "arg",
                "path": "mint_address"
              }
            ]
          }
        },
        {
          "name": "note_tree",
          "docs": ["Initial tree (tree_id = 0)"],
          "writable": true,
          "pda": {
            "seeds": [
              {
                "kind": "const",
                "value": [
                  112, 114, 105, 118, 97, 99, 121, 95, 110, 111, 116, 101, 95,
                  116, 114, 101, 101, 95, 118, 51
                ]
              },
              {
                "kind": "arg",
                "path": "mint_address"
              },
              {
                "kind": "const",
                "value": [0, 0]
              }
            ]
          }
        },
        {
          "name": "nullifiers",
          "writable": true,
          "pda": {
            "seeds": [
              {
                "kind": "const",
                "value": [
                  112, 114, 105, 118, 97, 99, 121, 95, 110, 117, 108, 108, 105,
                  102, 105, 101, 114, 115, 95, 118, 51
                ]
              },
              {
                "kind": "arg",
                "path": "mint_address"
              }
            ]
          }
        },
        {
          "name": "admin",
          "docs": [
            "When using Squads multisig, this should be the vault PDA.",
            "Squads will sign this account after multisig approval."
          ],
          "signer": true
        },
        {
          "name": "payer",
          "docs": [
            "Transaction fee payer (can be anyone, separate from admin authority)"
          ],
          "writable": true,
          "signer": true
        },
        {
          "name": "system_program",
          "address": "11111111111111111111111111111111"
        }
      ],
      "args": [
        {
          "name": "fee_bps",
          "type": "u16"
        },
        {
          "name": "mint_address",
          "type": "pubkey"
        },
        {
          "name": "min_deposit_amount",
          "type": {
            "option": "u64"
          }
        },
        {
          "name": "max_deposit_amount",
          "type": {
            "option": "u64"
          }
        },
        {
          "name": "min_withdraw_amount",
          "type": {
            "option": "u64"
          }
        },
        {
          "name": "max_withdraw_amount",
          "type": {
            "option": "u64"
          }
        }
      ]
    },
    {
      "name": "initialize_global_config",
      "discriminator": [113, 216, 122, 131, 225, 209, 22, 55],
      "accounts": [
        {
          "name": "global_config",
          "writable": true,
          "pda": {
            "seeds": [
              {
                "kind": "const",
                "value": [
                  103, 108, 111, 98, 97, 108, 95, 99, 111, 110, 102, 105, 103,
                  95, 118, 49
                ]
              }
            ]
          }
        },
        {
          "name": "admin",
          "docs": ["When using Squads multisig, this should be the vault PDA."],
          "signer": true
        },
        {
          "name": "payer",
          "docs": [
            "Transaction fee payer (can be anyone, separate from admin authority)"
          ],
          "writable": true,
          "signer": true
        },
        {
          "name": "system_program",
          "address": "11111111111111111111111111111111"
        }
      ],
      "args": []
    },
    {
      "name": "transact",
      "docs": [
        "Unified UTXO transaction instruction",
        "Circuit equation: sumIns + publicAmount = sumOuts",
        "Handles deposits (publicAmount > 0), withdrawals (publicAmount < 0), and transfers (publicAmount = 0)",
        "",
        "Cross-tree transactions:",
        "- input_tree_id: Tree containing input notes (for root validation)",
        "- output_tree_id: Tree for new output commitments",
        "- Can be the same tree or different trees",
        "- Allows withdrawals even when input tree is full (outputs go to new tree)"
      ],
      "discriminator": [217, 149, 130, 143, 221, 52, 252, 119],
      "accounts": [
        {
          "name": "config",
          "writable": true,
          "pda": {
            "seeds": [
              {
                "kind": "const",
                "value": [
                  112, 114, 105, 118, 97, 99, 121, 95, 99, 111, 110, 102, 105,
                  103, 95, 118, 51
                ]
              },
              {
                "kind": "arg",
                "path": "mint_address"
              }
            ]
          }
        },
        {
          "name": "global_config",
          "pda": {
            "seeds": [
              {
                "kind": "const",
                "value": [
                  103, 108, 111, 98, 97, 108, 95, 99, 111, 110, 102, 105, 103,
                  95, 118, 49
                ]
              }
            ]
          }
        },
        {
          "name": "vault",
          "writable": true,
          "pda": {
            "seeds": [
              {
                "kind": "const",
                "value": [
                  112, 114, 105, 118, 97, 99, 121, 95, 118, 97, 117, 108, 116,
                  95, 118, 51
                ]
              },
              {
                "kind": "arg",
                "path": "mint_address"
              }
            ]
          }
        },
        {
          "name": "input_tree",
          "docs": [
            "Input tree - where input notes came from (for root validation)"
          ],
          "writable": true,
          "pda": {
            "seeds": [
              {
                "kind": "const",
                "value": [
                  112, 114, 105, 118, 97, 99, 121, 95, 110, 111, 116, 101, 95,
                  116, 114, 101, 101, 95, 118, 51
                ]
              },
              {
                "kind": "arg",
                "path": "mint_address"
              },
              {
                "kind": "arg",
                "path": "input_tree_id"
              }
            ]
          }
        },
        {
          "name": "output_tree",
          "docs": [
            "Output tree - where new output commitments will be inserted"
          ],
          "writable": true,
          "pda": {
            "seeds": [
              {
                "kind": "const",
                "value": [
                  112, 114, 105, 118, 97, 99, 121, 95, 110, 111, 116, 101, 95,
                  116, 114, 101, 101, 95, 118, 51
                ]
              },
              {
                "kind": "arg",
                "path": "mint_address"
              },
              {
                "kind": "arg",
                "path": "output_tree_id"
              }
            ]
          }
        },
        {
          "name": "nullifiers",
          "writable": true,
          "pda": {
            "seeds": [
              {
                "kind": "const",
                "value": [
                  112, 114, 105, 118, 97, 99, 121, 95, 110, 117, 108, 108, 105,
                  102, 105, 101, 114, 115, 95, 118, 51
                ]
              },
              {
                "kind": "arg",
                "path": "mint_address"
              }
            ]
          }
        },
        {
          "name": "nullifier_marker_0",
          "docs": [
            "First nullifier marker (must not exist for withdrawals - ensures nullifier is fresh)",
            "For deposits (public_amount > 0), this should be the zero nullifier marker (reusable)",
            "NOTE: Nullifier markers are global (no tree_id) to prevent cross-tree double-spend"
          ],
          "writable": true,
          "pda": {
            "seeds": [
              {
                "kind": "const",
                "value": [
                  110, 117, 108, 108, 105, 102, 105, 101, 114, 95, 118, 51
                ]
              },
              {
                "kind": "arg",
                "path": "mint_address"
              },
              {
                "kind": "arg",
                "path": "input_nullifier_0"
              }
            ]
          }
        },
        {
          "name": "nullifier_marker_1",
          "docs": [
            "Second nullifier marker (must not exist for withdrawals - ensures nullifier is fresh)",
            "For deposits (public_amount > 0), this should be the zero nullifier marker (reusable)",
            "NOTE: Nullifier markers are global (no tree_id) to prevent cross-tree double-spend"
          ],
          "writable": true,
          "pda": {
            "seeds": [
              {
                "kind": "const",
                "value": [
                  110, 117, 108, 108, 105, 102, 105, 101, 114, 95, 118, 51
                ]
              },
              {
                "kind": "arg",
                "path": "mint_address"
              },
              {
                "kind": "arg",
                "path": "input_nullifier_1"
              }
            ]
          }
        },
        {
          "name": "relayer",
          "docs": ["Relayer who submits transaction (pays rent, receives fee)"],
          "writable": true,
          "signer": true
        },
        {
          "name": "recipient",
          "docs": [
            "Recipient (receives withdrawal amount if public_amount > 0)"
          ],
          "writable": true
        },
        {
          "name": "vault_token_account",
          "docs": ["Vault's token account (ATA for mint_address)"],
          "writable": true
        },
        {
          "name": "user_token_account",
          "docs": ["User's token account (for deposits)"],
          "writable": true
        },
        {
          "name": "recipient_token_account",
          "docs": ["Recipient's token account (for withdrawals)"],
          "writable": true
        },
        {
          "name": "relayer_token_account",
          "docs": ["Relayer's token account (for fees)"],
          "writable": true
        },
        {
          "name": "token_program",
          "docs": ["SPL Token program"]
        },
        {
          "name": "system_program",
          "address": "11111111111111111111111111111111"
        }
      ],
      "args": [
        {
          "name": "root",
          "type": {
            "array": ["u8", 32]
          }
        },
        {
          "name": "input_tree_id",
          "type": "u16"
        },
        {
          "name": "output_tree_id",
          "type": "u16"
        },
        {
          "name": "public_amount",
          "type": "i64"
        },
        {
          "name": "ext_data_hash",
          "type": {
            "array": ["u8", 32]
          }
        },
        {
          "name": "mint_address",
          "type": "pubkey"
        },
        {
          "name": "input_nullifier_0",
          "type": {
            "array": ["u8", 32]
          }
        },
        {
          "name": "input_nullifier_1",
          "type": {
            "array": ["u8", 32]
          }
        },
        {
          "name": "output_commitment_0",
          "type": {
            "array": ["u8", 32]
          }
        },
        {
          "name": "output_commitment_1",
          "type": {
            "array": ["u8", 32]
          }
        },
        {
          "name": "deadline",
          "type": "i64"
        },
        {
          "name": "ext_data",
          "type": {
            "defined": {
              "name": "ExtData"
            }
          }
        },
        {
          "name": "proof",
          "type": {
            "defined": {
              "name": "TransactionProof"
            }
          }
        },
        {
          "name": "note_ciphers",
          "type": {
            "option": {
              "defined": {
                "name": "NoteCiphers"
              }
            }
          }
        }
      ]
    },
    {
      "name": "transact_swap",
      "docs": [
        "Atomic cross-pool private swap",
        "Consumes notes from source pool, swaps via Raydium CPMM (no Serum), creates notes in dest pool",
        "All in one transaction - see swap.rs for implementation details"
      ],
      "discriminator": [36, 133, 230, 184, 198, 10, 202, 249],
      "accounts": [
        {
          "name": "source_config",
          "writable": true,
          "pda": {
            "seeds": [
              {
                "kind": "const",
                "value": [
                  112, 114, 105, 118, 97, 99, 121, 95, 99, 111, 110, 102, 105,
                  103, 95, 118, 51
                ]
              },
              {
                "kind": "arg",
                "path": "source_mint"
              }
            ]
          }
        },
        {
          "name": "global_config",
          "pda": {
            "seeds": [
              {
                "kind": "const",
                "value": [
                  103, 108, 111, 98, 97, 108, 95, 99, 111, 110, 102, 105, 103,
                  95, 118, 49
                ]
              }
            ]
          }
        },
        {
          "name": "source_vault",
          "writable": true,
          "pda": {
            "seeds": [
              {
                "kind": "const",
                "value": [
                  112, 114, 105, 118, 97, 99, 121, 95, 118, 97, 117, 108, 116,
                  95, 118, 51
                ]
              },
              {
                "kind": "arg",
                "path": "source_mint"
              }
            ]
          }
        },
        {
          "name": "source_tree",
          "docs": ["Source tree - where input notes came from"],
          "writable": true,
          "pda": {
            "seeds": [
              {
                "kind": "const",
                "value": [
                  112, 114, 105, 118, 97, 99, 121, 95, 110, 111, 116, 101, 95,
                  116, 114, 101, 101, 95, 118, 51
                ]
              },
              {
                "kind": "arg",
                "path": "source_mint"
              },
              {
                "kind": "arg",
                "path": "source_tree_id"
              }
            ]
          }
        },
        {
          "name": "source_nullifiers",
          "writable": true,
          "pda": {
            "seeds": [
              {
                "kind": "const",
                "value": [
                  112, 114, 105, 118, 97, 99, 121, 95, 110, 117, 108, 108, 105,
                  102, 105, 101, 114, 115, 95, 118, 51
                ]
              },
              {
                "kind": "arg",
                "path": "source_mint"
              }
            ]
          }
        },
        {
          "name": "source_nullifier_marker_0",
          "docs": [
            "First nullifier marker for source pool",
            "NOTE: Nullifier markers are global (no tree_id) to prevent cross-tree double-spend"
          ],
          "writable": true,
          "pda": {
            "seeds": [
              {
                "kind": "const",
                "value": [
                  110, 117, 108, 108, 105, 102, 105, 101, 114, 95, 118, 51
                ]
              },
              {
                "kind": "arg",
                "path": "source_mint"
              },
              {
                "kind": "arg",
                "path": "input_nullifier_0"
              }
            ]
          }
        },
        {
          "name": "source_nullifier_marker_1",
          "docs": [
            "Second nullifier marker for source pool",
            "NOTE: Nullifier markers are global (no tree_id) to prevent cross-tree double-spend"
          ],
          "writable": true,
          "pda": {
            "seeds": [
              {
                "kind": "const",
                "value": [
                  110, 117, 108, 108, 105, 102, 105, 101, 114, 95, 118, 51
                ]
              },
              {
                "kind": "arg",
                "path": "source_mint"
              },
              {
                "kind": "arg",
                "path": "input_nullifier_1"
              }
            ]
          }
        },
        {
          "name": "source_vault_token_account",
          "docs": [
            "Source vault's token account",
            "For native SOL pools (mint_address == Pubkey::default), this may be unused — pass any mut account.",
            "For SPL pools, must be the canonical ATA of the source vault for the source mint."
          ],
          "writable": true
        },
        {
          "name": "source_mint_account",
          "docs": [
            "Source token mint — for native SOL pools, pass the WSOL (NATIVE_MINT) account.",
            "Must match effective_mint(source_mint) so executor ATAs are created with WSOL."
          ]
        },
        {
          "name": "dest_config",
          "writable": true,
          "pda": {
            "seeds": [
              {
                "kind": "const",
                "value": [
                  112, 114, 105, 118, 97, 99, 121, 95, 99, 111, 110, 102, 105,
                  103, 95, 118, 51
                ]
              },
              {
                "kind": "arg",
                "path": "dest_mint"
              }
            ]
          }
        },
        {
          "name": "dest_vault",
          "writable": true,
          "pda": {
            "seeds": [
              {
                "kind": "const",
                "value": [
                  112, 114, 105, 118, 97, 99, 121, 95, 118, 97, 117, 108, 116,
                  95, 118, 51
                ]
              },
              {
                "kind": "arg",
                "path": "dest_mint"
              }
            ]
          }
        },
        {
          "name": "dest_tree",
          "docs": [
            "Destination tree - where output commitments will be inserted"
          ],
          "writable": true,
          "pda": {
            "seeds": [
              {
                "kind": "const",
                "value": [
                  112, 114, 105, 118, 97, 99, 121, 95, 110, 111, 116, 101, 95,
                  116, 114, 101, 101, 95, 118, 51
                ]
              },
              {
                "kind": "arg",
                "path": "dest_mint"
              },
              {
                "kind": "arg",
                "path": "dest_tree_id"
              }
            ]
          }
        },
        {
          "name": "dest_vault_token_account",
          "docs": [
            "Destination vault's token account",
            "For native SOL pools (mint_address == Pubkey::default), may be unused — pass any mut account.",
            "For SPL pools, must be the canonical ATA of the dest vault for the dest mint."
          ],
          "writable": true
        },
        {
          "name": "dest_mint_account",
          "docs": [
            "Destination token mint — for native SOL pools, pass the WSOL (NATIVE_MINT) account.",
            "Must match effective_mint(dest_mint) so executor ATAs are created with WSOL."
          ]
        },
        {
          "name": "executor",
          "docs": [
            "Executor PDA - holds tokens during swap",
            "Seeds include source_mint, dest_mint, nullifier, AND relayer key to prevent front-running DoS",
            "Uses init_if_needed: for native SOL swaps the executor is pre-created by fund_native_source."
          ],
          "writable": true,
          "pda": {
            "seeds": [
              {
                "kind": "const",
                "value": [
                  115, 119, 97, 112, 95, 101, 120, 101, 99, 117, 116, 111, 114
                ]
              },
              {
                "kind": "arg",
                "path": "source_mint"
              },
              {
                "kind": "arg",
                "path": "dest_mint"
              },
              {
                "kind": "arg",
                "path": "input_nullifier_0"
              },
              {
                "kind": "account",
                "path": "relayer"
              }
            ]
          }
        },
        {
          "name": "executor_source_token",
          "docs": [
            "Executor's source token account (receives from source vault)",
            "Uses init_if_needed: pre-created by fund_native_source for native SOL swaps."
          ],
          "writable": true,
          "pda": {
            "seeds": [
              {
                "kind": "account",
                "path": "executor"
              },
              {
                "kind": "const",
                "value": [
                  6, 221, 246, 225, 215, 101, 161, 147, 217, 203, 225, 70, 206,
                  235, 121, 172, 28, 180, 133, 237, 95, 91, 55, 145, 58, 140,
                  245, 133, 126, 255, 0, 169
                ]
              },
              {
                "kind": "account",
                "path": "source_mint_account"
              }
            ],
            "program": {
              "kind": "const",
              "value": [
                140, 151, 37, 143, 78, 36, 137, 241, 187, 61, 16, 41, 20, 142,
                13, 131, 11, 90, 19, 153, 218, 255, 16, 132, 4, 142, 123, 216,
                219, 233, 248, 89
              ]
            }
          }
        },
        {
          "name": "executor_dest_token",
          "docs": [
            "Executor's destination token account (receives swapped tokens)"
          ],
          "writable": true,
          "pda": {
            "seeds": [
              {
                "kind": "account",
                "path": "executor"
              },
              {
                "kind": "const",
                "value": [
                  6, 221, 246, 225, 215, 101, 161, 147, 217, 203, 225, 70, 206,
                  235, 121, 172, 28, 180, 133, 237, 95, 91, 55, 145, 58, 140,
                  245, 133, 126, 255, 0, 169
                ]
              },
              {
                "kind": "account",
                "path": "dest_mint_account"
              }
            ],
            "program": {
              "kind": "const",
              "value": [
                140, 151, 37, 143, 78, 36, 137, 241, 187, 61, 16, 41, 20, 142,
                13, 131, 11, 90, 19, 153, 218, 255, 16, 132, 4, 142, 123, 216,
                219, 233, 248, 89
              ]
            }
          }
        },
        {
          "name": "relayer",
          "docs": ["Relayer who submits transaction (pays rent, receives fee)"],
          "writable": true,
          "signer": true
        },
        {
          "name": "relayer_token_account",
          "docs": ["Relayer's token account for fees (dest token)"],
          "writable": true
        },
        {
          "name": "swap_program",
          "docs": ["Raydium Swap program (CPMM or AMM)"]
        },
        {
          "name": "jupiter_event_authority",
          "docs": ["Jupiter Event Authority (required for Jupiter V6 swaps)"]
        },
        {
          "name": "token_program",
          "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
        },
        {
          "name": "system_program",
          "address": "11111111111111111111111111111111"
        },
        {
          "name": "associated_token_program",
          "address": "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL"
        }
      ],
      "args": [
        {
          "name": "source_tree_id",
          "type": "u16"
        },
        {
          "name": "source_mint",
          "type": "pubkey"
        },
        {
          "name": "input_nullifier_0",
          "type": {
            "array": ["u8", 32]
          }
        },
        {
          "name": "input_nullifier_1",
          "type": {
            "array": ["u8", 32]
          }
        },
        {
          "name": "dest_tree_id",
          "type": "u16"
        },
        {
          "name": "dest_mint",
          "type": "pubkey"
        },
        {
          "name": "proof",
          "type": {
            "defined": {
              "name": "SwapProof"
            }
          }
        },
        {
          "name": "source_root",
          "type": {
            "array": ["u8", 32]
          }
        },
        {
          "name": "output_commitment_0",
          "type": {
            "array": ["u8", 32]
          }
        },
        {
          "name": "output_commitment_1",
          "type": {
            "array": ["u8", 32]
          }
        },
        {
          "name": "swap_params",
          "type": {
            "defined": {
              "name": "SwapParams"
            }
          }
        },
        {
          "name": "swap_amount",
          "type": "u64"
        },
        {
          "name": "swap_data",
          "type": "bytes"
        },
        {
          "name": "ext_data",
          "type": {
            "defined": {
              "name": "ExtData"
            }
          }
        },
        {
          "name": "note_ciphers",
          "type": {
            "option": {
              "defined": {
                "name": "NoteCiphers"
              }
            }
          }
        }
      ]
    },
    {
      "name": "update_global_config",
      "discriminator": [164, 84, 130, 189, 111, 58, 250, 200],
      "accounts": [
        {
          "name": "global_config",
          "writable": true,
          "pda": {
            "seeds": [
              {
                "kind": "const",
                "value": [
                  103, 108, 111, 98, 97, 108, 95, 99, 111, 110, 102, 105, 103,
                  95, 118, 49
                ]
              }
            ]
          }
        },
        {
          "name": "admin",
          "docs": ["has_one = admin ensures this matches global_config.admin."],
          "signer": true,
          "relations": ["global_config"]
        }
      ],
      "args": []
    },
    {
      "name": "update_pool_config",
      "discriminator": [68, 236, 203, 122, 179, 62, 234, 252],
      "accounts": [
        {
          "name": "config",
          "writable": true,
          "pda": {
            "seeds": [
              {
                "kind": "const",
                "value": [
                  112, 114, 105, 118, 97, 99, 121, 95, 99, 111, 110, 102, 105,
                  103, 95, 118, 51
                ]
              },
              {
                "kind": "arg",
                "path": "mint_address"
              }
            ]
          }
        },
        {
          "name": "admin",
          "signer": true,
          "relations": ["config"]
        }
      ],
      "args": [
        {
          "name": "_mint_address",
          "type": "pubkey"
        },
        {
          "name": "min_deposit_amount",
          "type": {
            "option": "u64"
          }
        },
        {
          "name": "max_deposit_amount",
          "type": {
            "option": "u64"
          }
        },
        {
          "name": "min_withdraw_amount",
          "type": {
            "option": "u64"
          }
        },
        {
          "name": "max_withdraw_amount",
          "type": {
            "option": "u64"
          }
        },
        {
          "name": "fee_bps",
          "type": {
            "option": "u16"
          }
        },
        {
          "name": "min_withdrawal_fee",
          "type": {
            "option": "u64"
          }
        },
        {
          "name": "fee_error_margin_bps",
          "type": {
            "option": "u16"
          }
        },
        {
          "name": "min_swap_fee",
          "type": {
            "option": "u64"
          }
        },
        {
          "name": "swap_fee_bps",
          "type": {
            "option": "u16"
          }
        }
      ]
    }
  ],
  "accounts": [
    {
      "name": "GlobalConfig",
      "discriminator": [149, 8, 156, 202, 160, 252, 176, 217]
    },
    {
      "name": "MerkleTreeAccount",
      "discriminator": [147, 200, 34, 248, 131, 187, 248, 253]
    },
    {
      "name": "NullifierMarker",
      "discriminator": [160, 124, 83, 42, 185, 14, 141, 101]
    },
    {
      "name": "NullifierSet",
      "discriminator": [251, 219, 17, 100, 208, 102, 127, 25]
    },
    {
      "name": "PrivacyConfig",
      "discriminator": [165, 149, 218, 209, 148, 237, 242, 159]
    },
    {
      "name": "SwapExecutor",
      "discriminator": [28, 237, 82, 118, 158, 162, 39, 225]
    },
    {
      "name": "Vault",
      "discriminator": [211, 8, 232, 43, 2, 152, 117, 119]
    }
  ],
  "events": [
    {
      "name": "CommitmentEvent",
      "discriminator": [89, 205, 140, 111, 36, 129, 217, 125]
    },
    {
      "name": "NullifierSpent",
      "discriminator": [166, 111, 130, 54, 212, 115, 152, 215]
    },
    {
      "name": "SwapExecutedEvent",
      "discriminator": [183, 28, 219, 210, 164, 184, 62, 12]
    }
  ],
  "errors": [
    {
      "code": 6000,
      "name": "Paused",
      "msg": "Pool is paused"
    },
    {
      "code": 6001,
      "name": "NoDenoms",
      "msg": "No denominations configured"
    },
    {
      "code": 6002,
      "name": "TooManyDenoms",
      "msg": "Too many denominations"
    },
    {
      "code": 6003,
      "name": "BadDenomIndex",
      "msg": "Bad denomination index"
    },
    {
      "code": 6004,
      "name": "MathOverflow",
      "msg": "Math overflow"
    },
    {
      "code": 6005,
      "name": "NullifierAlreadyUsed",
      "msg": "Nullifier already used"
    },
    {
      "code": 6006,
      "name": "NullifierTableFull",
      "msg": "Nullifier table is full"
    },
    {
      "code": 6007,
      "name": "UnknownRoot",
      "msg": "Unknown root"
    },
    {
      "code": 6008,
      "name": "RelayerNotAllowed",
      "msg": "Relayer not allowed"
    },
    {
      "code": 6009,
      "name": "InsufficientVaultBalance",
      "msg": "Vault balance too low"
    },
    {
      "code": 6010,
      "name": "TooManyRelayers",
      "msg": "Too many relayers"
    },
    {
      "code": 6011,
      "name": "InvalidProof",
      "msg": "Invalid proof encoding"
    },
    {
      "code": 6012,
      "name": "VerifyFailed",
      "msg": "Groth16 verification failed"
    },
    {
      "code": 6013,
      "name": "MerkleTreeFull",
      "msg": "Merkle tree is full - use a different tree_id or add a new tree with add_merkle_tree"
    },
    {
      "code": 6014,
      "name": "MerkleHashFailed",
      "msg": "Merkle hash failed"
    },
    {
      "code": 6015,
      "name": "InvalidExtData",
      "msg": "Invalid external data hash"
    },
    {
      "code": 6016,
      "name": "RecipientMismatch",
      "msg": "Recipient mismatch"
    },
    {
      "code": 6017,
      "name": "InvalidMintAddress",
      "msg": "Invalid mint address"
    },
    {
      "code": 6018,
      "name": "ExcessiveFee",
      "msg": "Excessive fee"
    },
    {
      "code": 6019,
      "name": "InsufficientFee",
      "msg": "Fee below minimum required for withdrawal"
    },
    {
      "code": 6020,
      "name": "ArithmeticOverflow",
      "msg": "Arithmetic overflow/underflow occurred"
    },
    {
      "code": 6021,
      "name": "InsufficientFundsForWithdrawal",
      "msg": "Insufficient funds for withdrawal (including rent exemption)"
    },
    {
      "code": 6022,
      "name": "InsufficientFundsForFee",
      "msg": "Insufficient funds for fee payment"
    },
    {
      "code": 6023,
      "name": "InvalidPublicAmount",
      "msg": "Invalid public amount data"
    },
    {
      "code": 6024,
      "name": "InvalidFeeAmount",
      "msg": "Invalid fee amount"
    },
    {
      "code": 6025,
      "name": "DuplicateNullifiers",
      "msg": "Duplicate nullifiers detected"
    },
    {
      "code": 6026,
      "name": "DuplicateCommitments",
      "msg": "Duplicate output commitments detected"
    },
    {
      "code": 6027,
      "name": "MissingTokenAccount",
      "msg": "Token account required for SPL token operations"
    },
    {
      "code": 6028,
      "name": "MissingTokenProgram",
      "msg": "Token program required for SPL token operations"
    },
    {
      "code": 6029,
      "name": "InvalidTokenAuthority",
      "msg": "Invalid token account authority"
    },
    {
      "code": 6030,
      "name": "RelayerMismatch",
      "msg": "Relayer account does not match ext_data.relayer"
    },
    {
      "code": 6031,
      "name": "RelayerTokenAccountMismatch",
      "msg": "Relayer token account not owned by ext_data.relayer"
    },
    {
      "code": 6032,
      "name": "RecipientTokenAccountMismatch",
      "msg": "Recipient token account not owned by ext_data.recipient"
    },
    {
      "code": 6033,
      "name": "DepositorTokenAccountMismatch",
      "msg": "Depositor token account not owned/delegated to relayer"
    },
    {
      "code": 6034,
      "name": "InvalidPrivateTransferFee",
      "msg": "Private transfer (public_amount == 0) must have fee == 0 and refund == 0"
    },
    {
      "code": 6035,
      "name": "DepositBelowMinimum",
      "msg": "Deposit amount below pool minimum"
    },
    {
      "code": 6036,
      "name": "DepositLimitExceeded",
      "msg": "Deposit amount exceeds pool maximum"
    },
    {
      "code": 6037,
      "name": "WithdrawalBelowMinimum",
      "msg": "Withdrawal amount below pool minimum"
    },
    {
      "code": 6038,
      "name": "WithdrawalLimitExceeded",
      "msg": "Withdrawal amount exceeds pool maximum"
    },
    {
      "code": 6039,
      "name": "InvalidPoolConfigRange",
      "msg": "Invalid PoolConfig range (min > max)"
    },
    {
      "code": 6040,
      "name": "ExcessiveFeeBps",
      "msg": "Fee basis points exceeds maximum (100 = 1%)"
    },
    {
      "code": 6041,
      "name": "ExcessiveFeeMargin",
      "msg": "Fee error margin exceeds maximum (5000 = 50%)"
    },
    {
      "code": 6042,
      "name": "UnauthorizedAdmin",
      "msg": "Only authorized admin can initialize"
    },
    {
      "code": 6043,
      "name": "Unauthorized",
      "msg": "Unauthorized: only admin or relayers can perform this action"
    },
    {
      "code": 6044,
      "name": "InvalidTreeId",
      "msg": "Invalid tree_id (tree does not exist or exceeds num_trees)"
    },
    {
      "code": 6045,
      "name": "TooManyTrees",
      "msg": "Maximum number of Merkle trees reached for this pool"
    },
    {
      "code": 6046,
      "name": "InvalidNullifiersForDeposit",
      "msg": "Deposits must use zero nullifiers (no notes consumed)"
    },
    {
      "code": 6047,
      "name": "ZeroNullifier",
      "msg": "Nullifier cannot be zero for withdrawals/transfers"
    },
    {
      "code": 6048,
      "name": "ZeroCommitment",
      "msg": "Output commitment cannot be zero"
    },
    {
      "code": 6049,
      "name": "InvalidTokenAccountOwner",
      "msg": "Token account must be owned by SPL Token Program"
    },
    {
      "code": 6050,
      "name": "VaultTokenAccountNotATA",
      "msg": "Vault token account must be the canonical Associated Token Account"
    },
    {
      "code": 6051,
      "name": "WithdrawalTooSmallForMinFee",
      "msg": "Withdrawal amount too small: max fee based on fee_bps would be less than min_withdrawal_fee"
    },
    {
      "code": 6052,
      "name": "InvalidNullifierMarkerForDeposit",
      "msg": "Nullifier marker account does not correspond to zero nullifier for deposits"
    },
    {
      "code": 6053,
      "name": "InsufficientDelegation",
      "msg": "Token account delegation amount insufficient for deposit"
    },
    {
      "code": 6054,
      "name": "InvalidSwapProgram",
      "msg": "Invalid swap program: must be Raydium CPMM or AMM"
    },
    {
      "code": 6055,
      "name": "InvalidRemainingAccounts",
      "msg": "Invalid remaining accounts: wrong count or ownership"
    },
    {
      "code": 6056,
      "name": "JupiterInsufficientAccounts",
      "msg": "Jupiter swap requires additional routing accounts"
    },
    {
      "code": 6057,
      "name": "JupiterInvalidInstruction",
      "msg": "Jupiter instruction data invalid or unsupported version"
    },
    {
      "code": 6058,
      "name": "InvalidSwapParams",
      "msg": "Swap params mints do not match instruction mints"
    },
    {
      "code": 6059,
      "name": "MissingTransactSwapInstruction",
      "msg": "fund_native_source must be immediately followed by transact_swap in the same transaction"
    },
    {
      "code": 6060,
      "name": "DeadlineExpired",
      "msg": "Transaction deadline has expired"
    }
  ],
  "types": [
    {
      "name": "CommitmentEvent",
      "type": {
        "kind": "struct",
        "fields": [
          {
            "name": "commitment",
            "type": {
              "array": ["u8", 32]
            }
          },
          {
            "name": "leaf_index",
            "type": "u64"
          },
          {
            "name": "new_root",
            "type": {
              "array": ["u8", 32]
            }
          },
          {
            "name": "timestamp",
            "type": "i64"
          },
          {
            "name": "mint_address",
            "type": "pubkey"
          },
          {
            "name": "tree_id",
            "type": "u16"
          },
          {
            "name": "ephemeral_public_key",
            "docs": [
              "Ephemeral Curve25519 public key for ECDH — generated fresh per note"
            ],
            "type": {
              "array": ["u8", 32]
            }
          },
          {
            "name": "encrypted_blob",
            "docs": [
              "NaCl secretbox ciphertext of (blinding[32] || amount[8])",
              "Zero bytes when relayer passes None (tests / non-recovery mode)"
            ],
            "type": {
              "array": ["u8", 80]
            }
          }
        ]
      }
    },
    {
      "name": "ExtData",
      "docs": [
        "External data that gets hashed into ext_data_hash",
        "These are public parameters that affect financial flows"
      ],
      "type": {
        "kind": "struct",
        "fields": [
          {
            "name": "recipient",
            "docs": ["Who receives withdrawal"],
            "type": "pubkey"
          },
          {
            "name": "relayer",
            "docs": ["Who submits tx (gets fee)"],
            "type": "pubkey"
          },
          {
            "name": "fee",
            "docs": ["Fee to relayer in lamports"],
            "type": "u64"
          },
          {
            "name": "refund",
            "docs": ["Refund to user in lamports"],
            "type": "u64"
          }
        ]
      }
    },
    {
      "name": "GlobalConfig",
      "type": {
        "kind": "struct",
        "fields": [
          {
            "name": "bump",
            "docs": ["PDA bump"],
            "type": "u8"
          },
          {
            "name": "admin",
            "docs": ["Admin who can configure global settings"],
            "type": "pubkey"
          }
        ]
      }
    },
    {
      "name": "MerkleTreeAccount",
      "docs": [
        "Layout tests verify 9107 bytes total with 1-byte alignment. Breaking this corrupts all accounts."
      ],
      "serialization": "bytemuckunsafe",
      "repr": {
        "kind": "rust",
        "packed": true
      },
      "type": {
        "kind": "struct",
        "fields": [
          {
            "name": "authority",
            "docs": ["Authority allowed to manage the tree (config admin)"],
            "type": "pubkey"
          },
          {
            "name": "height",
            "docs": ["Tree height (number of levels)"],
            "type": "u8"
          },
          {
            "name": "root_history_size",
            "docs": ["How many roots we track"],
            "type": "u16"
          },
          {
            "name": "next_index",
            "docs": ["Next leaf index"],
            "type": "u64"
          },
          {
            "name": "root_index",
            "docs": ["Index into root_history for the current root"],
            "type": "u64"
          },
          {
            "name": "root",
            "docs": ["Current root"],
            "type": {
              "array": ["u8", 32]
            }
          },
          {
            "name": "subtrees",
            "docs": ["Cached subtree values for each level"],
            "type": {
              "array": [
                {
                  "array": ["u8", 32]
                },
                22
              ]
            }
          },
          {
            "name": "root_history",
            "docs": ["Circular buffer of recent roots"],
            "type": {
              "array": [
                {
                  "array": ["u8", 32]
                },
                256
              ]
            }
          }
        ]
      }
    },
    {
      "name": "NoteCiphers",
      "docs": [
        "Encrypted note data passed by the relayer so users can recover funds",
        "from chain history alone if the off-chain note DB is lost.",
        "`ephemeral_public_key`: fresh Curve25519 pubkey for ECDH — reveals nothing",
        "`encrypted_blob`: NaCl secretbox of (blinding[32] || amount[8]); 40-byte",
        "plaintext → 80-byte ciphertext (24-byte nonce + 16-byte MAC)"
      ],
      "type": {
        "kind": "struct",
        "fields": [
          {
            "name": "note0_ephemeral_key",
            "type": {
              "array": ["u8", 32]
            }
          },
          {
            "name": "note0_encrypted",
            "type": {
              "array": ["u8", 80]
            }
          },
          {
            "name": "note1_ephemeral_key",
            "type": {
              "array": ["u8", 32]
            }
          },
          {
            "name": "note1_encrypted",
            "type": {
              "array": ["u8", 80]
            }
          }
        ]
      }
    },
    {
      "name": "NullifierMarker",
      "docs": [
        "Per-nullifier PDA marker (created when nullifier is spent).",
        "The nullifier itself is encoded in the PDA seeds; metadata is emitted via events."
      ],
      "type": {
        "kind": "struct",
        "fields": [
          {
            "name": "is_spent",
            "type": "bool"
          },
          {
            "name": "bump",
            "type": "u8"
          }
        ]
      }
    },
    {
      "name": "NullifierSet",
      "docs": [
        "Nullifier set metadata (actual nullifiers stored as individual PDAs)."
      ],
      "type": {
        "kind": "struct",
        "fields": [
          {
            "name": "bump",
            "type": "u8"
          },
          {
            "name": "count",
            "type": "u32"
          }
        ]
      }
    },
    {
      "name": "NullifierSpent",
      "type": {
        "kind": "struct",
        "fields": [
          {
            "name": "nullifier",
            "type": {
              "array": ["u8", 32]
            }
          },
          {
            "name": "timestamp",
            "type": "i64"
          },
          {
            "name": "mint_address",
            "type": "pubkey"
          },
          {
            "name": "tree_id",
            "type": "u16"
          }
        ]
      }
    },
    {
      "name": "PrivacyConfig",
      "type": {
        "kind": "struct",
        "fields": [
          {
            "name": "bump",
            "docs": ["PDA bump for this config"],
            "type": "u8"
          },
          {
            "name": "vault_bump",
            "docs": ["PDA bump for vault"],
            "type": "u8"
          },
          {
            "name": "admin",
            "docs": ["Admin who can configure pool and relayers"],
            "type": "pubkey"
          },
          {
            "name": "fee_bps",
            "docs": ["Fee in basis points (0–10_000) for withdrawals"],
            "type": "u16"
          },
          {
            "name": "min_withdrawal_fee",
            "docs": [
              "Minimum fee for withdrawals (in lamports) to ensure relayer compensation"
            ],
            "type": "u64"
          },
          {
            "name": "fee_error_margin_bps",
            "docs": [
              "Fee error margin in basis points (e.g., 500 = 5%)",
              "Allows fee variance to prevent timing attacks where identical fees",
              "could correlate deposits/withdrawals"
            ],
            "type": "u16"
          },
          {
            "name": "total_tvl",
            "docs": ["Total value locked (all deposits combined)"],
            "type": "u64"
          },
          {
            "name": "mint_address",
            "docs": [
              "Token mint address (for now: SOL, future: multi-token support)"
            ],
            "type": "pubkey"
          },
          {
            "name": "min_deposit_amount",
            "docs": [
              "Minimum amount allowed per deposit (in lamports/token units)"
            ],
            "type": "u64"
          },
          {
            "name": "max_deposit_amount",
            "docs": [
              "Maximum amount allowed per deposit (in lamports/token units)"
            ],
            "type": "u64"
          },
          {
            "name": "min_withdraw_amount",
            "docs": [
              "Minimum amount allowed per withdrawal (in lamports/token units)"
            ],
            "type": "u64"
          },
          {
            "name": "max_withdraw_amount",
            "docs": [
              "Maximum amount allowed per withdrawal (in lamports/token units)"
            ],
            "type": "u64"
          },
          {
            "name": "num_relayers",
            "docs": ["Relayer registry"],
            "type": "u8"
          },
          {
            "name": "relayers",
            "type": {
              "array": ["pubkey", 16]
            }
          },
          {
            "name": "num_trees",
            "docs": ["Multi-tree support: number of active Merkle trees"],
            "type": "u16"
          },
          {
            "name": "next_tree_index",
            "docs": ["Suggested tree index for next deposit (round-robin)"],
            "type": "u16"
          },
          {
            "name": "min_swap_fee",
            "docs": [
              "Minimum swap fee in destination token units (e.g., 100000 = 0.1 USDC)",
              "Ensures relayer compensation for swap transactions"
            ],
            "type": "u64"
          },
          {
            "name": "swap_fee_bps",
            "docs": [
              "Swap fee in basis points (0-10_000) of swap output amount",
              "Used with min_swap_fee: actual fee must be >= max(min_swap_fee, output * swap_fee_bps / 10000)"
            ],
            "type": "u16"
          }
        ]
      }
    },
    {
      "name": "SwapExecutedEvent",
      "type": {
        "kind": "struct",
        "fields": [
          {
            "name": "source_mint",
            "type": "pubkey"
          },
          {
            "name": "dest_mint",
            "type": "pubkey"
          },
          {
            "name": "source_tree_id",
            "type": "u16"
          },
          {
            "name": "dest_tree_id",
            "type": "u16"
          },
          {
            "name": "nullifiers",
            "type": {
              "array": [
                {
                  "array": ["u8", 32]
                },
                2
              ]
            }
          },
          {
            "name": "commitments",
            "type": {
              "array": [
                {
                  "array": ["u8", 32]
                },
                2
              ]
            }
          },
          {
            "name": "timestamp",
            "type": "i64"
          }
        ]
      }
    },
    {
      "name": "SwapExecutor",
      "docs": [
        "Ephemeral PDA that holds tokens during swap, created and closed atomically"
      ],
      "type": {
        "kind": "struct",
        "fields": [
          {
            "name": "source_mint",
            "type": "pubkey"
          },
          {
            "name": "dest_mint",
            "type": "pubkey"
          },
          {
            "name": "nullifier",
            "type": {
              "array": ["u8", 32]
            }
          },
          {
            "name": "bump",
            "type": "u8"
          },
          {
            "name": "swap_amount",
            "docs": [
              "Swap amount stored by fund_native_source for validation in transact_swap.",
              "Zero when executor was created directly in transact_swap (relayer-float path)."
            ],
            "type": "u64"
          },
          {
            "name": "is_prefunded",
            "docs": [
              "1 when executor was pre-funded by fund_native_source (vault already debited).",
              "0 for the single-instruction relayer-float path (backward compatible)."
            ],
            "type": "u8"
          },
          {
            "name": "relayer",
            "docs": [
              "Relayer who created this executor — only they may call reclaim_stale_executor."
            ],
            "type": "pubkey"
          }
        ]
      }
    },
    {
      "name": "SwapParams",
      "docs": [
        "Swap parameters committed to in the ZK proof.",
        "`source_mint` and `dest_mint` are passed as separate `transact_swap` args",
        "and supplied to `hash()` at call time."
      ],
      "type": {
        "kind": "struct",
        "fields": [
          {
            "name": "min_amount_out",
            "type": "u64"
          },
          {
            "name": "deadline",
            "type": "i64"
          },
          {
            "name": "dest_amount",
            "docs": [
              "Amount of destination tokens the user commits to receiving.",
              "Included in swapParamsHash — cryptographically binds the ZK circuit's",
              "destAmount to the on-chain vault deposit, preventing an attacker from",
              "encoding an inflated destination note while receiving a tiny swap output."
            ],
            "type": "u64"
          },
          {
            "name": "swap_data_hash",
            "docs": [
              "SHA-256 hash of the raw swap instruction data (swap_data).",
              "Binds the exact DEX instruction bytes into the ZK proof so the relayer",
              "cannot substitute different swap_data (e.g. 0% slippage) after the user",
              "has generated their proof.  Set to [0u8;32] for CPMM/AMM swaps, which",
              "already enforce dex_min_out by direct instruction decoding."
            ],
            "type": {
              "array": ["u8", 32]
            }
          }
        ]
      }
    },
    {
      "name": "SwapProof",
      "docs": [
        "Proof for swap transaction circuit (2-in-2-out cross-pool UTXO model)"
      ],
      "type": {
        "kind": "struct",
        "fields": [
          {
            "name": "proof_a",
            "type": {
              "array": ["u8", 64]
            }
          },
          {
            "name": "proof_b",
            "type": {
              "array": ["u8", 128]
            }
          },
          {
            "name": "proof_c",
            "type": {
              "array": ["u8", 64]
            }
          }
        ]
      }
    },
    {
      "name": "TransactionProof",
      "docs": [
        "Proof for new UTXO transaction circuit (same structure, different VK)"
      ],
      "type": {
        "kind": "struct",
        "fields": [
          {
            "name": "proof_a",
            "type": {
              "array": ["u8", 64]
            }
          },
          {
            "name": "proof_b",
            "type": {
              "array": ["u8", 128]
            }
          },
          {
            "name": "proof_c",
            "type": {
              "array": ["u8", 64]
            }
          }
        ]
      }
    },
    {
      "name": "Vault",
      "type": {
        "kind": "struct",
        "fields": [
          {
            "name": "bump",
            "docs": ["PDA bump for this vault"],
            "type": "u8"
          }
        ]
      }
    }
  ]
}
