Pyth pro migration: dual-accept mint, Hermes-free SDKs, v2 crank - #1207
Open
bryzettler wants to merge 36 commits into
Open
Pyth pro migration: dual-accept mint, Hermes-free SDKs, v2 crank#1207bryzettler wants to merge 36 commits into
bryzettler wants to merge 36 commits into
Conversation
Receiver and push-oracle IDs now point at the pro deployments (rec2/pyt2), matching upstream's pro-compatible feature. Legacy IDs stay exported as LEGACY_* constants for the transition-window dual-accept checks (ticket 03). Also fixes the crate's unit tests, broken since the Anchor 0.31 bump (discriminator() -> DISCRIMINATOR const).
Receiver, push-oracle, and wormhole program IDs plus optional Hermes API key (Authorization: Bearer) become env config with legacy defaults, so the existing deployment runs unchanged and a pro deployment needs only env. Note: prettier reformatted index.ts on first touch; semantic changes are the env wiring only.
Extract makePythReceiver so both call sites share the program-ID wiring, rename convertedIDL to wormholeIdl, and stop duplicating the legacy default IDs in the README (src/env.ts is the single source).
Repin-only change: the vendored Pyth receiver SDK (issue 01) already flips the DCA owner checks to the pro receiver (rec2). Re-fixture the integration suite to clone the pro-receiver-owned USDC/USD and HNT/USD PriceUpdateV2 accounts so the create->repay round trip runs against pro feeds.
After the Pyth Core upgrade puts Hermes behind paid API keys, third
parties and blockchain-api keep minting DC and reading HNT prices with a
plain package bump and zero Pyth configuration (ADR-0002).
- mintDataCredits builds a single transaction that references the
crank-fed pro HNT feed account as the price oracle; the ephemeral
Hermes price-update posting path is removed. The txs: [{tx, signers}]
return shape is preserved; the priceUpdates return field is removed.
- getOraclePrice reads and parses the pro feed account over its existing
Solana connection (no Hermes), preserving its return shape.
- PYTH_HERMES_URL exports removed from data-credits-sdk and
currency-utils; hermes-client dependency dropped.
- HNT feed-account constant flipped to the pro-receiver-owned account;
the feed-id constant is untouched.
- blockchain-api mint procedure: Squads comment rewritten (minting stays
non-proposable as a product decision, not the stale-by-execution
technical reason, which no longer holds).
Integration test tests/data-credits.ts passes (8 passing, built with
TESTING=true as CI does).
The blockchain-api e2e mint test is upgraded to real on-chain submission
but marked it.skip until ticket 09 deploys the dual-accept data-credits
program to mainnet: surfpool clones the un-upgraded mainnet program,
which rejects the pro-receiver-owned feed with AccountOwnedByWrongProgram.
bryzettler
marked this pull request as ready for review
July 16, 2026 15:19
Member
|
Reminder that this patches the pyth feed/receiver which will need to happen for #1197 as well |
Observed >10s account-read lag on the service RPC defeats any bounded poll: odd ticks read the pre-init Verified status for the full 10s window and memo-bailed, halving the write cadence. The turner simulates against its own RPC, which sees the same-slot init within ~1s — so serve the writes on a status mismatch and let simulation arbitrate. The memo bail remains only for a missing account, which a stale read can't fake once polling covers the same-transaction create.
Each of the 17 e2e matrix jobs ran a full build-anchor. When the anchor build cache was evicted (repo sits at the 10GB Actions cache cap), every job did a cold anchor build that can't finish inside the 20-minute job timeout, so entire runs died as 'cancelled'. The matrix jobs only need target/types to build @helium/idls; build once in a dedicated job with a 60-minute budget and hand the generated types/IDLs to the matrix via an artifact.
madninja
approved these changes
Jul 20, 2026
…hange Build the changed programs' IDLs at the PR base and head with anchor idl build and require an @helium/idls changeset only when the generated IDL actually differs (ignoring metadata.version). Internal logic changes like the SIMD-553 CU optimizations no longer demand a no-op package bump. Verified locally: all four programs this branch touches produce byte-identical IDLs vs develop.
…tion
The websocket path can reject with the raw confirmation result
({ err: { InstructionError } }) rather than the InstructionError
itself, which #1213's fix didn't cover.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Pyth Core upgrade — early migration (cutover 2026-07-31)
Migrates every Helium surface off Hermes ahead of Pyth's July 31 cutover (paid API keys + new router trust model). Mainnet rollout is sequenced separately: a 48h feed-freshness gate on the v2 crank, then Squads-executed program upgrades and AutoTopOff flips; merging this PR only triggers changesets and devnet deploys.
On-chain programs
mint_data_credits_v0accepts anhnt_price_oracleowned by either the legacy receiver (rec5EKMGg6MxZYaMdyBfgwp4d5rB9T1VQH5pJv5LtFJ) or the pro receiver. The check keys on the oracle account's owner program, not a pinned address — this is what keeps the live ephemeral-update path working (see below).has_onepin (6b69a7d,hnt_price_oracleviahas_oneagainst a stored field that is now updatable throughupdate_data_credits_v0(newhntPriceOraclearg + resolver default). This commit must NOT ship in the initialprogram-data-credits-0.2.7deploy — it breaks every ephemeral minter the moment it hits mainnet. The 0.2.7 tag is cut from a release branch at187d7ba(last commit before it); thehas_onecode ships later as 0.2.8 only after ephemeral traffic is confirmed dead.He5mh…and crank URL to thetuktuk-pyth-v2hostname.pyth_solana_receiver_sdk: repinned to pro program IDs; legacy IDs kept asLEGACY_*constants (used by dual-accept).The ephemeral price-update path (why dual-accept is shaped this way)
Live mint traffic today (~5 mints/14h, 800-tx scan of the DataCredits PDA on 2026-07-17) does not read the crank-maintained legacy feed
4Ddm…. Every observed mint posts its own ephemeral Hermes price update in-transaction via the legacy receiverrec5…— the current published-SDK / blockchain-api behavior: fetch a VAA from Hermes, post it to a keypair-addressed ephemeral account, mint against it, close it. Consequences baked into this PR:has_onepin, which is why that deploy is gated on a stricter traffic check: nomint_data_credits_v0with an oracle owned byrec5…at all. That check fails as of 2026-07-17 (all observed mints go throughrec5…); earliest realistic window is mid-August, after prod blockchain-api ships the Hermes-free SDK and stragglers upgrade.updateDataCreditsV0 { hntPriceOracle: He5mh… }must execute back-to-back in the same Squads session — between them, mints are pinned to the stored4Ddm…, stale once the legacy crank is torn down.Services & monitoring
tuktuk-pyth-v2deployment against the pro programs. v2 encoded-VAA PDA namespaced with a"v2"seed to avoid collision with the v1 deployment. Pre-flight hardening from the freshness-gate investigation: stale VAA reads re-poll before memo-bail, wrong-status VAAs defer to turner simulation, and the poll window extends past observed RPC read lag.has_onetrain ships), andsolana_pyth_publish_timefeed freshness. Backing Grafana/Mimir alert rules (crank balance thresholds, feed-stale >600s) land via helium-terraform.Client SDKs (breaking)
@helium/data-credits-sdk/@helium/currency-utils: Hermes dropped entirely.mintDataCreditspasses the crank-fed HNT feed account;getOraclePricereads it on-chain. Breaking:priceUpdatesremoved from the return value,PYTH_HERMES_URLexports deleted;{txs}shape unchanged, zero Pyth configuration needed by consumers.hntPriceOracleto the pro feed so old call sites keep building.create-common-lut.ts/create-tuktuk-dca-lut.tscorrected to the pro feed so a future re-run doesn't bake the dead feed back in. No on-chain LUT work — the live mainnet LUT never contained a Pyth feed,HELIUM_COMMON_LUT/_DEVNETunchanged.Release notes
@helium/spl-utils,@helium/currency-utils,@helium/data-credits-sdk(minor). Merging this PR intodeveloptriggers the Version-Packages PR and devnet program deploys — mainnet program deploys are tag-driven and gated on the 48h freshness gate + Squads session.it.skipped until dual-accept is live on mainnet (surfpool clones the mainnet program); it gets un-skipped as part of the post-flip release train before this merge finalizes.