solana_kit_pyth 0.9.3
solana_kit_pyth: ^0.9.3 copied to clipboard
Pyth Network Hermes client and price account codecs for Solana Kit Dart.
solana_kit_pyth #
Pyth Network client for the Solana Kit Dart SDK.
Covers the pull-model Pyth integration surface:
- Hermes price service client — the official
v2REST API for price feeds and binary price updates - Binary update parsing — accumulator update blobs, Wormhole VAA envelopes, and wire-format price feed messages
- On-chain account decoding — the classic Pyth price account layout and the push oracle
PriceUpdateV2price feed accounts - Update submission — instruction builders for the Pyth Solana Receiver program
Installation #
Installation #
Install the package directly:
dependencies:
"solana_kit_pyth": ^
If your app uses several Solana Kit packages together, you can also depend on the umbrella package instead:
dart pub add solana_kit
Inside this monorepo, Dart workspace resolution uses the local package automatically.
Documentation #
- Package page: https://pub.dev/packages/solana_kit_pyth
- API reference: https://pub.dev/documentation/solana_kit_pyth/latest/
- Workspace docs: https://openbudgetfun.github.io/solana_kit/
- Package catalog entry: https://openbudgetfun.github.io/solana_kit/reference/package-catalog#solana_kit_pyth
- Source code: https://github.com/openbudgetfun/solana_kit/tree/main/packages/solana_kit_pyth
For architecture notes, getting-started guides, and cross-package examples, start with the workspace docs site and then drill down into the package README and API reference.
Usage #
Fetch a price from Hermes #
import 'package:solana_kit_pyth/solana_kit_pyth.dart';
Future<void> main() async {
final hermes = HermesClient(HermesConfig());
// Discover feeds by symbol.
final feeds = await hermes.getPriceFeeds(query: 'bitcoin');
print(feeds.single.id); // hex price feed id
// Latest update, with the parsed price included.
final update = await hermes.getLatestPriceUpdates(
[feeds.single.id],
encoding: HermesEncoding.hex,
parsed: true,
);
final feed = update.parsed!.single;
final price = feed.price;
print('${price.price} ± ${price.conf} * 10^${price.expo}');
}
Decode a binary update and post it on chain
The binary payload of a Hermes update is an accumulator update blob containing one Wormhole VAA plus merkle-committed price messages. Parse it, trim guardian signatures so the update fits in a single transaction, and submit it with the Pyth Solana Receiver's postUpdateAtomic instruction:
import 'package:solana_kit_codecs_strings/solana_kit_codecs_strings.dart';
import 'package:solana_kit_addresses/solana_kit_addresses.dart';
import 'package:solana_kit_pyth/solana_kit_pyth.dart';
Future<void> publish(
HermesPriceUpdate update,
Address payer,
Address priceUpdateAccount,
) async {
// Decode binary.data[0] (hex or base64 per the response encoding).
// In Solana Kit, "encoders" turn encoded strings into raw bytes.
final bytes = switch (update.binaryEncoding) {
HermesEncoding.hex => getBase16Encoder().encode(update.binaryData.single),
HermesEncoding.base64 => getBase64Encoder().encode(update.binaryData.single),
};
final accumulator = parseAccumulatorUpdateData(bytes);
for (final message in accumulator.updates) {
final priceFeed = parsePythPriceFeedMessage(message.message);
print('feed 0x${priceFeed.feedIdHex}: '
'${priceFeed.price} ± ${priceFeed.confidence} * 10^${priceFeed.exponent}');
final instruction = await getPostUpdateAtomicInstruction(
payer: payer,
vaa: trimVaaSignatures(accumulator.vaa), // 5 signatures by default
update: message,
priceUpdateAccount: priceUpdateAccount,
);
// Add the instruction to a transaction message and send it.
print('post $instruction');
}
}
The receiver program also supports post_update, which consumes an encoded-VAA account that was already verified by the Wormhole program. On-chain price accounts decode with decodePythPriceAccount (classic layout) and decodePriceUpdateV2Account (push oracle PriceUpdateV2).
API overview #
| Export | Purpose |
|---|---|
HermesClient / HermesConfig |
Hermes v2 REST client (price_feeds, latest/timestamped updates) |
HermesEncoding, HermesAssetType |
Query enums: hex/base64 payloads, feed asset types |
HermesPriceUpdate, HermesPriceFeed, HermesPriceFeedMetadata |
Typed models for Hermes responses (BigInt price and confidence) |
parseAccumulatorUpdateData |
Split a Hermes binary blob into its VAA and merkle price updates |
parseWormholeVaa, trimVaaSignatures |
Wormhole VAA (v1) envelope parsing and signature trimming |
parsePythWormholeMessage, parsePythPriceFeedMessage |
Pythnet payload and wire-format price feed message parsing |
decodePythPriceAccount |
Classic Pyth on-chain price account decoder |
decodePriceUpdateV2Account |
Push oracle PriceUpdateV2 price feed account decoder |
getPostUpdateAtomicInstruction, getPostUpdateInstruction |
Pyth Solana Receiver instruction builders |
getPythConfigAddress, getPythTreasuryAddress, getGuardianSetAddress |
Receiver and Wormhole PDA helpers |
Scope #
- Hermes v2 REST endpoints only; the SSE streaming endpoint (
/v2/updates/price/stream) is out of scope for v1. - Update submission targets the deployed Pyth Solana Receiver (
post_update_atomic/post_update). The historicalupdate_price_feeds-style receiver interface is not part of the current program and is not implemented. - The classic price account decoder targets layout version 2 (the
@pythnetwork/clientv2 layout). - No cryptographic signature verification happens client-side; guardian signatures are verified by the receiver program on chain.
Upstream reference #
Audited against:
@pythnetwork/hermes-clientv3.1.0 (Hermes v2 REST surface)@pythnetwork/pyth-solana-receiverv0.16.0 (receiver IDL, VAA helpers, PDA seeds)@pythnetwork/clientv2.22.1 (price account layout, magic constant)@pythnetwork/price-service-sdkv1.9.0 (accumulator update parsing, wire message formats)
HermesPrice.asDouble is a lossy floating-point conversion. Extreme exponents overflow to infinity or underflow to zero in bounded time; use the integer price and expo fields when exact decimal arithmetic is required.
On-chain confidence and slot fields are decoded as unsigned BigInt values across the full 64-bit range.