TypeScript SDK

Program Upgrade 0.1.11

Upgrade to SDK 2.8.0 before September 4, 2026 — banks moving to the new oracle setups will not decode on older SDKs

Upgrade to @0dotxyz/p0-ts-sdk@^2.8.0 before Friday, September 4, 2026. From that date banks start moving to the new 0.1.11 oracle setups. SDK 2.7.x and older throw while decoding any such bank, which fails Project0Client.initialize and every bank read — not just actions on that bank. The upgrade is additive: no code changes required.

TL;DR: program 0.1.11 adds nine oracle setups that do not depend on Switchboard — Kamino Scope feeds, and exchange-rate pricing for mSOL, SPL/Sanctum LSTs and Exponent PTs. Existing instructions and account layouts are untouched. What breaks is decoding: older SDKs don't know the new enum values, so one migrated bank stops them loading banks at all. SDK >= 2.8.0 decodes and prices every setup, includes the extra accounts in health checks, and is padded so future setups degrade gracefully instead of throwing.

What changes

  • Nine new OracleSetup variants (18–26): Scope, PythMSOL, KaminoMSOL, JuplendMSOL, PythLST, KaminoLST, JuplendLST, PTPyth, PTFixed. How each one prices is on Oracles.
  • BankConfig.scope_entry_index (u16) replaces two padding bytes. Same size, no other layout change.
  • Every existing instruction keeps its accounts and arguments. Two admin instructions are added (lending_pool_configure_bank_oracle_scope, lending_pool_set_oracle_price), replacing lending_pool_set_fixed_oracle_price.
  • New error codes 61366139 and 68006803; 6132 renamed to UseSetOraclePrice. See Errors.

The breaking change

A bank's oracle setup is a one-byte enum and Anchor resolves it against the IDL. The IDL in SDK <= 2.7.4 lists 18 variants, so a setup byte of 18 or higher makes the coder throw:

TypeError: Cannot read properties of null (reading 'property')

Project0Client.initialize decodes every bank in the group, so a single migrated bank breaks initialization for everyone on an older SDK. This affects reads, and it is triggered by the first bank migration — not by the program deploy.

What you must do

Using Project0Client or the SDK builders — upgrade. Nothing else. initialize passes the new pricing options through, computeHealthAccountMetas appends the extra accounts, and unknown future setups parse to OracleSetup.Unknown (zero price) instead of throwing.

Calling fetchOracleData directly — pass the two new, optional option blocks, or banks on the new setups price at zero with a warning:

const { bankOraclePriceMap } = await fetchOracleData(banks, {
  pythOpts: { mode: "on-chain", connection },
  swbOpts: { mode: "on-chain", connection },
  scopeOpts: { mode: "on-chain", connection },
  oracleMultiplierOpts: { mode: "on-chain", connection },
});

The exchange rate is baked into the price: an mSOL bank's OraclePrice is mSOL/USD, matching what the program caches on the bank. Venue receipt-token rates stay in assetShareValueMultiplierByBank, as before. See Banks & Prices.

Hand-rolling remainingAccounts — the new setups need their pricing account after the oracle: oracleKeys[1] for PythMSOL / PythLST / PTPyth, oracleKeys[2] for the Kamino and JupLend variants. Scope and PTFixed keep the [bank, oracleKeys[0]] shape. Prefer computeHealthAccountMetas.

Decoding accounts yourself — use the SDK's bundled 0.1.11 IDL, passed through new Program(...). Do not fetch the IDL from chain; the on-chain IDL account is not kept current.

Serving prices or multipliers from your own API — return prices the way the program caches them (rate included, venue rate excluded). In API mode the SDK only rejects non-numeric multipliers, so your endpoint must return program-valid rates.

Testing on staging

getConfig("staging-mainnet-clone") already runs 0.1.11 with one bank per new family:

BankSetup
Dt8xUxXxUgVpg74ke5WB4XBogmv1E4TM7zRfwEnbm3SFwSOL · Scope
Bf2QXbRZPGtDHvd4AVoFDb4jNjMSDjsPGDaboSHkzE21mSOL · PythMSOL
ZEK4wkNUMbU2ALzKSfb888yZwugypJY466snSj6CuK6jitoSOL · PythLST
4jNGCy6SvEY2itfCrvTGQC65mKHcwZgoahiZjtvmBizKPT-hyUSD · PTFixed
7Np6qLQg691RUM64S4J63Py7dRNGMKho3Fh9UU5Q9YZwPT-hyloSOL · PTPyth

Troubleshooting

SymptomCauseFix
TypeError: Cannot read properties of null (reading 'property') on initialize or any bank decodeSDK <= 2.7.4 meeting a 0.1.11 bankUpgrade to >= 2.8.0
Banks priced at 0 plus a no scopeOpts / no oracleMultiplierOpts warningDirect fetchOracleData call without the new optionsPass both options
WrongNumberOfOracleAccounts / WrongOracleAccountKeys on borrow or withdrawHand-built remainingAccounts missing the pricing accountUse computeHealthAccountMetas
ScopeStalePrice (6802) or StakePoolStale (6139)Feed entry or stake pool not refreshedWait; the SDK prices the bank at zero meanwhile

On this page