{
  "address": "7q7cns2MDf2sNVtwGHczub2oTrz8YjqFutEHHJZuQKqc",
  "metadata": {
    "name": "rwa_exit",
    "version": "0.1.0",
    "spec": "0.1.0",
    "description": "RWA exit program (claim-based redemption)"
  },
  "instructions": [
    {
      "name": "claim",
      "docs": [
        "Holder claim: burn `amount` RWA tokens, receive the pro-rata payout. Signed by the",
        "holder. Payout comes from the exit escrow (a payout-mint token account owned by the",
        "ExitState PDA, funded before claims open).",
        "",
        "payout (payout smallest units) =",
        "amount * final_price_cents * 10^payout_decimals / (100 * 10^rwa_decimals)",
        "where final_price_cents is USD cents per WHOLE rwa token. Computed in u128."
      ],
      "discriminator": [
        62,
        198,
        214,
        193,
        213,
        159,
        108,
        210
      ],
      "accounts": [
        {
          "name": "holder",
          "signer": true
        },
        {
          "name": "state",
          "writable": true,
          "pda": {
            "seeds": [
              {
                "kind": "const",
                "value": [
                  101,
                  120,
                  105,
                  116
                ]
              },
              {
                "kind": "account",
                "path": "state.mint",
                "account": "ExitState"
              }
            ]
          }
        },
        {
          "name": "rwa_mint",
          "writable": true
        },
        {
          "name": "holder_rwa_account",
          "writable": true
        },
        {
          "name": "payout_mint"
        },
        {
          "name": "escrow_payout_account",
          "writable": true
        },
        {
          "name": "holder_payout_account",
          "writable": true
        },
        {
          "name": "holder_clock",
          "docs": [
            "The holder's accrual clock, settled before the burn so the coupon they earned while",
            "holding is banked rather than lost with their balance. Optional: mints without the",
            "accrual hook have no clock. See `claim`."
          ],
          "writable": true,
          "optional": true
        },
        {
          "name": "accrual_program",
          "optional": true,
          "address": "BhQAF2HBBFvtpG4dYYkqEtzpndSQGHzsNCBns8t6XXkw"
        },
        {
          "name": "rwa_token_program",
          "docs": [
            "Token program for the RWA mint (Token-2022)."
          ]
        },
        {
          "name": "payout_token_program",
          "docs": [
            "Token program for the payout mint (SPL Token or Token-2022)."
          ]
        }
      ],
      "args": [
        {
          "name": "amount",
          "type": "u64"
        }
      ]
    },
    {
      "name": "init_config",
      "docs": [
        "Bind this program to its governing authority. Callable ONCE, and only by the program's",
        "current upgrade authority.",
        "",
        "Gating on the upgrade authority is what makes the bootstrap safe: at deploy time that is",
        "the deploy wallet, and after the Squads handoff it is the multisig vault. The only party",
        "who can claim a program's Config is therefore the same party who can already replace its",
        "bytecode. A permissionless `init_config` would simply move the first-caller-wins hole",
        "from the per-asset PDAs up to the global one."
      ],
      "discriminator": [
        23,
        235,
        115,
        232,
        168,
        96,
        1,
        231
      ],
      "accounts": [
        {
          "name": "payer",
          "writable": true,
          "signer": true
        },
        {
          "name": "upgrade_authority",
          "docs": [
            "Must be this program's current upgrade authority."
          ],
          "signer": true
        },
        {
          "name": "program_data"
        },
        {
          "name": "config",
          "writable": true,
          "pda": {
            "seeds": [
              {
                "kind": "const",
                "value": [
                  99,
                  111,
                  110,
                  102,
                  105,
                  103
                ]
              }
            ]
          }
        },
        {
          "name": "system_program",
          "address": "11111111111111111111111111111111"
        }
      ],
      "args": [
        {
          "name": "authority",
          "type": "pubkey"
        },
        {
          "name": "operator",
          "type": "pubkey"
        }
      ]
    },
    {
      "name": "initiate_exit",
      "docs": [
        "Begin an exit: fix the redemption price and open claims. Admin (multisig) only.",
        "Assumes the vault has been funded with enough payout token for the supply.",
        "",
        "`deadline` is the unix timestamp after which claims close and `sweep` may run.",
        "**0 means no deadline** — claims stay open indefinitely, which is the historical",
        "behaviour and the safe default. Redemption is a holder's principal, not a periodic",
        "coupon, so an expiry is a deliberate wind-down decision for governance to make per",
        "asset, never something to switch on by accident.",
        "",
        "`treasury` is the sweep destination. It was previously never initialised at all — the",
        "field existed, `set_treasury` wrote it, and nothing ever read it.",
        "`final_price_cents` is an OVERRIDE, not the normal input. Pass 0 and the price is derived",
        "from the Market's Asset PDA at the moment the exit opens.",
        "",
        "It used to be the only input: a governance-gated number typed by a human, never",
        "cross-checked against anything. Under accrual-in-price that is the single most",
        "consequential number in the instrument's life — it is principal plus every day of accrued",
        "interest, and it is unrecoverable once holders start claiming against it. Deriving by",
        "default and overriding by exception is the right way round; the override stays because a",
        "defaulted or impaired wind-down genuinely does not redeem at the accreted price.",
        "A wind-down halts trading and pays holders out. A market maker with a queued redemption",
        "has already delivered its stock and is owed cash at a locked price — start an exit",
        "underneath it and it becomes a creditor of a closing book, its inventory counted as the",
        "vault's.",
        "",
        "Bounded rather than a veto: past force_resolve_window the redemption settles one way or",
        "the other without anyone's permission, so the venue goes flat on its own."
      ],
      "discriminator": [
        15,
        194,
        144,
        7,
        247,
        94,
        48,
        161
      ],
      "accounts": [
        {
          "name": "config",
          "pda": {
            "seeds": [
              {
                "kind": "const",
                "value": [
                  99,
                  111,
                  110,
                  102,
                  105,
                  103
                ]
              }
            ]
          }
        },
        {
          "name": "venue_link",
          "docs": [
            "rwa_market's record of which program holds venue state.",
            "",
            "MANDATORY, and that is the whole fix. `venue` below used to be an `Option`, which made",
            "the flat-before-exit rule opt-in: `backend/chain/solana/encode.js` never passed the",
            "account, so the check had never once executed. An optional account is an optional",
            "check, and a caller winding an asset down over a maker's head is exactly the caller",
            "who would omit it.",
            "",
            "Reading the link rather than a compiled-in id is the same reason `rwa_market::sell`",
            "does: the venue deployment is governance state, not a constant. It must therefore be",
            "set (§12.1 step 5) before this program's upgrade goes live, or `initiate_exit` cannot be",
            "called at all — which is the safe direction to fail in."
          ],
          "pda": {
            "seeds": [
              {
                "kind": "const",
                "value": [
                  118,
                  101,
                  110,
                  117,
                  101,
                  95,
                  112,
                  114,
                  111,
                  103,
                  114,
                  97,
                  109
                ]
              }
            ],
            "program": {
              "kind": "const",
              "value": [
                221,
                159,
                24,
                192,
                16,
                176,
                255,
                9,
                119,
                197,
                127,
                62,
                29,
                18,
                21,
                45,
                59,
                235,
                199,
                95,
                185,
                250,
                187,
                236,
                205,
                182,
                96,
                187,
                160,
                214,
                11,
                217
              ]
            }
          }
        },
        {
          "name": "venue",
          "docs": [
            "the program `venue_link` names — so a caller cannot substitute a flat venue for a busy",
            "one — and it may legitimately not exist, which is how an asset with no venue passes."
          ]
        },
        {
          "name": "admin",
          "docs": [
            "C-4: this was an unconstrained Signer, so anyone could open the exit for a mint with an",
            "arbitrary `final_price_cents` and drain the escrow by burning one smallest unit."
          ],
          "signer": true
        },
        {
          "name": "mint"
        },
        {
          "name": "payout_mint",
          "docs": [
            "Payout token mint (the RWA token's payout_token). Recorded for claim()."
          ]
        },
        {
          "name": "asset",
          "docs": [
            "Read-only: the Market listing, so the exit price is derived rather than typed.",
            "",
            "OPTIONAL, deliberately. Redemption is the last-resort path and must never be hostage to",
            "the trading path still existing — an asset can be delisted, and an impaired or defaulted",
            "wind-down does not redeem at the accreted price anyway. So: supply it and pass 0 to",
            "derive (what the encoder always does), or omit it and pass an explicit override.",
            "",
            "Boxed for the same reason Trade's asset is: Anchor deserialises onto the stack, and this",
            "context also runs an `init`."
          ],
          "optional": true
        },
        {
          "name": "state",
          "writable": true,
          "pda": {
            "seeds": [
              {
                "kind": "const",
                "value": [
                  101,
                  120,
                  105,
                  116
                ]
              },
              {
                "kind": "account",
                "path": "mint"
              }
            ]
          }
        },
        {
          "name": "payer",
          "writable": true,
          "signer": true
        },
        {
          "name": "system_program",
          "address": "11111111111111111111111111111111"
        }
      ],
      "args": [
        {
          "name": "final_price_cents",
          "type": "u64"
        },
        {
          "name": "treasury",
          "type": "pubkey"
        },
        {
          "name": "deadline",
          "type": "i64"
        }
      ]
    },
    {
      "name": "set_config_authority",
      "docs": [
        "Rotate the governing authority (migrating to a new Squads multisig) and/or the operator",
        "hot key. Current authority only.",
        "",
        "Every per-asset account created BEFORE a rotation keeps the old admin recorded in its own",
        "state — this only changes who may create new ones. Rotating existing assets is a separate",
        "concern (see M-1 in SECURITY-AUDIT.md)."
      ],
      "discriminator": [
        16,
        200,
        212,
        18,
        95,
        43,
        107,
        89
      ],
      "accounts": [
        {
          "name": "authority",
          "signer": true
        },
        {
          "name": "config",
          "writable": true,
          "pda": {
            "seeds": [
              {
                "kind": "const",
                "value": [
                  99,
                  111,
                  110,
                  102,
                  105,
                  103
                ]
              }
            ]
          }
        }
      ],
      "args": [
        {
          "name": "authority",
          "type": "pubkey"
        },
        {
          "name": "operator",
          "type": "pubkey"
        }
      ]
    },
    {
      "name": "set_treasury",
      "docs": [
        "Update treasury (sweep destination). Admin only."
      ],
      "discriminator": [
        57,
        97,
        196,
        95,
        195,
        206,
        106,
        136
      ],
      "accounts": [
        {
          "name": "admin",
          "signer": true
        },
        {
          "name": "state",
          "writable": true,
          "pda": {
            "seeds": [
              {
                "kind": "const",
                "value": [
                  101,
                  120,
                  105,
                  116
                ]
              },
              {
                "kind": "account",
                "path": "state.mint",
                "account": "ExitState"
              }
            ]
          }
        }
      ],
      "args": [
        {
          "name": "treasury",
          "type": "pubkey"
        }
      ]
    },
    {
      "name": "sweep",
      "docs": [
        "Move whatever is left in the exit escrow to `treasury` and close the exit.",
        "Admin (multisig) only. The instruction the module doc promised and never had",
        "(SECURITY-AUDIT H-4).",
        "",
        "Allowed in exactly two situations, and the distinction matters:",
        "",
        "1. `completed` — every token has been redeemed (supply hit 0). Whatever remains is",
        "over-funding plus rounding dust, since `claim` always rounds DOWN. No holder can",
        "be harmed, because there is no holder left. This was the stranded case: `claim`",
        "is blocked by `NotClaimable` once completed, so the residue had no exit path at",
        "all and was locked in the PDA forever.",
        "2. past a non-zero `deadline` — a governance-chosen wind-down. Holders who did not",
        "redeem in the window lose the ability to; that is why `deadline` is opt-in and",
        "defaults to 0.",
        "",
        "Sweeping sets `completed`, so it is terminal either way."
      ],
      "discriminator": [
        40,
        23,
        234,
        175,
        14,
        61,
        154,
        177
      ],
      "accounts": [
        {
          "name": "admin",
          "signer": true
        },
        {
          "name": "state",
          "writable": true,
          "pda": {
            "seeds": [
              {
                "kind": "const",
                "value": [
                  101,
                  120,
                  105,
                  116
                ]
              },
              {
                "kind": "account",
                "path": "state.mint",
                "account": "ExitState"
              }
            ]
          }
        },
        {
          "name": "payout_mint"
        },
        {
          "name": "escrow_payout_account",
          "writable": true
        },
        {
          "name": "treasury_payout_account",
          "writable": true
        },
        {
          "name": "payout_token_program"
        }
      ],
      "args": []
    },
    {
      "name": "sync_admin",
      "docs": [
        "Re-point this account's `admin` at the CURRENT `config.authority`.",
        "",
        "SECURITY-AUDIT M-1: every per-asset admin was written once at creation and never again,",
        "so rotating the Squad left every existing asset pointing at the old multisig — and the",
        "more assets exist, the worse that gets. `set_config_authority` moves the program-level",
        "authority; this carries the change down to accounts that already exist.",
        "",
        "The new value is READ FROM CONFIG, never supplied by the caller, so this can only ever",
        "converge an account onto the current authority. It cannot redirect one anywhere else,",
        "which is why gating it on the operator is enough — there is no value here to abuse."
      ],
      "discriminator": [
        39,
        26,
        200,
        133,
        62,
        114,
        42,
        235
      ],
      "accounts": [
        {
          "name": "config",
          "pda": {
            "seeds": [
              {
                "kind": "const",
                "value": [
                  99,
                  111,
                  110,
                  102,
                  105,
                  103
                ]
              }
            ]
          }
        },
        {
          "name": "signer",
          "signer": true
        },
        {
          "name": "state",
          "writable": true,
          "pda": {
            "seeds": [
              {
                "kind": "const",
                "value": [
                  101,
                  120,
                  105,
                  116
                ]
              },
              {
                "kind": "account",
                "path": "state.mint",
                "account": "ExitState"
              }
            ]
          }
        }
      ],
      "args": []
    }
  ],
  "accounts": [
    {
      "name": "AccrualClock",
      "discriminator": [
        167,
        73,
        169,
        165,
        84,
        217,
        122,
        35
      ]
    },
    {
      "name": "Asset",
      "discriminator": [
        234,
        180,
        241,
        252,
        139,
        224,
        160,
        8
      ]
    },
    {
      "name": "Config",
      "discriminator": [
        155,
        12,
        170,
        224,
        30,
        250,
        204,
        130
      ]
    },
    {
      "name": "ExitState",
      "discriminator": [
        228,
        34,
        202,
        229,
        148,
        42,
        89,
        194
      ]
    },
    {
      "name": "VenueLink",
      "discriminator": [
        197,
        70,
        34,
        152,
        183,
        67,
        68,
        38
      ]
    }
  ],
  "events": [
    {
      "name": "AdminSynced",
      "discriminator": [
        31,
        149,
        231,
        47,
        182,
        14,
        227,
        231
      ]
    },
    {
      "name": "Claimed",
      "discriminator": [
        217,
        192,
        123,
        72,
        108,
        150,
        248,
        33
      ]
    },
    {
      "name": "ConfigSet",
      "discriminator": [
        15,
        104,
        59,
        16,
        236,
        241,
        8,
        6
      ]
    },
    {
      "name": "ExitInitiated",
      "discriminator": [
        231,
        181,
        41,
        200,
        30,
        79,
        20,
        73
      ]
    },
    {
      "name": "ExitSwept",
      "discriminator": [
        209,
        185,
        39,
        190,
        12,
        231,
        21,
        81
      ]
    }
  ],
  "errors": [
    {
      "code": 6000,
      "name": "InvalidExitPrice",
      "msg": "derived exit price is zero; pass an explicit override"
    },
    {
      "code": 6001,
      "name": "MissingAssetForDerivedPrice",
      "msg": "price 0 means derive, but no market asset account was supplied"
    },
    {
      "code": 6002,
      "name": "WrongMarketAsset",
      "msg": "supplied market asset is not the canonical Asset PDA for this mint"
    },
    {
      "code": 6003,
      "name": "Unauthorized",
      "msg": "caller is not authorized for this action"
    },
    {
      "code": 6004,
      "name": "AlreadyInitiated",
      "msg": "exit already initiated"
    },
    {
      "code": 6005,
      "name": "NotClaimable",
      "msg": "exit is not open for claims"
    },
    {
      "code": 6006,
      "name": "MathOverflow",
      "msg": "payout math overflow"
    },
    {
      "code": 6007,
      "name": "InvalidAmount",
      "msg": "amount must be greater than zero"
    },
    {
      "code": 6008,
      "name": "ZeroPayout",
      "msg": "this amount redeems to zero payout; redeem a larger amount"
    },
    {
      "code": 6009,
      "name": "DeadlineInPast",
      "msg": "deadline must be in the future, or 0 for no deadline"
    },
    {
      "code": 6010,
      "name": "ClaimWindowClosed",
      "msg": "the claim window for this exit has closed"
    },
    {
      "code": 6011,
      "name": "SweepNotAllowed",
      "msg": "sweep needs full redemption or a passed deadline"
    },
    {
      "code": 6012,
      "name": "WrongTreasury",
      "msg": "treasury account owner does not match the recorded treasury"
    },
    {
      "code": 6013,
      "name": "VenueNotFlat",
      "msg": "the market-maker venue still owes a redemption"
    },
    {
      "code": 6014,
      "name": "VenueNotPaused",
      "msg": "pause the market-maker venue before opening the exit"
    },
    {
      "code": 6015,
      "name": "AssetStillActive",
      "msg": "halt the asset on the market before opening the exit"
    }
  ],
  "types": [
    {
      "name": "AccrualClock",
      "docs": [
        "Per-holder, per-mint accrual state. The Solana twin of EVM's `lastPayoutTimestamp`",
        "plus the balance-weighting that `_afterTokenTransfer` performs inline."
      ],
      "type": {
        "kind": "struct",
        "fields": [
          {
            "name": "owner",
            "type": "pubkey"
          },
          {
            "name": "mint",
            "type": "pubkey"
          },
          {
            "name": "last_settled_ts",
            "docs": [
              "Last time accrual was banked into `accrued_balance_seconds`."
            ],
            "type": "i64"
          },
          {
            "name": "accrued_balance_seconds",
            "docs": [
              "Σ(balance × seconds held), in smallest units × seconds."
            ],
            "type": "u128"
          },
          {
            "name": "bump",
            "type": "u8"
          }
        ]
      }
    },
    {
      "name": "AdminSynced",
      "type": {
        "kind": "struct",
        "fields": [
          {
            "name": "previous",
            "type": "pubkey"
          },
          {
            "name": "current",
            "type": "pubkey"
          }
        ]
      }
    },
    {
      "name": "Asset",
      "docs": [
        "LAYOUT IS READ BY BYTE OFFSET OUTSIDE THIS PROGRAM. price_cents @168, rate_bps @226,",
        "checkpoint_price_scaled @230, checkpoint_at @246, maturity_ts @262 are hardcoded in",
        "solana/scripts/price-feed-job.js (the Switchboard feed a lending market prices from) and in",
        "ge-onchain-frontend utils/solana/rwaMarket.js (displayed prices and quotes). Append only. A",
        "reordered or inserted field yields a plausible wrong price, not an error, in both places."
      ],
      "type": {
        "kind": "struct",
        "fields": [
          {
            "name": "mint",
            "type": "pubkey"
          },
          {
            "name": "vault",
            "type": "pubkey"
          },
          {
            "name": "payout_mint",
            "type": "pubkey"
          },
          {
            "name": "admin",
            "type": "pubkey"
          },
          {
            "name": "price_updater",
            "type": "pubkey"
          },
          {
            "name": "price_cents",
            "type": "u64"
          },
          {
            "name": "fee_bps",
            "type": "u16"
          },
          {
            "name": "is_active",
            "type": "bool"
          },
          {
            "name": "max_per_tx",
            "type": "u64"
          },
          {
            "name": "max_per_user",
            "type": "u64"
          },
          {
            "name": "bump",
            "type": "u8"
          },
          {
            "name": "last_price_update_ts",
            "docs": [
              "When `set_price` last ran. 0 = never (a freshly listed asset's first update is free)."
            ],
            "type": "i64"
          },
          {
            "name": "window_start_ts",
            "docs": [
              "Start of the current rate-limit window, and the price it opened at. Total movement away",
              "from the anchor is what the window cap bounds; the window re-anchors once it expires."
            ],
            "type": "i64"
          },
          {
            "name": "window_anchor_cents",
            "type": "u64"
          },
          {
            "name": "min_update_interval_secs",
            "docs": [
              "Per-asset overrides. 0 = use the module default."
            ],
            "type": "u32"
          },
          {
            "name": "max_window_deviation_bps",
            "type": "u16"
          },
          {
            "name": "rate_bps",
            "docs": [
              "Annual accrual rate in bps, signed (negative = amortising down). 0 = no accrual."
            ],
            "type": "i32"
          },
          {
            "name": "checkpoint_price_scaled",
            "docs": [
              "Checkpoint price at cents x ACCRUAL_SCALE. See C-10 on base_payout."
            ],
            "type": "u128"
          },
          {
            "name": "checkpoint_at",
            "docs": [
              "When the checkpoint was taken. Accrual runs from here. 0 = never checkpointed."
            ],
            "type": "i64"
          },
          {
            "name": "last_rate_update_ts",
            "docs": [
              "When set_rate last ran. 0 = never."
            ],
            "type": "i64"
          },
          {
            "name": "maturity_ts",
            "docs": [
              "Cached maturity, read from TokenMeta by set_rate. 0 = no maturity. Cached so the C-6",
              "clamp costs nothing on the trading path; safe because maturity_date is write-once."
            ],
            "type": "i64"
          },
          {
            "name": "allowance_spent_bps",
            "docs": [
              "Allowance used by price updates, in bps of the price before each update, summed."
            ],
            "type": "u16"
          },
          {
            "name": "allowance_at",
            "docs": [
              "When allowance_spent_bps was last written (unix seconds). 0 = never: full allowance."
            ],
            "type": "u32"
          }
        ]
      }
    },
    {
      "name": "Claimed",
      "type": {
        "kind": "struct",
        "fields": [
          {
            "name": "mint",
            "type": "pubkey"
          },
          {
            "name": "holder",
            "type": "pubkey"
          },
          {
            "name": "amount",
            "type": "u64"
          }
        ]
      }
    },
    {
      "name": "Config",
      "docs": [
        "Program-level authority. One per program, seeds [\"config\"].",
        "",
        "Exists because every per-asset `init` instruction used to accept an unconstrained `Signer`",
        "as \"admin\" and write it straight into the new account, making whoever called first the",
        "owner of a PDA our own flow would later fund. See C-1..C-5 in SECURITY-AUDIT.md."
      ],
      "type": {
        "kind": "struct",
        "fields": [
          {
            "name": "authority",
            "docs": [
              "Governing authority — the Squads vault PDA. Written into every per-asset account's",
              "admin/owner field, so a caller can never nominate itself."
            ],
            "type": "pubkey"
          },
          {
            "name": "operator",
            "docs": [
              "Operator hot key. May CREATE per-asset accounts and pay their rent, but never chooses",
              "who controls them."
            ],
            "type": "pubkey"
          },
          {
            "name": "bump",
            "type": "u8"
          }
        ]
      }
    },
    {
      "name": "ConfigSet",
      "type": {
        "kind": "struct",
        "fields": [
          {
            "name": "authority",
            "type": "pubkey"
          },
          {
            "name": "operator",
            "type": "pubkey"
          }
        ]
      }
    },
    {
      "name": "ExitInitiated",
      "type": {
        "kind": "struct",
        "fields": [
          {
            "name": "mint",
            "type": "pubkey"
          },
          {
            "name": "final_price_cents",
            "type": "u64"
          },
          {
            "name": "deadline",
            "type": "i64"
          },
          {
            "name": "treasury",
            "type": "pubkey"
          }
        ]
      }
    },
    {
      "name": "ExitState",
      "type": {
        "kind": "struct",
        "fields": [
          {
            "name": "mint",
            "type": "pubkey"
          },
          {
            "name": "payout_mint",
            "type": "pubkey"
          },
          {
            "name": "admin",
            "type": "pubkey"
          },
          {
            "name": "treasury",
            "type": "pubkey"
          },
          {
            "name": "final_price_cents",
            "type": "u64"
          },
          {
            "name": "initiated",
            "type": "bool"
          },
          {
            "name": "completed",
            "type": "bool"
          },
          {
            "name": "total_paid_out",
            "type": "u64"
          },
          {
            "name": "total_burned",
            "type": "u64"
          },
          {
            "name": "bump",
            "type": "u8"
          },
          {
            "name": "deadline",
            "docs": [
              "Unix timestamp after which claims close and `sweep` may run. 0 = no deadline, claims",
              "never expire. Redemption returns a holder's principal, so an expiry is opt-in."
            ],
            "type": "i64"
          }
        ]
      }
    },
    {
      "name": "ExitSwept",
      "type": {
        "kind": "struct",
        "fields": [
          {
            "name": "mint",
            "type": "pubkey"
          },
          {
            "name": "amount",
            "type": "u64"
          }
        ]
      }
    },
    {
      "name": "VenueLink",
      "docs": [
        "The rwa_venue deployment this market defers to. See `set_venue_program`."
      ],
      "type": {
        "kind": "struct",
        "fields": [
          {
            "name": "venue_program",
            "type": "pubkey"
          },
          {
            "name": "bump",
            "type": "u8"
          }
        ]
      }
    }
  ]
}