Sickle Sol

Off-chain code

This layer builds, checks, signs, and sends the transactions that call the Sickle program, and it tests the program from the outside.

Note: Every path:line below is relative to the repository root. Nothing in this layer links the Rust crate. Every module reads the program through the Anchor IDL.

management-ui/ is a legacy compatibility tree, not the application serving so.vf.at; vfat-io/sickle-sol-ui owns that surface and its deployment. The legacy tree cannot yet be deleted because both Meteora canary adapters bundle its action builder and preparation modules (deploy/meteora-keeper/meteora-canary-adapter.ts:20-21, deploy/meteora-keeper/meteora-ui-acceptance-adapter.ts:27-28), and root tests consume its IDL and fixtures. Treat its routes and pages as retirement scope, not as the target for a live UI fix.

Files

The layer has 5 parts. The tables below give one row per file. The last column says whether the file is pure or whether it touches RPC, an HTTP API, a signer, or the process environment.

Builder: scripts/builder/, shared timing

PathLinesPurposePure or I/O
shared/intent-timing.ts8Authorization validity, quote age, and pre-expiry send marginpure
scripts/builder/pdas.ts251Seeds, program IDs, and every PDA and ATA derivationpure
scripts/builder/common-accounts.ts120Shared pool-token, fee-collector, intent, event, and account-coder primitivespure
scripts/builder/protocol-account.ts7Shared foreign-account decode errorpure
scripts/builder/accounts.ts1036Orca and authorization account maps in Anchor camelCasepure
scripts/builder/instructions.ts943Anchor .instruction() wrappers for Orca, swap, and authorization instructionspure, plus 2 RPC helpers for ATAs
scripts/builder/orca.ts905Orca account decoders, tick math, tick-array PDAs, placement formulapure
scripts/builder/liquidity.ts163Q64.64 sqrt-price and liquidity mathpure
scripts/builder/zap.ts135Sizes an add-liquidity instruction from two balancespure
scripts/builder/fees.ts38Fee index constants and floor fee mathpure
scripts/builder/transfer-fees.ts159Token-2022 transfer-fee math and schedule loadpure, plus 1 RPC loader
scripts/builder/jupiter.ts400Swap planner, route ceilings, Jupiter JSON to instructionpure
scripts/builder/jupiter-api.ts191HTTP client for Jupiter /quote and /swap-instructionsHTTP API
scripts/builder/clmm-owner-rebalance.ts230Shared CLMM owner drain, optional swap, and re-add pipelineRPC config and optional quote
scripts/builder/clmm-intent-composer.ts361Shared CLMM keeper authorization guards and signed swap compositionpure
scripts/builder/flows.ts358Orca pool/position load and owner-rebalance adapter, quote freeze, simulateRPC
scripts/builder/intent-codec.ts655Byte codec, canonical form, digest, and signature for the authorizationpure
scripts/builder/intent.ts1603Authorization planner and the Orca keeper composers for rebalance, compound, and exitRPC in loaders, pure composers
scripts/builder/intent-packets.ts266Freezes transaction A, transaction B, and the cancellation before A is sentRPC
scripts/builder/intent-cleanup.ts78Cancels or expires scanned authorizations with a recheckRPC
scripts/builder/executor-authorization.ts31Maps the executor role to the optional global keeper accountpure
scripts/builder/canary-session.ts70Requires 3 distinct keys for the canarypure
scripts/builder/compound-credit.ts1314Same-mint reward credit for compound, both CLMM venuespure planners, plus 2 RPC loaders
scripts/builder/budgets.ts48Compute-unit budgets and the Meteora simulation limitpure
scripts/builder/alt.ts315Lookup-table address selection, create, extend, fetchpure selection, RPC create and fetch
scripts/builder/send.ts423Compute-budget instructions, packet size check, single send, retry classificationpure helpers, RPC send loop
scripts/builder/dry-run.ts381Simulates a canary step and prices its fee and rentRPC
scripts/builder/raydium.ts811Raydium account decoders, tick math, bitmap extension, placement formulapure
scripts/builder/raydium-accounts.ts779Raydium account maps in Anchor camelCasepure
scripts/builder/raydium-instructions.ts354Anchor wrappers for the Raydium instructionspure, plus 2 RPC helpers for ATAs
scripts/builder/raydium-flows.ts236Raydium pool/position load and owner-rebalance adapterRPC
scripts/builder/raydium-intent.ts1105Raydium keeper composers for rebalance, compound, and exitRPC in loaders, pure composers
scripts/builder/meteora.ts679Meteora account decoders, bin-array PDAs, chunk planningpure
scripts/builder/meteora-accounts.ts887Meteora account maps in Anchor camelCasepure
scripts/builder/meteora-instructions.ts367Anchor wrappers for the Meteora instructionspure
scripts/builder/meteora-intent-codec.ts249Byte codec and digest for the DLMM authorizationpure
scripts/builder/meteora-intent.ts692DLMM authorization planner and the Meteora keeper composersRPC in planner, pure composers
scripts/builder/meteora-flow.ts530Owner Meteora steps from an observed position, frozen packet executionpure steps, transport interface
scripts/builder/meteora-driver.ts473Reads one coherent Meteora snapshot and prepares one owner packetRPC

Keeper: scripts/keeper/, scripts/keeper-sim.ts, scripts/canary*.ts

PathLinesPurposePure or I/O
scripts/keeper/decide.ts275Off-chain copy of the 4 keeper checks and the automator authorization rulepure
scripts/keeper/rpc-connection.ts32A Connection with a 10 s deadline and no rate-limit retryRPC factory
scripts/keeper/meteora-planner.ts784Meteora eligibility planner over one snapshotpure
scripts/keeper/meteora-post-confirm.ts406Expected post-transaction state and its checkpure
scripts/keeper/meteora-canary.ts322Canary policy parser and admission rulespure
scripts/keeper/meteora-rpc-collector.ts1312Reads pairs, positions, settings, and authorizations in one slot contextRPC
scripts/keeper/meteora-live-adapter.ts1378Production dependencies: authorization loader, action builder, composer, post-confirm readerRPC, signs with an injected keypair
scripts/keeper/meteora-runtime-adapter.ts471Dry-run, lookup-table, packet-size, and raw-send mechanics for one runtime packetRPC
scripts/keeper/meteora-runtime.ts2832Durable single-replica runtime: SQLite store, file lock, HTTP health, work loopfilesystem, SQLite, HTTP server, injected sends
scripts/keeper/meteora-runtime-entry.ts175Container entry point that reads the environment and starts the runtimeprocess.env
scripts/keeper/meteora-observe-soak.ts314Bounded observe-only soak of the collectorRPC, filesystem
scripts/keeper-sim.ts334Dry-run planner for the Orca keeper actions over every PositionSettings accountRPC, never sends
scripts/canary.ts757Owner lifecycle on mainnet with small fundsRPC, signs with the provider wallet
scripts/canary-intent.ts1494Orca keeper flows on mainnet: authorization, rebalance, exit, replayed nonceRPC, HTTP API, signs with owner, session, keeper
scripts/canary-raydium.ts1632Raydium owner and keeper flows on mainnetRPC, HTTP API, signs with owner, session, keeper
shared/meteora-recovery.ts256Selects the next Meteora exit step from one decoded position. Shared with the UI.pure

Legacy compatibility UI: management-ui/src/

PathLinesPurposePure or I/O
management-ui/src/hooks.server.ts23Redirects owner and keeper pages when a feature flag is offprocess.env
management-ui/src/routes/api/**/+server.ts186920 HTTP endpoints. See the route table below.RPC through $lib/server
management-ui/src/lib/server/solana.ts180The only reader of SOLANA_RPC_URL, PDA helpers, account fetchersRPC
management-ui/src/lib/server/tx.ts461Unsigned legacy and v0 serializers, owner-management instruction buildersRPC for the blockhash
management-ui/src/lib/server/runtime.ts178Feature flags and the per-action transaction checkpure over an environment record
management-ui/src/lib/server/input.ts40Shared public-key, amount, and tick request validationpure
management-ui/src/lib/server/intent.ts830Authorization state read, plan, signature check, transaction A assemblyRPC, HTTP API
management-ui/src/lib/server/orca.ts1473Orca owner flows: fund, deposit, harvest, exit, compound, rebalance, zapRPC, HTTP API
management-ui/src/lib/server/raydium.ts1384Raydium owner flows and the rebalance lookup-table planRPC, HTTP API
management-ui/src/lib/server/admin.ts141Admin instruction builders checked against the live global configRPC
management-ui/src/lib/server/jupiter.ts147Jupiter HTTP client for the UIHTTP API
management-ui/src/lib/server/venue.ts, depth.ts480Venue market data and depth curvesHTTP API, RPC
management-ui/src/lib/server/meteora*.ts (excluding *.test.ts)10732Meteora reads, owner entry, recovery, automation, coordination, keeper composersRPC, HTTP API, in-memory state
management-ui/src/lib/sickle/decode.ts339Borsh decoders for the 4 program account typespure
management-ui/src/lib/sickle/instructions.ts601Instruction discriminators and argument encoderspure
management-ui/src/lib/sickle/orca.ts, orca-tx.ts1159Orca decoders, tick and liquidity math, Orca instruction encoderspure
management-ui/src/lib/sickle/raydium.ts, raydium-tx.ts977Raydium decoders, tick math, Raydium instruction encoderspure
management-ui/src/lib/sickle/intent.ts, intent-tx.ts1100Second copy of the authorization codec, PDAs, decoders, and transaction encoderspure
management-ui/src/lib/sickle/intent-timing.ts3Re-exports the shared builder/UI intent timing policypure
management-ui/src/lib/sickle/jupiter.ts351Second copy of the swap planner and route conversionpure
management-ui/src/lib/sickle/fees.ts, transfer-fees.ts164Second copy of fee math and Token-2022 fee mathpure
management-ui/src/lib/sickle/meteora-*.ts, settings-tx.ts (excluding *.test.ts)2626Meteora codec and transaction encoders, settings encoder, readinesspure
management-ui/src/lib/dlmm/*.ts (excluding *.test.ts)3150Meteora lb_clmm decoders, support policy, range planner, chart datapure
management-ui/src/lib/wallet/wallet.svelte.ts233Wallet Standard connector. The only place a transaction is signed.browser wallet, /api/rpc
management-ui/src/lib/idl/sickle.json9037The checked-in IDL snapshotdata

Tests and fixtures

PathLinesPurpose
tests/*.ts4814163 top-level files: 56 spec files, 6 helper modules, 1 registration module
tests/sickle/*.ts103208 legacy-validator modules registered by tests/sickle.ts
tests/support/sickle-context.ts171Provider, program, PDAs, and event decoder for the legacy-validator suite
tests/fixtures/intent-vectors.json131Authorization byte vectors shared with Rust
tests/fixtures/meteora-intent-vectors.json62DLMM authorization byte vectors shared with Rust
tests/fixtures/meteora-dlmm-layout.json559Meteora account offsets shared with Rust
tests/fixtures/meteora-builder-packets.json71Meteora packet fixture for tests/builder-meteora-packets.ts
tests/fixtures/meteora-cu-probe.json445Raw compute samples for the docs
tests/fixtures/meteora-cu-campaign.json7264Cross-pair crossings with per-bin settlement-work counts
tests/fixtures/meteora-cu-work-premium.json2203Paired per-bin settlement premium, same bins
tests/fixtures/meteora-cu-surfpool-worst-work.json344CI complete-transaction figures in the worst settlement state

Scripts and configuration

PathLinesPurpose
/package.json45test, test:ts, test:surfpool, test:keeper-runtime, keeper:sim, keeper:meteora
Anchor.toml77[scripts] test entry points, [test.validator] clone list, [surfpool] fork settings
.mocharc.json5ts-node/register, timeout 1,000,000 ms
scripts/dev/gen-idl.mjs242Writes the IDL snapshot, target/idl/sickle.json, and target/types/sickle.ts

Responsibilities

  • Derive every PDA and ATA that the program re-derives on chain.
  • Produce the exact camelCase account map that accountsStrict requires for each instruction.
  • Decode the foreign venue accounts that the IDL does not describe.
  • Size liquidity, slippage floors, fees, and Token-2022 transfer fees.
  • Plan a keeper authorization in canonical form, compute its digest, and sign it.
  • Compose the atomic transaction B for each keeper action.
  • Freeze transaction A, transaction B, and a cancellation before A is sent.
  • Check the packet size against the wire limit before a send.
  • Send with a blockhash refresh and refuse to retry a program error.
  • Predict off chain whether the program accepts a keeper action.
  • Serve the management UI with unsigned transactions and read models.
  • Proxy JSON-RPC for the browser with a method allowlist.
  • Test the program on a legacy validator, on a mainnet fork, and on mainnet.

Public items

scripts/builder/pdas.ts

ItemKindMeaning
GLOBAL_CONFIG_SEED, SICKLE_SEED, POSITION_SETTINGS_SEED, KEEPER_SEEDconstProgram seeds. pdas.ts:21-27
ORCA_POSITION_SEED, RAYDIUM_POSITION_SEEDconstBoth equal "position". Kept distinct on purpose. pdas.ts:29-36
RAYDIUM_TICK_ARRAY_SEED, RAYDIUM_TICK_ARRAY_BITMAP_SEEDconstRaydium seeds. pdas.ts:38-42
INTENT_*_SEED, DLMM_INTENT_AUTHORIZATION_SEED, DLMM_INTENT_POSITION_SEED, ACTION_INTENT_SEEDconstAuthorization and per-nonce position seeds. pdas.ts:44-58
EVENT_AUTHORITY_SEEDconstAnchor's __event_authority. pdas.ts:64
TOKEN_PROGRAM_ID, TOKEN_2022_PROGRAM_ID, ASSOCIATED_TOKEN_PROGRAM_IDconstToken program IDs. pdas.ts:66-75
associatedTokenAddressfnATA for owner, mint, and token program. pdas.ts:84
globalConfigPda, sicklePda, positionSettingsPda, globalAutomatorPdafnProgram PDAs. pdas.ts:97-130
eventAuthorityPdafnThe event authority PDA. pdas.ts:133
intentDomainPda, intentNoncePda, intentSessionPdafnDurable authorization PDAs. pdas.ts:138-163
nonceLeBytesfn8-byte little-endian nonce seed. pdas.ts:166
intentAuthorizationPda, dlmmIntentAuthorizationPda, dlmmIntentPositionPda, actionIntentPdafnPer-nonce PDAs. pdas.ts:173-221
orcaPositionPda, raydiumPersonalPositionPdafnVenue position PDAs. pdas.ts:228-251

scripts/builder/accounts.ts

ItemKindMeaning
CommonInputinterfaceprogramId, owner, authority, whirlpoolProgram, whirlpool, decoded pool. accounts.ts:66
ModifyLiquidityInput, RebalanceInputtypeCommonInput plus position mint and tick range, or plus old and new mints. accounts.ts:221, accounts.ts:753
SwapFeeActiontype"deposit" or "withdraw". accounts.ts:564
orcaRewardGroupMetas, orcaRewardCollectorMetas, orcaRewardRemainingAccountsfnReward vault, Sickle ATA, mint, and collector ATA metas per initialized slot. accounts.ts:109-145
resolveOpenPositionAccountsfnorca_open_position. accounts.ts:148
resolveIncreaseLiquidityAccountsfnorca_increase_liquidity. Consent account defaults on when keeper or intent is set. accounts.ts:242
resolveDecreaseLiquidityAccountsfnorca_decrease_liquidity. accounts.ts:271
resolveCollectFeesAccounts, resolveCollectRewardsAccountsfnorca_collect_fees, orca_collect_rewards. accounts.ts:276-345
resolveClosePositionAccountsfnorca_close_position. Settings PDA is always present. accounts.ts:354
resolveHarvestForAccounts, resolveCompoundForAccounts, resolveExitForAccountsfnharvest_for, compound_for, exit_for. accounts.ts:389, :476, :491
resolveJupiterSwapAccountsfnjupiter_swap. Fee collector ATA only when a fee action is set. accounts.ts:580
resolveRebalanceAccounts, resolveRebalanceForAccountsfnorca_rebalance_position, rebalance_for. accounts.ts:764-792
resolveInitializeIntentDomainAccounts, resolveSetIntentSessionAccountsfnAdmin migration and session instruction. accounts.ts:795-823
resolvePreauthorizeIntentAccounts, resolvePreauthorizeDlmmIntentAccountsfnTransaction A, both families. accounts.ts:830-883
resolveCancelIntentAccounts, resolveCancelDlmmIntentAccountsfnOwner cancellation. accounts.ts:886-925
resolveExpireIntentAuthorizationAccounts, resolveExpireDlmmIntentAuthorizationAccountsfnPermissionless expiry. accounts.ts:932-967
resolveFinalizeIntentAccounts, resolveFinalizeDlmmIntentAccountsfnFinalizer, both families. accounts.ts:1013-1036

accounts.ts:60-63 re-exports SNAPSHOT_ACCOUNT_CODER_NAMES and eventCpiAccounts, and accounts.ts:459 re-exports IntentRef, so existing Orca-facing imports keep working while the canonical definitions live in the venue-neutral module below.

scripts/builder/common-accounts.ts

ItemKindMeaning
SNAPSHOT_ACCOUNT_CODER_NAMESconstAnchor's runtime names for GlobalConfig and PositionSettings. common-accounts.ts:17-20
decodeSickleSnapshotAccountfnGenerated-IDL typed decoder for coherent snapshots after caller ownership validation. common-accounts.ts:22-36
PoolTokenDescriptor, IntentRefinterfaceOne mint/program pair, and one intent nonce plus optional session signer. common-accounts.ts:38-41, :82-85
resolveSicklePoolAccountsfnSickle, global config, and both program-aware pool-token ATAs. common-accounts.ts:47-67
feeCollectorAccountfnProgram-aware fee-collector ATA. common-accounts.ts:70-76
intentInitAccountsfnThe three nullable transaction-B intent accounts. common-accounts.ts:92-108
eventCpiAccountsfnAnchor event authority plus the Sickle program. common-accounts.ts:115-120

scripts/builder/instructions.ts

ItemKindMeaning
OrcaRewardAtaPreparationInput, TransferHookAccounts, RewardHookAccountstypeReward ATA inputs and transfer-hook account groups. instructions.ts:73, instructions.ts:182-196
buildOrcaRewardAtaPreparation, buildMissingOrcaRewardAtaPreparation, assertOrcaRewardAtasPreparedfnIdempotent reward ATA creates. The last 2 read RPC. instructions.ts:98-164
buildOpenPosition, buildIncreaseLiquidity, buildDecreaseLiquidityfnOrca position instructions. instructions.ts:226-300
buildCollectFees, buildCollectRewards, buildClosePositionfnOrca collect and close. instructions.ts:303-356
buildHarvestFor, buildCompoundFor, buildExitForfnOrca keeper instructions. instructions.ts:359-432
buildJupiterSwapfnOwner swap. Rejects keeper or position inputs. instructions.ts:444
buildIntentJupiterSwapfnKeeper swap with fee_action = null. instructions.ts:502
authorizationToAnchorArg, dlmmAuthorizationToAnchorArgfnCodec payload to Anchor argument shape. instructions.ts:561-628
buildInitializeIntentDomain, buildSetIntentSessionfnDomain migration and session. instructions.ts:631-671
buildPreauthorizeIntentIx, buildPreauthorizeDlmmIntentIxfnThe program instruction of transaction A. instructions.ts:679-728
buildCancelIntent, buildCancelDlmmIntent, buildExpireIntentAuthorization, buildExpireDlmmIntentAuthorizationfnCancellation and expiry. instructions.ts:731-795
buildFinalizeIntent, buildFinalizeDlmmIntentfnFinalizer with vaults, owner ATAs, and mints as remaining accounts. instructions.ts:849-878
buildRebalance, buildRebalanceForfnOrca owner and keeper rebalance. instructions.ts:881-943

scripts/builder/clmm-owner-rebalance.ts

ItemKindMeaning
SwapLegFetchertypeInjected Jupiter quote boundary. clmm-owner-rebalance.ts:41
ClmmOwnerRebalanceCompositioninterfaceShared instruction and lookup-table result. clmm-owner-rebalance.ts:95
composeClmmOwnerRebalancefnFee-aware drain, optional swap, conservative re-add, ordering, and ALT propagation. clmm-owner-rebalance.ts:101

shared/intent-timing.ts

ItemKindMeaning
DEFAULT_VALIDITY_SLOTS, INTENT_QUOTE_MAX_AGE_SLOTS, SEND_MARGIN_SLOTSconstBuilder, server, and browser timing defaults. intent-timing.ts:2-8

scripts/builder/clmm-intent-composer.ts

ItemKindMeaning
SEND_MARGIN_SLOTSconstCompatibility re-export of the shared pre-expiry margin. clmm-intent-composer.ts:23
assertIntentActionAndPosition, assertIntentExpiryMarginfnShared action, venue-position, and expiry guards. clmm-intent-composer.ts:26-58
assertSignedWithdrawalFloorsfnCompares both signed drain floors with the frozen economic plan. clmm-intent-composer.ts:61
composeClmmIntentSingleSwap, composeClmmIntentExitSwapsfnSigned compound/rebalance leg or exit target legs, including quote and vault validation. clmm-intent-composer.ts:110, :236

scripts/builder/flows.ts

ItemKindMeaning
FetchedPoolStateinterfaceDecoded pool plus both transfer-fee schedules. flows.ts:38
getPoolState, getPositionStatefnFetch and decode a pool with its mint owners, or a position. flows.ts:46, flows.ts:124
RebalanceFlowinterfaceInstructions, new mint keypair, lookup tables. flows.ts:133
SwapLegFetchertypeCompatibility re-export of the shared quote boundary. flows.ts:30
INTENT_QUOTE_MAX_AGE_SLOTSconstCompatibility re-export of the shared quote age. flows.ts:149
FrozenIntentSwapLeginterfaceOne frozen route with mints, programs, amounts, and slot window. flows.ts:156
assertFreshIntentQuotefnRejects a zero, stale, or non-exact-floor quote. flows.ts:168
freezeIntentSwapLegfnFetches a quote and stamps its slot window. flows.ts:193
composeRebalancefnOwner Orca rebalance. Rejects a keeper input. flows.ts:247
simulatefnSimulates a legacy or v0 transaction without a send. flows.ts:329

scripts/builder/intent.ts

ItemKindMeaning
DEFAULT_VALIDITY_SLOTS, SEND_MARGIN_SLOTSconstCompatibility re-exports of the shared timing policy. intent.ts:126-129
PlannedIntentAuthorization, PlannedSwapBound, PlanIntentAuthorizationBase, IntentPlanningContextinterfacePlanner inputs and outputs. intent.ts:138-216
plannedSwapBoundFromFrozenQuotefnA signed edge from a frozen quote. intent.ts:164
loadIntentPlanningContextfnDomain value, nonce, and slot in one read. intent.ts:224
planIntentAuthorization, planIntentAuthorizationForPoolfnOrca wrapper and the venue-neutral planner. intent.ts:260, intent.ts:289
buildPreauthorizeIntentfnSigns the digest and returns [ed25519, preauthorize_intent]. intent.ts:400
ConfirmedIntentAuthorization, confirmIntentAuthorizationinterface, fnStored authorization image and its digest check. intent.ts:436-475
IntentActionFlow, IntentExitFlow, IntentCompoundFlow, OrcaIntentCompoundFlowinterfaceComposer outputs. intent.ts:478, intent.ts:684, intent.ts:928-940
OrcaIntentRebalanceSnapshot, OrcaIntentExitSnapshot, OrcaIntentCompoundSnapshotinterface, typeFrozen economic images. intent.ts:485, intent.ts:619, intent.ts:884
loadOrcaIntentRebalanceSnapshot, loadOrcaIntentCompoundSnapshotfnOne-context loaders. intent.ts:510, intent.ts:948
planOrcaExitEconomics, planOrcaRebalanceEconomics, planOrcaCompoundEconomicsfnFloors, usable credit, swap direction. intent.ts:631, intent.ts:826, intent.ts:1048
assessCompoundDustSide, planOrcaCompoundReaddfnDust proof and compound add-liquidity plan. intent.ts:1068, intent.ts:1117
composeIntentExitfn[exit_for, swaps..., finalize_intent]. intent.ts:695
composeIntentCompoundfn[update_fees_and_rewards?, compound_for, swap?, increase?, finalize_intent]. intent.ts:1260
composeIntentRebalancefn[rebalance_for, swap?, increase, finalize_intent]. intent.ts:1434

scripts/builder/intent-codec.ts

ItemKindMeaning
AUTHORIZATION_VERSION, MAX_INTENT_ASSETS, MAX_SWAP_EDGES, INTENT_DIGEST_PREFIX, MAX_DUST_BPS, MAX_COMPOUND_DUST_BPSconstCopies of constants.rs. intent-codec.ts:27-36
IntentAction, IntentSignerKindtypeEnum names mapped to Borsh indexes. intent-codec.ts:39-51
IntentAssetBound, SwapEdge, RebalanceIntentParams, ExitIntentParams, AuthorizationV2interfaceField-for-field copies of intent.rs:108-208. intent-codec.ts:54-106
ZERO_REBALANCE_PARAMS, zeroExitParams, AUTHORIZATION_V2_SIZEconst, fnZero fillers and the fixed size. intent-codec.ts:108-138
serializeAuthorizationV2fnFixed-size Borsh bytes, zero-padded. intent-codec.ts:199
canonicalizeAuthorizationV2, validateCanonicalAuthorizationfnSort, then apply the rules of validate_canonical. intent-codec.ts:257, intent-codec.ts:276
authorizationDigestfnsha256(prefix, version, program, domain PDA, domain value, payload). intent-codec.ts:433
signIntentDigest, verifyIntentDigest, ed25519VerifyInstructionfnRaw ed25519 over the digest and the native verify instruction. intent-codec.ts:460-495
decodeIntentDomain, decodeIntentNonce, decodeIntentSession, decodeIntentAuthorizationfnAccount decoders at fixed offsets. intent-codec.ts:504-655

scripts/builder/intent-packets.ts, scripts/builder/alt.ts, scripts/builder/send.ts

ItemKindMeaning
IntentPacketSpec, FrozenIntentPacket, FrozenIntentPacketSet, IntentPacketValidityinterfacePacket inputs and frozen bytes. intent-packets.ts:28-58
freezeIntentPacketsfnFreezes A, B, and cancellation on one blockhash, then checks the window. intent-packets.ts:116
executeFrozenIntentPacketsfnSends A then B. On failure sends the cancellation and proves removal. intent-packets.ts:223
lookupAddressesForInstructions, missingLookupAddressesfnTable-eligible keys and the missing subset. alt.ts:40, alt.ts:69
newestSlotInSlotHashes, recentSlotsInSlotHashes, unclaimedRecentSlotForLookupTablefnSlotHashes parsing for table creation. alt.ts:111-132
ensureLookupTable, ensurePersistentLookupTable, fetchLookupTablesfnCreate, reuse and extend, fetch. alt.ts:162, alt.ts:258, alt.ts:302
PriorityFeeOptions, RetryOptions, SendResult, SendOptions, TransactionLifetime, SendAndConfirmOptionsinterfaceSend knobs and one-attempt lifetime. send.ts:48-229
priorityFeeInstructions, withPriorityFeesfnHeap frame, CU limit, CU price. send.ts:87, send.ts:123
retryDelayMs, isRetriableErrorfnBackoff and error class by message text. send.ts:135, send.ts:153
signedTransactionBytes, signedV0TransactionBytesfnSigned bytes, legacy or v0. send.ts:237, send.ts:268
PACKET_LIMIT, assertPacketFit, assertV0PacketFitconst, fnWire limit and its check. send.ts:286-337
sendAndConfirmTransactionBytesfnSends signed bytes once and confirms against their original lifetime. send.ts:344
sendWithRetryfnRefreshes the blockhash and re-signs around the single-send helper. send.ts:381

Other builder files

FilePublic items
scripts/builder/orca.tsTICK_ARRAY_SIZE, WP_NFT_UPDATE_AUTH, MEMO_PROGRAM_ID, MIN_TICK_INDEX, MAX_TICK_INDEX, TICK_ARRAY_SEED, REWARD_SLOT_COUNT, 5 discriminators, pool/position and reward/fee state interfaces, decodePool, decodeWhirlpool, decodePosition and 6 reward/fee state decoders, tickArrayStartIndex, tickArrayPda, tickArrayPdaForTick, updateFeesAndRewardsInstruction, TickRounding, alignTick, buildSymmetricRange, FULL_RANGE_ONLY_TICK_SPACING_THRESHOLD, isFullRangeOnly, fullRangeTicks, buildOpenRange, expectedRebalanceRange
scripts/builder/protocol-account.tsInvalidProtocolAccountData
scripts/builder/raydium.tsTick constants, MEMO_PROGRAM_ID, 3 discriminators, POOL_REWARD_SLOT_COUNT, RaydiumPoolState and 10 state interfaces, raydiumSwapSide, decodePool, decodePersonalPosition and 6 state decoders, tick-array and bitmap helpers raydium.ts:618-765, alignTick, expectedRebalanceRange
scripts/builder/raydium-accounts.tsrewardGroupMetas, rewardCollectorMetas, RaydiumCommonInput, RaydiumPositionInput, RaydiumRebalanceInput, 10 resolveRaydium*Accounts functions
scripts/builder/raydium-instructions.tsRaydiumRewardAtaPreparationInput, buildMissingRaydiumRewardAtaPreparation, assertRaydiumRewardAtasPrepared, 10 buildRaydium* wrappers
scripts/builder/raydium-flows.tsFetchedRaydiumPoolState, getRaydiumPoolState, getRaydiumPositionState, RaydiumRebalanceFlow, composeRaydiumRebalance
scripts/builder/raydium-intent.tsplanRaydiumIntentAuthorization, 3 snapshot loaders, 3 economics planners, 1 swap-limit planner, raydiumPoolTokenYieldReceiptsFromPlan, composeIntentRaydiumCompound, composeIntentRaydiumExit, composeIntentRaydiumRebalance, 9 interfaces
scripts/builder/meteora.tsDLMM_PROGRAM_ID, METEORA_DLMM_AUTOMATION_LB_PAIR, METEORA_DLMM_INTENT_MAX_WIDTH, 24 layout constants, DlmmPairState, DlmmPositionState and 6 interfaces, decodeLbPair, decodeLbPairMintKeys, decodePositionV2, assertDlmmPairSupported, assertSicklePosition, bin-array PDA helpers, planMeteoraChunks, planMeteoraPositionAllocation, validateMeteoraLiquidityParameters
scripts/builder/meteora-accounts.tsMeteoraCommonInput, 6 input types, meteoraBinArrayMetas, 4 remaining-account helpers, 12 resolveMeteora*Accounts functions
scripts/builder/meteora-instructions.tsMeteoraAtaPreparationInput, buildMeteoraAtaPreparation, buildMeteoraInitializeBinArray, 14 buildMeteora* wrappers
scripts/builder/meteora-intent-codec.tsDLMM_AUTHORIZATION_VERSION, METEORA_DLMM_PROTOCOL_INDEX, DLMM_INTENT_DIGEST_PREFIX, 3 size constants, DlmmActionParameters, DlmmAuthorizationV1, validateCanonicalDlmmAuthorization, canonicalizeDlmmAuthorizationV1, serializeDlmmAuthorizationV1, decodeDlmmAuthorizationV1, dlmmAuthorizationDigest
scripts/builder/meteora-intent.tsPlannedDlmmIntentAuthorization, PlanMeteoraIntentAuthorizationInput, planMeteoraIntentAuthorization, buildPreauthorizeDlmmIntent, buildCancelPlannedDlmmIntent, buildExpirePlannedDlmmIntent, composeMeteoraIntentCompound, composeMeteoraIntentRebalance, composeMeteoraIntentExit
scripts/builder/meteora-flow.tsStep types, nextMeteoraAllocationStep, buildNextMeteoraAllocationStep, buildMeteoraPreparationStep, buildMeteoraFundingStep, buildMeteoraHarvestStep, nextMeteoraExitStep, buildMeteoraExitStep, freezeMeteoraOwnerPacket, executeFrozenMeteoraOwnerPacket, 2 error classes
scripts/builder/meteora-driver.tsReader and RPC interfaces, loadMeteoraOwnerSnapshot, 5 prepare*Packet functions, executePreparedMeteoraOwnerStep
scripts/builder/compound-credit.ts15 interfaces and types, planOrcaPoolTokenFeeReceipts, planRaydiumPoolTokenFeeReceipts, planOrcaPoolTokenCompoundCredits, planRaydiumPoolTokenCompoundCredits, loadOrcaPoolTokenCompoundCredits, loadRaydiumPoolTokenCompoundCredits
scripts/builder/jupiter.tsJUPITER_CPI_EXCLUDED_DEXES, jupiterCpiQuoteParams, RebalanceSwapPlan, planRebalanceSwap, JupiterApiInstruction, JupiterRouteLimitError, 7 ceiling constants, RAYDIUM_DRAIN_CLOSE_HEAP_FRAME_BYTES, RouteLimits, 3 limit sets, JUPITER_FIXED_ROUTE_ACCOUNTS, SINGLE_LEG_QUOTE_MAX_ACCOUNTS, JupiterSwapLeg, jupiterSwapLegFromApi
scripts/builder/jupiter-api.tsJUPITER_API_BASE_URL, QuotedSwapLeg, fetchJupiterSwapLeg
scripts/builder/liquidity.tsQ64, tickIndexToSqrtPriceX64, liquidityFromTokenA, liquidityFromTokenB, estimateLiquidity, tokenAmountsFromLiquidity, applySlippage
scripts/builder/zap.tsZapInPlan, FixedMaxZapInPlan, planZapIn, planZapInAgainstFixedMaxima
scripts/builder/fees.tsFEE_ACTION_HARVEST 0, _COMPOUND 1, _REBALANCE 2, _EXIT 3, _DEPOSIT 4, feeAmount, afterFee
scripts/builder/transfer-fees.tsActiveTransferFee, MintAccountForTransferFee, transferFeeExcludedAmount, transferFeeIncludedAmount, activeTransferFeesForEpoch, loadActiveTransferFees
scripts/builder/budgets.tsINTENT_COMPOUND_CU, ORCA_HARVEST_CU, INTENT_REBALANCE_CU, INTENT_EXIT_CU, METEORA_KEEPER_SIMULATION_CU_LIMIT
scripts/builder/dry-run.tsLAMPORTS_PER_SIGNATURE, DryRunSealBreach, isDryRunSealBreach, sealConnection, DryRunPrerequisiteMissing, isDryRunPrerequisiteMissing, DryRunOptions, DryRunResult, dryRun, printDryRun, summariseDryRun
scripts/builder/intent-cleanup.tsScannedIntentAuthorization, IntentCleanupResult, cancelScannedIntentAuthorizations, expireScannedIntentAuthorizations
scripts/builder/executor-authorization.tsSickleExecutorAuthorizationRole, optionalGlobalKeeper
scripts/builder/canary-session.tsCanarySessionAuthorization, assertCanarySessionActors, assertCanarySessionKeypair, canarySessionAuthorization

scripts/keeper/decide.ts

ItemKindMeaning
PERMISSION_HARVEST, _COMPOUND, _REBALANCE, _EXITconstBits 0 to 3. decide.ts:18-21
DEFAULT_PUBKEYconstThe all-zeros key as base58. decide.ts:24
RewardBehavior, KeeperAction, NormalizedSettings, DecisiontypeInputs and outputs of the checks. decide.ts:26-64
evaluateHarvest, evaluateCompoundfnCopies of validate_harvest_for and validate_compound_for. decide.ts:70-79
evaluateRebalancefnCopy of validate_rebalance_for: delay, cutoff, debounce, buffer, stop-loss. decide.ts:87
evaluateExitfnCopy of validate_exit_for. decide.ts:126
GlobalAutomatorRecord, SickleAuthority, isAuthorizedAutomatorinterface, fnCopy of is_authorized_automator. decide.ts:146-193
ACTION_PERMISSION, LiveState, ActionPlan, planForPositionconst, fnAll 4 checks for one position. decide.ts:196-272

Meteora keeper runtime

FilePublic items
scripts/keeper/meteora-planner.tsMETEORA_ADX_USDC_LB_PAIR, METEORA_INTENT_MAX_BIN_WIDTH, KEEPER_ACTION_PRIORITY, KEEPER_ACTION_PERMISSION, KEEPER_SKIP_REASON_CODES, blocksMeteoraActionEconomicPlan, splitIntoMeteoraKeeperChunks, compareAddress, resolveMeteoraExecutorAuthorization, assessMeteoraActionSettingsReadiness, planMeteoraKeeperDiscovery
scripts/keeper/meteora-post-confirm.tsMETEORA_POST_CONFIRM_VIOLATIONS, assertMeteoraPostConfirmExpectation, validateMeteoraPostConfirmEvidence, 6 types
scripts/keeper/meteora-canary.ts4 cohort constants, 3 canary caps, METEORA_CANARY_ADMISSION_REASONS, parseMeteoraAdxUsdcCanaryPolicy, parseMeteoraAdxUsdcCanaryRecoveryPolicy
scripts/keeper/meteora-rpc-collector.tsconnectionMeteoraRpcCollectorReader, createMeteoraKeeperRpcCollector, 3 types
scripts/keeper/meteora-live-adapter.tsconnectionMeteoraKeeperLiveReader, createMeteoraAuthorizationLoader, createMeteoraKeeperReviewedActionBuilder, assertMeteoraKeeperActionDraft, createMeteoraKeeperLiveComposer, createMeteoraPostConfirmInspector, createMeteoraKeeperLiveDependencies
scripts/keeper/meteora-runtime-adapter.tssimulateAndFreezeMeteoraRuntimeFlow, packetFromFrozenIntentPacket, frozenPacketSignature, frozenMeteoraPacketTransport
scripts/keeper/meteora-runtime.tsMETEORA_KEEPER_WORK_STATUSES, MeteoraKeeperPermanentPreparationError, isMeteoraKeeperPermanentPreparationError, stableJson, redactSecrets, FilesystemLock, MeteoraKeeperRuntimeStore, MeteoraKeeperRuntime
scripts/keeper/meteora-runtime-entry.tsselectMeteoraKeeperRuntimeDependencies
scripts/keeper/meteora-observe-soak.tsassertLoopbackRpcUrl, runBoundedMeteoraObserveSoak, runMeteoraSurfpoolObserveSoak
scripts/keeper/rpc-connection.tsKEEPER_RPC_TIMEOUT_MS, fetchWithKeeperRpcDeadline, createBoundedKeeperRpcConnection

Management UI routes

Every route is a SvelteKit +server.ts. The server builds unsigned transactions and reads state. The browser signs. The table names the server function each route calls. No route calls scripts/builder/. The UI has its own copy of the encoders under management-ui/src/lib/sickle/.

RouteMethodInputOutputServer function
/api/rpcPOSTJSON-RPC body, 1 to 10 requestsUpstream response, or an errorfetch(rpcUrl()). api/rpc/+server.ts:94
/api/txPOSTaction plus action fields. api/tx/+server.ts:84-142{ transaction, description } or { steps[] }, base64 unsigned56 case branches. api/tx/+server.ts:328-928
/api/intentGET?owner=Domain, nonce, sessions, pending authorizationsfetchIntentState. server/intent.ts:139
/api/intentPOSTowner, protocol, pool, position, action, executor, validitySlots, swaps, sessionCanonical authorization JSON plus digestplanIntent. server/intent.ts:281
/api/sickleGET?owner=PDA, decoded account, lamports, vaultsfetchSickleByOwner. server/solana.ts:94
/api/adminGETnoneGlobal config and global keepersfetchGlobalConfig, listGlobalAutomators. server/solana.ts:87, server/admin.ts:24
/api/poolsGET?venue=orca or ?venue=raydium, plus q, sort, limit{ total, pools }listVenuePools. server/venue.ts:208
/api/pools/depthGET?venue=&address=&span=Liquidity curveliquidityCurve. server/depth.ts:220
/api/orca/positionsGET?owner={ positions }listOrcaPositions. server/orca.ts:357
/api/orca/poolGET?address=Decoded pool plus market datadescribePool, venuePool. server/orca.ts:220, server/venue.ts:219
/api/raydium/positionsGET?owner={ positions }listRaydiumPositions. server/raydium.ts:287
/api/raydium/poolGET?address=Decoded pool plus market datadescribeRaydiumPool, venuePool. server/raydium.ts:179
/api/meteora/poolsGET?q=&sort=&limit={ total, pools }listMeteoraPools. server/meteora.ts:103
/api/meteora/pairGET?address=Pair context, oracle window, fee rates, marketloadPairContext, loadOracleWindow, meteoraPool. server/meteora.ts:169, server/meteora.ts:567, server/meteora.ts:118
/api/meteora/binsGET?address=&span=Bin window around the active binloadPairContext, loadBinWindow. server/meteora.ts:252
/api/meteora/positionsGET?owner=&page=&pageSize=Paged positions with totallistSicklePositions. server/meteora.ts:342
/api/meteora/positionGET?address=&owner=One position resolved bin by bindescribePosition. server/meteora.ts:465
/api/meteora/automationGET?owner=&position=Readiness snapshotloadMeteoraAutomation. server/meteora-automation.ts:382
/api/meteora/recoveryPOSTowner, positionOne unsigned recovery step, or completebuildNextMeteoraRecovery, meteoraRecoveryPacketInstructions. server/meteora-actions.ts:455, server/meteora-actions.ts:89
/api/meteora/enterPOSTaction in prepare-next, allocate-next, fund, add, plus keys and amountsOne unsigned packet, or a lookup-required resultbuildNextMeteoraPreparation, buildNextMeteoraAllocation, buildMeteoraVaultFunding, buildMeteoraAddLiquidity, toMeteoraOwnerPacket. server/meteora-enter.ts:453-636, server/tx.ts:367
/api/meteora/coordinationPOSTStrict owner, position, action, session tuple. server/meteora-coordination-request.tsThe next coordinator stateloadMeteoraCoordination. server/meteora-coordination.ts:932

The /api/tx actions map to these server builders.

Action groupServer builders
initialize, setManager, setAutomator, createAta, sweepinitializeSickleIx, setManagerIx, setCustomAutomatorIx, createSickleAtaIx, sweepTokenIxs. server/tx.ts:86-170
orcaFund, orcaDeposit, orcaHarvest, orcaExit, orcaCompoundbuildOrcaFund, buildOrcaDeposit, buildOrcaHarvest, buildOrcaExit, buildOrcaCompound. server/orca.ts:482-772
orcaRebalance, orcaRebalanceSwap, orcaRebalanceIncreasebuildOrcaRebalanceStart, buildOrcaRebalanceSwap, buildOrcaRebalanceIncrease. server/orca.ts:831-1064
orcaZapInSwap, orcaZapInDeposit, orcaZapOutSwapbuildOrcaZapInSwap, buildOrcaZapInDeposit, buildOrcaZapOutSwap. server/orca.ts:1149-1369
raydium*buildRaydiumFund, buildRaydiumDeposit, buildRaydiumHarvest, buildRaydiumCompound, buildRaydiumExit, buildRaydiumIncrease, buildRaydiumZapInSwap, buildRaydiumZapInDeposit, buildRaydiumZapOutSwap, planRaydiumRebalanceTable, buildRaydiumRebalanceStart, buildRaydiumRebalanceSwap. server/raydium.ts:405-1296
setPositionSettings, unsetPositionSettingsbuildSetPositionSettings, buildUnsetPositionSettings. server/orca.ts:1456-1468
setIntentSession, intentPreauthorize, dlmmIntentPreauthorize, cancelIntent, cancelDlmmIntentbuildSetIntentSession, buildPreauthorizeIntent, buildPreauthorizeDlmmIntent, buildCancelIntent, buildCancelDlmmIntent, planIntentPreauthorizationTable. server/intent.ts:654-816
admin*9 builders. server/admin.ts:51-127
meteoraClose, meteoraSetPositionSettings, meteoraUnsetPositionSettings, meteoraCancelDlmmIntentbuildMeteoraClose, buildMeteoraPositionSettings, buildMeteoraUnsetPositionSettings, buildMeteoraCancelDlmmAuthorization. server/meteora-actions.ts:575, server/meteora-automation.ts:415-513

The IDL contract

ItemWhereMeaning
target/idl/sickle.jsonwritten by anchor build or scripts/dev/gen-idl.mjs. Git ignores target/The live IDL. Six runtime/deploy tools load it: scripts/canary.ts:152, scripts/canary-raydium.ts:198, scripts/canary-intent.ts:175, scripts/keeper-sim.ts:109, scripts/deploy/init-config.ts:53, and scripts/deploy/init-intent-domain.ts:47; no offline spec does
target/types/sickle.tswritten by gen-idl.mjs with convertIdlToCamelCaseThe generated Sickle type used to parameterize Anchor programs and coders. Every builder import is type-only, enforced at tests/offchain-boundaries.ts:254-281
management-ui/src/lib/idl/sickle.jsonchecked inThe snapshot. tests/builder-accounts.ts:13, tests/builder-meteora.ts:4, tests/builder-meteora-flow.ts:6, and tests/builder-meteora-driver.ts:7 load it
anchor.workspace.Sickletests/support/sickle-context.ts:64How the legacy-validator suite gets its Program
camelCase account namescommon-accounts.ts:16-20Anchor renames token_2022_program to token2022Program. Account decoders use globalConfig, not GlobalConfig
eventCpiAccountscommon-accounts.ts:110-120Adds eventAuthority and program to every map for an instruction that emits an event. The test context has its own copy at tests/support/sickle-context.ts:83-89

How a call flows through it

This follows one keeper Orca rebalance as scripts/canary-intent.ts runs it. Transaction A carries the owner's signed limits. Transaction B does the work.

  1. The canary reads pool, position, global config, settings, mint owners, and transfer fees in one slot context. scripts/builder/intent.ts:510-606
  2. It derives the exact new tick range from the live tick and the settings shape. scripts/canary-intent.ts:942-947, scripts/builder/orca.ts:894
  3. It plans the withdrawal floors, the post-fee balances, and the swap direction. scripts/builder/intent.ts:826-881
  4. If a swap is needed it fetches one Jupiter quote and freezes it with a slot window and the exact slippage floor. scripts/builder/flows.ts:193-224, scripts/builder/jupiter-api.ts:61
  5. It builds the authorization: 2 pool vaults as assets, the swap edge, the floors, the window, the nonce. It sorts the assets and edges and checks the canonical rules. scripts/builder/intent.ts:289-392, scripts/builder/intent-codec.ts:257-426
  6. It computes the digest over prefix, version, program, domain PDA, domain value, and payload. scripts/builder/intent-codec.ts:433-452
  7. It composes transaction B from the same snapshot and frozen quote: rebalance_for, the optional keeper swap, orca_increase_liquidity, and finalize_intent. The Orca adapter owns the venue legs and the shared core validates/builds the signed swap. scripts/builder/intent.ts:1434-1603, scripts/builder/clmm-intent-composer.ts:110-209
  8. Each instruction maps its accounts through a resolver and the Anchor client. scripts/builder/accounts.ts:773-792, scripts/builder/instructions.ts:912-943
  9. The owner or session key signs the digest, and transaction A becomes [ed25519 verify, preauthorize_intent]. scripts/builder/intent.ts:400-433, scripts/builder/intent-codec.ts:460-495
  10. A cancellation for the same nonce is built. scripts/builder/instructions.ts:731
  11. All 3 packets are signed on one blockhash, fetched lookup tables are checked, and each packet is measured against the wire limit. Then the window and the quote age are checked one last time. scripts/builder/intent-packets.ts:66-170
  12. A is sent and confirmed, then B. On any failure the cancellation is sent and the authorization PDA must be absent. scripts/builder/intent-packets.ts:223-266

Invariants the layer owns

  1. An owner composer never composes a keeper flow. composeRebalance and composeRaydiumRebalance throw when keeper is set. scripts/builder/flows.ts:263-267, scripts/builder/raydium-flows.ts:171-175.
  2. A standalone swap instruction never carries automator accounts. buildJupiterSwap rejects keeper and position. scripts/builder/instructions.ts:467-473.
  3. An authorization reaches the signer only in canonical form. The codec sorts and then applies every rule of validate_canonical, with a plain Error per rule. scripts/builder/intent-codec.ts:257-426.
  4. Every swap output asset carries a positive floor. The codec rejects a zero minOut on an edge output. scripts/builder/intent-codec.ts:322-329.
  5. A frozen quote is exact. assertFreshIntentQuote requires minAmountOut === applySlippage(quotedOut, bps, "min") and a slot inside the window. scripts/builder/flows.ts:168-190.
  6. A composer refuses a snapshot that disagrees with the signed authorization. Withdrawal floors, edge direction, input cap, output floor, position, and action are compared. Venue adapters check snapshot identity; the shared core checks authorization and swap bounds. scripts/builder/intent.ts:1486-1496, scripts/builder/clmm-intent-composer.ts:26-75, scripts/builder/clmm-intent-composer.ts:110-209.
  7. Nothing is quoted, planned, or fetched after transaction A. The freeze does the last RPC read before A and the executor only sends and confirms. scripts/builder/intent-packets.ts:149-169, scripts/builder/intent-packets.ts:223-266.
  8. A packet never exceeds the wire limit. assertPacketFit throws with the measured size. scripts/builder/send.ts:294-314, scripts/builder/intent-packets.ts:92-98.
  9. A route never exceeds its ceiling. jupiterSwapLegFromApi throws JupiterRouteLimitError on data bytes or account count. scripts/builder/jupiter.ts:372-387.
  10. The Sickle PDA is never marked a signer in a Jupiter route. scripts/builder/jupiter.ts:391-398.
  11. A landed program error is never retried. The single-attempt helper throws on confirmation.value.err, and isRetriableError returns false for custom program error, InstructionError, and simulation failed. scripts/builder/send.ts:153-180, scripts/builder/send.ts:344-369.
  12. A keeper session key is never the executor. The codec rejects sessionSigner === executor. scripts/builder/intent-codec.ts:403-407.
  13. The management server never signs. /api/tx returns serialize({ requireAllSignatures: false }) bytes. The browser adds local position-mint signatures and then the wallet signature. management-ui/src/lib/server/tx.ts:223-233, management-ui/src/lib/wallet/wallet.svelte.ts:143-185.
  14. A digest signature is re-verified on the server before transaction A is assembled. management-ui/src/lib/server/intent.ts:681-684.
  15. A disabled feature returns 403 before the body is parsed further. management-ui/src/routes/api/tx/+server.ts:316-324, management-ui/src/lib/server/runtime.ts:139-163.
  16. The RPC proxy forwards only 4 methods. management-ui/src/routes/api/rpc/+server.ts:9-14.

Limits

LimitValueWhere
Packet size1232 bytesscripts/builder/send.ts:286
Authorization payload663 bytesscripts/builder/intent-codec.ts:123-138
Assets per authorization3scripts/builder/intent-codec.ts:29
Swap edges per authorization2scripts/builder/intent-codec.ts:31
Dust, any action5000 bpsscripts/builder/intent-codec.ts:35
Dust, compound100 bpsscripts/builder/intent-codec.ts:36
Default authorization validity150 slotsshared/intent-timing.ts:2
Send margin before expiry20 slotsshared/intent-timing.ts:8
Quote age20 slotsshared/intent-timing.ts:5
Single-swap route data280 bytesscripts/builder/jupiter.ts:296
Route accounts40scripts/builder/jupiter.ts:297
Orca keeper rebalance route data204 bytesscripts/builder/jupiter.ts:301
Raydium keeper rebalance route data222 bytesscripts/builder/jupiter.ts:302
Multi-swap route data, accounts130 bytes, 24scripts/builder/jupiter.ts:303-304
Quote maxAccounts26scripts/builder/jupiter.ts:352-354
Raydium keeper heap frame256 KiBscripts/builder/jupiter.ts:315
Heap frame range32 to 256 KiBscripts/builder/send.ts:37-39
Compute budget, every CLMM action1,400,000 CUscripts/builder/budgets.ts:20-33
Retry attempts, base delay, cap3, 500 ms, 10,000 msscripts/builder/send.ts:63-68
Keeper RPC deadline10,000 msscripts/keeper/rpc-connection.ts:4
RPC proxy body, response256 KiB, 4 MiBmanagement-ui/src/routes/api/rpc/+server.ts:16-17
RPC proxy batch, concurrency, timeout10, 16, 10,000 msmanagement-ui/src/routes/api/rpc/+server.ts:18-20
RPC proxy rate30 requests per 10,000 msmanagement-ui/src/routes/api/rpc/+server.ts:21-22
Coordination state TTL, entries300,000 ms, 128management-ui/src/lib/server/meteora-coordination-state.ts:64-65

Tests

The routine check is anchor test --validator legacy. It runs tests/**/*.ts minus tests/mainnet-acceptance.ts on a solana-test-validator with 8 cloned mainnet accounts. Anchor.toml:28, Anchor.toml:47-69. The Surfpool scripts run 3 fork processes. Anchor.toml:29-32. CI runs yarn test:keeper-runtime without a validator and the 3 Surfpool scripts after the legacy run. .github/workflows/ci.yml:114, .github/workflows/ci.yml:218-244.

KindFilesCoversNeeds
Pure unit, builderbuilder.ts, builder-accounts.ts, builder-alt.ts, builder-canary-session.ts, builder-clmm-intent-composer.ts, builder-common-accounts.ts, builder-compound-credit.ts, builder-compound-intent.ts, builder-dry-run.ts, builder-executor-authorization.ts, builder-fees.ts, builder-finalize-intent.ts, builder-flows.ts, builder-intent.ts, builder-intent-alt.ts, builder-intent-cleanup.ts, builder-intent-packets.ts, builder-intent-timing.ts, builder-jupiter.ts, builder-raydium.ts, builder-raydium-intent.ts, builder-send.ts, builder-transfer-fees.ts, builder-zap.ts, offchain-boundaries.tsPDAs, decoders, account key sets against the IDL snapshot, math, codec vectors, timing policy, packet budgets, composer arguments with a recording program, stubbed RPCnothing
Pure unit, Meteora builderbuilder-meteora.ts, builder-meteora-flow.ts, builder-meteora-driver.ts, builder-meteora-intent.ts, builder-meteora-packets.tsLayout fixture, chunking, account maps, owner steps, driver snapshot, DLMM codec vectors, 1,400-bin packetnothing
Pure unit, keeperkeeper-sim.ts, meteora-keeper-runtime.ts, meteora-keeper-rpc-collector.ts, meteora-keeper-live-adapter.ts, meteora-keeper-alerts.ts, meteora-keeper-observe-soak.ts, meteora-keeper-canary-adapter.ts, meteora-ui-acceptance-adapter.ts, meteora-pair-admission.tsdecide.ts and decode.ts against state.rs and orca.rs, runtime store and loop with stubbed RPC, collector, adapter, Prometheus rules, admission registrynothing. 2 files read process.env for artifact paths
Pure unit, acceptance toolingacceptance-artifact-unit.ts, acceptance-closeout-unit.ts, acceptance-coverage-unit.ts, acceptance-guards-unit.ts, acceptance-matrix-unit.ts, mainnet-meteora-acceptance-unit.ts, mainnet-meteora-closeout-unit.ts, deploy-provenance-unit.ts, orca-pool-fixture-unit.ts, rpc-relay-hardening-unit.tsSpend guard, coverage ledger, artifact hash, matrix document, pool fixture bytesnothing
Helper modules, no itacceptance-artifact.ts, acceptance-coverage.ts, acceptance-guards.ts, orca-pool-fixture.ts, surfpool-helpers.ts, mainnet-meteora-acceptance.ts, support/sickle-context.tsShared code the specs importloaded by the glob, run nothing
Legacy validatorsickle.ts registers sickle/core.ts, sickle/orca.ts, sickle/jupiter.ts, sickle/intents.ts, sickle/raydium.ts, sickle/raydium-fork.ts, sickle/orca-fork.ts, sickle/orca-lifecycle.tsEvery instruction against the built program, authorization flow, events, a local Orca poolanchor test --validator legacy
Surfpool mainnet forksurfpool-lifecycle.ts, surfpool-t22-lifecycle.ts, surfpool-jupiter.ts, surfpool-raydium-lifecycle.ts, surfpool-t22-raydium-lifecycle.ts, surfpool-meteora-lifecycle.tsFunded lifecycles on live pools with cheatcodes, keeper flows, Token-2022 pools, Meteora compute limitsSurfpool. Each self-skips on a legacy validator through isSurfnet. tests/surfpool-helpers.ts:50
Mainnet, real fundsmainnet-acceptance.ts with mainnet-meteora-acceptance.ts as phase 15The deployed artifact, config, allowlist, and every instruction, or an explicit skip with a reasonscripts/deploy/acceptance.sh, excluded from the glob. Anchor.toml:28

Fixtures shared with Rust.

FixtureRust readerTypeScript readers
tests/fixtures/intent-vectors.jsonprograms/sickle/src/intent.rs:3380tests/builder-intent.ts, management-ui/src/lib/sickle/intent.test.ts:35, scripts/dev/gen-intent-vectors.ts
tests/fixtures/meteora-intent-vectors.jsonprograms/sickle/src/intent.rs:3425tests/builder-meteora-intent.ts, management-ui/src/lib/sickle/meteora-intent.test.ts, scripts/dev/gen-meteora-intent-vectors.ts
tests/fixtures/meteora-dlmm-layout.jsonprograms/sickle/src/meteora.rs:2123tests/builder-meteora.ts, management-ui/src/lib/dlmm/meteora.ts, management-ui/src/lib/dlmm/pdas.ts

The management UI has 62 vitest files under management-ui/src/ (61 before this change; src/lib/server/input.test.ts is new). One of them, management-ui/src/lib/sickle/builder-parity.test.ts, compares the UI encoders with scripts/builder/pdas.ts, jupiter.ts, and transfer-fees.ts byte for byte.

Gaps.

  • composeRaydiumRebalance runs only in tests/builder-transfer-fees.ts:838 with a recording program. No validator or fork test sends its output.
  • decide.ts does not model validate_rebalance_progress programs/sickle/src/state.rs:723 or the placement check. tests/keeper-sim.ts has no case for RebalanceNoOp or InvalidRangePlacement.
  • The shared send transport is unit-tested with a stubbed Connection, but no validator or fork test sends through it. Only mainnet acceptance and the canaries use that path live.
  • ensureLookupTable and ensurePersistentLookupTable run only in the validator and fork suites.
  • surfpool-jupiter.ts self-skips when the Jupiter API is unreachable. tests/surfpool-jupiter.ts:271-279. A network fault reads as a pass.

Simplification and audit notes

  1. L10-N007 — Retirement boundary and duplication across repositories. The legacy management UI does not import scripts/builder/. It carries a second implementation of 7 modules. The PDAs are at management-ui/src/lib/sickle/orca-tx.ts:36-104. The tick and liquidity math is at management-ui/src/lib/sickle/orca.ts:329-503. The Raydium tick math is at management-ui/src/lib/sickle/raydium.ts:299-355. The fee math is at management-ui/src/lib/sickle/fees.ts:11-19. The transfer-fee math is at management-ui/src/lib/sickle/transfer-fees.ts:97-113. The swap planner is at management-ui/src/lib/sickle/jupiter.ts:83-282. The authorization codec is at management-ui/src/lib/sickle/intent.ts:175-425. The UI comments say so at orca.ts:2-3, raydium.ts:2, jupiter.ts:1, fees.ts:2. builder-parity.test.ts:1-25 states that nothing else checks the claim. That test covers PDAs, admin encoding, discriminators, transfer fees, and Jupiter. It does not cover the tick or liquidity math, the account maps of the Orca and Raydium position instructions, or the codec. The codec rests on the shared vectors alone. The HTTP app is not served: deploy-restricted.sh:59-80 recognizes the authoritative sickle-sol-ui marker and exits without rebuilding or repointing traffic. Two selected server modules remain production inputs through the canary adapter imports cited at the start of this page, so deleting the whole tree is not yet safe. A shared live off-chain core would have to include the sibling repository; extracting only against this legacy copy would solve the wrong boundary.

  2. L10-N008 — Duplication inside the legacy UI. PDA derivation appears in management-ui/src/lib/server/solana.ts:62-80, management-ui/src/lib/server/tx.ts:44-48, management-ui/src/lib/sickle/orca-tx.ts:36-104, management-ui/src/lib/sickle/intent.ts:458-507, and management-ui/src/lib/dlmm/pdas.ts:31-40.

  3. L10-N009 — Very long functions. MeteoraKeeperRuntime scripts/keeper/meteora-runtime.ts:1837-2824 is 988 lines. MeteoraKeeperRuntimeStore meteora-runtime.ts:669-1800 is 1132 lines. createMeteoraKeeperRpcCollector scripts/keeper/meteora-rpc-collector.ts:667-1312 is 646 lines. The /api/tx POST handler management-ui/src/routes/api/tx/+server.ts:314-935 is 622 lines with 2 switch statements over the same body.action. planIntent management-ui/src/lib/server/intent.ts:281-645 is 365 lines. planRebalanceSwap scripts/builder/jupiter.ts:139-258 is 120 lines.

  4. L10-N010 — Error handling is inconsistent. The builder throws Error in most places, RangeError in send.ts:71-79 and intent.ts:1074-1089, and 4 custom classes: JupiterRouteLimitError jupiter.ts:268, InvalidProtocolAccountData scripts/builder/protocol-account.ts:2, DryRunSealBreach dry-run.ts:64, MeteoraOwnerPacketRejected meteora-flow.ts:466. buildJupiterSwap returns Promise.reject instructions.ts:467-473 while buildFinalizeIntent throws synchronously instructions.ts:821-823. isRetriableError classifies by substring match on the message text send.ts:153-180. /api/tx maps every thrown Error to HTTP 422, including a programming error api/tx/+server.ts:931-934.

  5. L10-N011 — Comment does not match code. management-ui/README.md:68 says the RPC proxy passes sendTransaction and simulateTransaction. The allowlist at management-ui/src/routes/api/rpc/+server.ts:9-14 has getAccountInfo, getSignatureStatuses, getTransaction, and sendTransaction only.

  6. L10-N012 — Comment does not match code. scripts/builder/zap.ts:5-10 says the program requires the add-liquidity instruction through the Instructions sysvar with MissingZapInLeg. programs/sickle/src/errors.rs:96 still declares the variant, and no handler raises it. tests/sickle/orca.ts:2338-2341 records that the authorization ledger replaced it.

  7. L10-N013 — Comment does not match code. scripts/builder/instructions.ts:166 is a one-line doc comment for orca_open_position followed by the TransferHookAccounts doc block. buildOpenPosition at instructions.ts:226 has no doc comment.

  8. L10-N014 — Off-chain copy is incomplete. evaluateRebalance scripts/keeper/decide.ts:87-123 mirrors validate_rebalance_for programs/sickle/src/state.rs:586-687 but not validate_rebalance_progress state.rs:723 or the placement check. The header at decide.ts:5-10 says it predicts the exact on-chain error.

  9. L10-N015 — Anchor null for an optional account. resolveIncreaseLiquidityAccounts returns null for globalAutomator, positionSettings, and actionIntent scripts/builder/accounts.ts:258-266. The comment in scripts/builder/executor-authorization.ts:8-11 explains that Anchor then emits the program ID as a sentinel. A reader of accounts.ts alone does not see that.

  10. L10-N016 — Test self-skips. The 6 Surfpool files return early on a legacy validator tests/surfpool-lifecycle.ts:747-753, tests/surfpool-meteora-lifecycle.ts:872-875. tests/surfpool-jupiter.ts:271-279 also skips on any Jupiter transport failure. tests/mainnet-acceptance.ts records 47 ledger.skip calls with reasons in its ledger. A green legacy run proves nothing about those files.

  11. L10-N017 — Missing execution tests. See the remaining gaps under Tests: composeRaydiumRebalance, the shared send transport, and the lookup-table creation path.

  12. L10-N019 — A registry that looks like a gate gates nothing. The Meteora pair admission registry evaluates pairs as executable or not scripts/meteora-pair-admission.ts:1-24. No keeper, runtime, or UI code reads it. Only its report script and its test read it. The keeper and the UI act on pairs through their own hard-coded constants instead. Its v1 record docs/release-evidence/meteora-pair-admission-v1.json bounds ADX-USDC at 56 bins. The program now allows at most 55 on that pair, so the record evaluates as not executable. No path acts on that result.

  13. L10-N020 — Some UI checks compare a width with the wrong limit. The program limits a keeper action to f of the pair's initialized reward slots: 55, 55, or 48 bins. Three management UI surfaces compare with the structural 55 instead. The settings encoder does it at management-ui/src/lib/sickle/settings-tx.ts:275, :358, and :430. The economics snapshot does it at management-ui/src/lib/sickle/meteora-economics.ts:215 and management-ui/src/lib/server/meteora-economics.ts:262. The action preparation does it at management-ui/src/lib/server/meteora-action-preparation.ts:330. On the one admitted pair, ADX-USDC, 55 is also f(1), so today the result is correct. If that pair initializes a second reward slot, f drops to 48. These surfaces then accept settings of 49 to 55 bins that the program rejects in transaction B. The user sees valid settings, and the keeper holds the rows. The fix is to compare with meteoraDlmmIntentMaxWidth(pair), as the readiness check and the intent composers already do. The review of pull request 297 found this.

Resolved

  1. L10-R001 — The six Orca and Raydium keeper composers repeated authorization action, venue-position, expiry-margin, withdrawal-floor, and signed-edge guards. Four repeated the same optional single-swap validation/build block, and the two exit composers repeated the same zero-to-two target-swap pipeline. Those shared rules now live in clmm-intent-composer.ts; the venue adapters retain their distinct snapshot predicates, economic planners, account maps, drain/re-add instructions, output names, and Raydium heap requirement. The old SEND_MARGIN_SLOTS import remains available through intent.ts. The focused composer and transfer-fee suites pin instruction order, mixed token programs, fee math, post-swap arithmetic, and both swap directions; the source-level boundary test also requires all six wrappers to call the shared guards and appropriate swap composer. A direct shared-composer suite now pins every migrated guard, current-slot quote freshness, the optional no-swap path, zero-leg rejection, strict signed limits, cumulative exit floors, and lookup-table propagation. Focused Orca and Raydium compound, rebalance (with and without a swap), and exit cases pin the returned venue/swap/re-add/finalize order. The Orca exit cases also run both in-kind and target-swap composeIntentExit paths offline with mixed token programs. The zero-amount frozen-leg branch was removed as unreachable because the now directly tested quote validation rejects a zero-sized leg.

  2. L10-R002 — The Orca and Raydium owner-rebalance composers independently estimated the drain, loaded the protocol fee, applied transfer fees, planned and built an optional Jupiter swap, derived conservative post-swap balances, sized the re-add, ordered the three legs, and propagated route lookup tables. Those decisions now live once in clmm-owner-rebalance.ts. Each venue wrapper loads its own accounts, maps A/B or 0/1 into the shared pair, and supplies only its drain and increase builders. SwapLegFetcher moved with the shared policy and remains re-exported from flows.ts for compatibility. The existing 12 owner fee/swap cases pin both adapters; a source-level test also requires each wrapper to call the shared composer exactly once and forbids it from re-importing the extracted policy helpers.

  3. L10-R003 — Six TypeScript exports had no importer in scripts/, tests/, shared/, or management-ui/src/, and this private package exposes no package entrypoint. The declarations and their orphaned imports are removed. The three composer connection parameters retain their call positions as _connection, following the existing exit-composer convention; unused drain-credit destructures, Sickle aliases, and the flows.ts value alias are removed. TypeScript compilation and the existing builder and keeper suites preserve the reachable account, instruction, and packet behavior.

  4. L10-R004 — Orca, Raydium, and Meteora separately derived the same Sickle, global config, pool-token, and fee-collector accounts, while the two CLMM resolvers separately built the same three optional intent slots. Resolved by moving those derivations, the event-CPI pair, and shared account-coder names into scripts/builder/common-accounts.ts. Venue adapters retain only their intentional A/B, 0/1, and X/Y output names, and accounts.ts re-exports its old public names for compatibility. tests/builder-common-accounts.ts directly pins the shared contract; the existing Orca, Raydium, and Meteora suites still pin every public resolver map. Their mutation check rejected a side-1 ATA derived with side 0's token program in four independent tests.

  5. L10-R005 — The keeper's narrow Orca decoder and the builder's full decoder both read the Whirlpool tick spacing and live tick, while the builder imported the position decoder and shared error upward from scripts/keeper/. Resolved by making scripts/builder/orca.ts the one owner of Orca account layouts: the narrow and full pool decoders share one field reader, every position decoder shares one core reader, and the keeper now imports those builder decoders. The venue-neutral error lives in protocol-account.ts, used by both Orca and Raydium. tests/offchain-boundaries.ts walks every builder TypeScript import and fails if the reverse dependency returns; its mutation check caught protocol-account.ts -> ../keeper/decide before this text was written.

  6. L10-R006 — The UI coordinator generated and cached a replacement-position keypair it never used to sign, while the keeper independently generated a second keypair for the same logical role. Resolved by eliminating both secrets. The destination is now the PDA [b"dlmm_intent_position", sickle, nonce_le]; meteora_rebalance_for and meteora_intent_open_position independently require it, and the open handler supplies its signer privilege only through invoke_signed. The keeper packet is signed only by its ordinary service identity. The UI's bounded state retains the unsigned authorization draft, but no private key, and a stored authorization remains reconstructible after a server restart.

  7. L10-R007 — buildFinalizeIntent and buildFinalizeDlmmIntent duplicated the same non-exit and exit remaining-account grammar, while their account resolvers duplicated every fixed key except the authorization PDA name. The two public builders are now thin wrappers over finalizeIntentRemainingAccounts that keep the family-specific discriminators and mismatch errors. The two public resolvers now share resolveFinalizeCommonAccounts, with a callback that inserts the typed authorization key at its original position. A focused offline suite pins every fixed key to its absolute expected address, both remaining-account forms, and both errors, while the source-level boundary test requires both public families to keep calling the shared cores.

  8. L10-R008 — sendFrozenPacket and sendWithRetry duplicated raw submission, blockhash-lifetime confirmation, and landed-error handling even though their retry policies intentionally differ. That one-attempt boundary now lives in sendAndConfirmTransactionBytes. Frozen A, B, and cancellation packets each call it once without refreshing their reviewed bytes; sendWithRetry keeps the blockhash refresh, re-sign, backoff, and transient-error classification around it. Stubbed-RPC tests pin the exact bytes and lifetime, default and overridden transport options, landed failure, fresh signature on retry, and terminal no-retry path. The packet-orchestration suite continues to prove an uncertain A failure goes straight to the pre-frozen cancellation, while the source-level boundary test requires both callers to use the shared helper.

  9. L10-R009 — Intent authorization timing was independently copied between the root builder, packet executor, management server, and browser form. The three defaults now live in dependency-free shared/intent-timing.ts; thin builder and UI modules preserve the old public import paths. The packet freeze uses the shared send margin instead of a literal, Meteora coordination imports validity directly instead of through the server intent module, and the form derives its string default from the shared bigint. Root and UI unit tests pin the three values and compatibility exports, while the source-level boundary test requires every consumer to import the shared policy. The send tests now also pin both callers' exact blockhash lifetime, commitment, and preflight options. Live transport remains an explicit acceptance/canary coverage gap.

  10. L10-R010 — Four API routes carried local public-key parsers, and the transaction and intent routes separately parsed non-negative amounts. Those request primitives now live in management-ui/src/lib/server/input.ts:4-40. Public keys and amounts intentionally require JSON strings. The explicit key type guard is defense in depth relative to the shared parser introduced by the extraction, which already stringified and rejected non-string JSON keys. The extraction itself tightened the older transaction-route parser, which passed non-string values directly to PublicKey and accepted some of them. The amount rule intentionally tightens the old contract: it prevents already-rounded JSON numbers above JavaScript's safe-integer range from silently changing instruction data, accepts only canonical unsigned decimal strings, and rejects values above u64::MAX. Empty, padded, whitespace, signed, fractional, and radix-prefixed forms all fail with HTTP 400. All in-repo callers already send canonical decimal strings; valid request behavior is unchanged. parseRequiredKey preserves the Meteora owner-step routes' distinct missing-value error before delegating to the same key parser. The shared tick parser also replaces the Orca and Raydium deposit paths' ?? NaN bypasses at management-ui/src/routes/api/tx/+server.ts:701-771, so every CLMM tick request fails with the same HTTP 400 contract. The focused suite pins string-only values and both error shapes, requires all four routes to import the shared module, checks every Meteora owner-step key, and checks each deposit case independently management-ui/src/lib/server/input.test.ts:30-123. The transaction-route header now describes its admin, intent, and protocol-management scope.

  11. L10-R011 — Two offline Meteora suites loaded the ignored build IDL while the other builder specs used the checked-in snapshot. builder-meteora-flow.ts and builder-meteora-driver.ts now use the snapshot too, so their runtime no longer depends on anchor build having populated target/idl. The source-level boundary suite walks every TypeScript spec's direct imports and rejects any dependency on the ignored IDL tests/offchain-boundaries.ts:373-396; reverting either import makes that guard fail. Generated target/types remain a typecheck input, not a runtime IDL source.

  12. L10-R012 — The Orca and Raydium coherent intent snapshot loaders decoded GlobalConfig and PositionSettings through raw account coders and erased the generated account types with as any, including the earlier settings fetches. decodeSickleSnapshotAccount now maps the two runtime coder names to anchor.IdlAccounts<Sickle> once in common-accounts.ts. Both venue loaders keep the same raw buffers from their single-context account reads but use the typed helper for all four frozen decodes and typed Anchor fetch results. A source-level test pins both account mappings, four helper calls per venue, and rejects raw coder calls or as any in either loader tests/offchain-boundaries.ts:181-209. The helper documents the caller's owner check, the generated exit-token keys now flow without redundant PublicKey casts, and all builder references to the generated Sickle type are explicit type-only imports; a second boundary case enforces that import contract tests/offchain-boundaries.ts:254-281. Typecheck and the existing compound and rebalance suites preserve behavior.

  13. L10-R013 — The Orca keeper rebalance wrapper forced withSettings: true, then re-derived and overwrote the same old/new settings PDAs already returned by resolveRebalanceCommon; the Raydium wrapper carried the identical dead override. Both wrappers now re-export the common resolver's values with non-null assertions solely to preserve the account type required by accountsStrict scripts/builder/accounts.ts:743-762, scripts/builder/raydium-accounts.ts:706-728. The source boundary requires each wrapper to force settings, forbids a second positionSettingsPda call, and pins both re-exported values tests/offchain-boundaries.ts:211-252. The Orca and Raydium unit suites independently pin both returned settings addresses tests/builder-accounts.ts:523-537, tests/builder-raydium.ts:921-926. The program must still validate the required keeper settings because transactions are untrusted; that on-chain boundary is not removable duplication.

  14. L10-N018 — A compute check depended on live mainnet state. The Meteora Surfpool test compared three measured compute figures with caps 1,400 CU above each measurement. The fork read the ADX-USDC pair and its bin arrays from mainnet, and one code path measured 3,866 CU and 5,056 CU apart on two days. Resolved by pinning that state, not by widening the allowance. The test writes the accounts in tests/fixtures/meteora-acceptance-state.json, captured at one mainnet slot, before it measures tests/surfpool-helpers.ts:237-273. It also refuses to measure a transaction that names a Meteora account outside the pinned set or the accounts that the test creates tests/surfpool-meteora-lifecycle.ts:1442-1484. That refusal stops a later flow from reading live state again without notice.

    Throwaway pull requests 300 to 303 show both properties. Each branch changed the test or the program on top of the fix, ran CI, and was closed without a merge. The figures are compound / rebalance / exit in CU. The pinned figures are 850,547 / 1,141,737 / 593,730.

    RunFiguresResult
    300: one more address derivation850,547 / 1,143,266 / 593,713Fails: 129 over the cap
    302: light changed state, no pin850,724 / 1,141,807 / 593,730+177 / +70 / 0
    301: light changed state, then the pin850,547 / 1,141,737 / 593,730Equal to the pin
    302: strong changed state, no pin850,621 / 1,120,640 / 593,713+74 / −21,097 / −17
    301: strong changed state, then pin850,547 / 1,141,737 / 593,713Pin, exit −17
    303: strong, no pin, two-sided check850,621 / 1,120,640 / 593,713Fails: below the lower end
    299 at 6443f51, after an outage850,547 / 1,141,737 / 593,730Equal to the pin
    299 at 57e07b9, the next day850,547 / 1,141,768 / 593,713+0 / +31 / −17

    The light change multiplies bin amounts and liquidity by 1.5 and increases the fee accumulators and the volatility. The strong change also empties every other bin and adds 2^120 to each fee accumulator. The strong change without the pin moves rebalance by about 4 times the largest measured daily drift. Pull request 303 ran it twice and measured the same 1,120,640 both times. The two runs of pull request 299 are the first pinned runs apart in time: hours for 6443f51 and about one day for 57e07b9. They are not the week that the note asks for.

    Under the pin the figures agree within tens of CU. They are not always equal. Rebalance moved 31 CU and exit 17 CU with no code change. The likely cause is the number of digits in logged amounts. That is a hypothesis with some support: compound once moved 31 CU the same way, and no movement is a multiple of the 1,500 CU cost of one bump candidate. It is not a proven mechanism.

    The claim does not rest on a sample. The test overwrites each account that it reads, and the refusal enforces that. A later change made the check two-sided. Each figure must now stay within 1,400 CU of its pinned value in both directions tests/surfpool-meteora-lifecycle.ts:194-210. The earlier check allowed any decrease. With the pin, only a code change can move a figure by more than the residue, and a decrease is a change too. The two upper ends are the old caps without change, so the new check only adds a lower end. A later run on another day therefore needs no human check. Normal CI runs this test on each pull request that changes code. If the pin is incomplete, a figure moves and CI fails in either direction. A figure outside the band is a finding to report. After a deliberate optimization, set the figure again from CI in the same change. The residue sets a lower limit on the allowance. Do not make the band as small as about 100 CU, because it would then fail with no code change. Whether a flow fits is a separate check, the worst-work margin in the same test.

Source: docs/dev/layers/10-off-chain.md in vfat-io/sickle-programs, vendored here by its sync workflow. Edit the markdown there; this page is rebuilt from it on deploy.