Skip to content

Commit 16cc46e

Browse files
authored
docs: code docs for solana sdk (#1330)
* Do it * Remove some duplicate code * Cleanup * Cleanup * Cleanup import * Correct description * Fix path * Cleanup deps * Unique * Works * Continue * Lint * Lint config * Fix ci * Checkpoint * Checkpoint * Gitignore * Cleanup * Cleanup * Continue building the sdk * build function * Remove files * Remove files * Rename * Refactor : make transaction builder * Make commitment * Move * Progress * Checkpoint * Ephemeral signers 2 * Checkpoint * Checkpoint * Fix bug * Cleanup idls * Compute units * Make program addresses configurable * Handle arrays * Handle arrays * Move PythSolanaReceiver * Cleanup constants * Contants * Refactor constants * Gitignore refactor * package lock * Cleanup idl * Add useful static * Add useful static * Add useful static * Lint * Add lint config * Docs * Comments * Docs * Don't touch this * Readme * Readme * Cleanup * Readme * Fix * address readme comments * from pyth, not pythnet * Add a couple more comments * Rename cleanup to close * Go go go
1 parent 04b66fa commit 16cc46e

File tree

9 files changed

+526
-62
lines changed

9 files changed

+526
-62
lines changed

package-lock.json

Lines changed: 161 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

target_chains/solana/README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,19 @@
22

33
This folder contains:
44

5-
- A Pyth receiver program to receive Pythnet price feeds on Solana in `programs/pyth-solana-receiver`
5+
- A Pyth receiver program to receive Pyth price updates on Solana in `programs/pyth-solana-receiver`
66
- A Cli that acts as a simple client to interact with the Pyth receiver program in `cli/`
77

88
# Overview of the design
99

10-
Receiving a price update from Pythnet involves two steps:
10+
Posting a Pyth price update involves two steps:
1111

1212
- First, verifying the VAA i.e. verifying the Wormhole guardians' signatures on the accumulator root that contains all the price updates for a given Pythnet slot.
1313
- Second, verifying the price update by providing an inclusion proof that proves the price update is part of the accumulator root that was verified in the first step.
1414

1515
# Implementation
1616

17-
This contract offers two ways to post a price update from Pythnet onto Solana:
17+
This contract offers two ways to post a Pyth price update onto Solana:
1818

1919
- `post_update` allows you to do it in 2 transactions and checks all the Wormhole guardian signatures (the quorum is currently 13 signatures). It relies on the Wormhole contract to verify the signatures.
2020
- `post_update_atomic` allows you to do it in 1 transaction but only partially checks the Wormhole guardian signatures (5 signatures seems like the best it can currently do). Therefore it is less secure. It relies on a guardian set account from the Wormhole contract to check the signatures against the guardian keys.
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
# Pyth Solana Receiver JS SDK
2+
3+
This is a Javascript SDK to interact with the Pyth Solana Receiver contract whose code lives [here](/target_chains/solana).
4+
5+
## Pull model
6+
7+
The Pyth Solana Receiver allows users to consume Pyth price updates on a pull basis. This means that the user is responsible for submitting the price data on-chain whenever they want to interact with an app that requires a price update.
8+
9+
Price updates get posted into price update accounts, owned by the Receiver contract. Once an update has been posted to a price update account, it can be used by anyone by simply passing the price update account as one of the accounts in a Solana instruction.
10+
Price update accounts can be closed by whoever wrote them to recover the rent.
11+
12+
## Example use
13+
14+
```ts
15+
import { Connection, PublicKey } from '@solana/web3.js';
16+
import { PriceServiceConnection } from '@pythnetwork/price-service-client';
17+
import { PythSolanaReceiver } from '@pythnetwork/pyth-solana-receiver';
18+
import { MyFirstPythApp, IDL } from './idl/my_first_pyth_app';
19+
20+
21+
const SOL_PRICE_FEED_ID = "0xef0d8b6fda2ceba41da15d4095d1da392a0d2f8ed0c6c7bc0f4cfac8c280b56d"
22+
const ETH_PRICE_FEED_ID = "0xff61491a931112ddf1bd8147cd1b641375f79f5825126d665480874634fd0ace"
23+
24+
const priceServiceConnection = new PriceServiceConnection("https://hermes.pyth.network/", { priceFeedRequestConfig: { binary: true } });
25+
const priceUpdateData = await priceServiceConnection.getLatestVaas([SOL_PRICE_FEED_ID, ETH_PRICE_FEED_ID]); // Fetch off-chain price update data
26+
27+
28+
const myFirstPythApp = new Program<MyFirstPythApp>(IDL as MyFirstPythApp, , PublicKey.unique(), {})
29+
const getInstructions = async (priceFeedIdToPriceUpdateAccount: Record<string, PublicKey>) => { return [{ instruction: await myFirstApp.methods.consume().accounts({ solPriceUpdate: priceFeedIdToPriceUpdateAccount[SOL_PRICE_FEED_ID], ethPriceUpdate: priceFeedIdToPriceUpdateAccount[ETH_PRICE_FEED_ID] }).instruction(), signers: [] }] };
30+
31+
const pythSolanaReceiver = new PythSolanaReceiver({ connection, wallet });
32+
const transactions = await pythSolanaReceiver.withPriceUpdate(priceUpdateData, getInstructions, {})
33+
await pythSolanaReceiver.provider.sendAll(transactions);
34+
```
35+
36+
Or, alternatively:
37+
38+
```ts
39+
import { PublicKey } from "@solana/web3.js";
40+
import { PriceServiceConnection } from "@pythnetwork/price-service-client";
41+
import { PythSolanaReceiver } from "@pythnetwork/pyth-solana-receiver";
42+
import { MyFirstPythApp, IDL } from "./idl/my_first_pyth_app";
43+
44+
const SOL_PRICE_FEED_ID =
45+
"0xef0d8b6fda2ceba41da15d4095d1da392a0d2f8ed0c6c7bc0f4cfac8c280b56d";
46+
const ETH_PRICE_FEED_ID =
47+
"0xff61491a931112ddf1bd8147cd1b641375f79f5825126d665480874634fd0ace";
48+
49+
const priceServiceConnection = new PriceServiceConnection(
50+
"https://hermes.pyth.network/",
51+
{ priceFeedRequestConfig: { binary: true } }
52+
);
53+
const priceUpdateData = await priceServiceConnection.getLatestVaas([
54+
SOL_PRICE_FEED_ID,
55+
ETH_PRICE_FEED_ID,
56+
]); // Fetch off-chain price update data
57+
58+
const pythSolanaReceiver = new PythSolanaReceiver({ connection, wallet });
59+
const { postInstructions, closeInstructions, priceFeedIdToPriceUpdateAccount } =
60+
await pythSolanaReceiver.buildPostPriceUpdateInstructions(priceUpdateData); // Get instructions to post the price update data and to close the accounts later
61+
62+
const myFirstPythApp = new Program<MyFirstPythApp>(
63+
IDL as MyFirstPythApp,
64+
PublicKey.unique(),
65+
{}
66+
);
67+
const consumerInstruction: InstructionWithEphemeralSigners = {
68+
instruction: await myFirstPythApp.methods
69+
.consume()
70+
.accounts({
71+
solPriceUpdate: priceFeedIdToPriceUpdateAccount[SOL_PRICE_FEED_ID],
72+
ethPriceUpdate: priceFeedIdToPriceUpdateAccount[ETH_PRICE_FEED_ID],
73+
})
74+
.instruction(),
75+
signers: [],
76+
};
77+
78+
const transactions = pythSolanaReceiver.batchIntoVersionedTransactions(
79+
[...postInstructions, consumerInstruction, ...closeInstructions],
80+
{}
81+
); // Put all the instructions together
82+
await pythSolanaReceiver.provider.sendAll(transactions);
83+
```

0 commit comments

Comments
 (0)