Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
2ebde4b
Do it
guibescos Feb 26, 2024
c086dcf
Remove some duplicate code
guibescos Feb 26, 2024
d32169f
Cleanup
guibescos Feb 26, 2024
b49e084
Cleanup
guibescos Feb 26, 2024
fb0d06f
Cleanup import
guibescos Feb 26, 2024
d08e92a
Correct description
guibescos Feb 26, 2024
d73e808
Fix path
guibescos Feb 26, 2024
3113026
Cleanup deps
guibescos Feb 26, 2024
4b645cc
Unique
guibescos Feb 26, 2024
191fa01
Works
guibescos Feb 26, 2024
9172fad
Continue
guibescos Feb 26, 2024
063de56
Lint
guibescos Feb 26, 2024
b905266
Lint config
guibescos Feb 26, 2024
81a3307
Fix ci
guibescos Feb 26, 2024
6a2bdbc
Checkpoint
guibescos Feb 20, 2024
dc687d1
Checkpoint
guibescos Feb 20, 2024
0045908
Gitignore
guibescos Feb 20, 2024
d8757d5
Cleanup
guibescos Feb 20, 2024
b854868
Cleanup
guibescos Feb 20, 2024
97f8bd0
Continue building the sdk
guibescos Feb 20, 2024
a5f0cae
build function
guibescos Feb 21, 2024
8328496
Remove files
guibescos Feb 21, 2024
a0f95ea
Remove files
guibescos Feb 21, 2024
131d8ce
Rename
guibescos Feb 21, 2024
f3fc9ef
Refactor : make transaction builder
guibescos Feb 23, 2024
db73a1f
Make commitment
guibescos Feb 23, 2024
520e5fb
Move
guibescos Feb 26, 2024
eedd806
Progress
guibescos Feb 27, 2024
42c7cd0
Checkpoint
guibescos Feb 27, 2024
07756b1
Ephemeral signers 2
guibescos Feb 27, 2024
16c1f86
Checkpoint
guibescos Feb 27, 2024
ef052fa
Checkpoint
guibescos Feb 27, 2024
160c011
Fix bug
guibescos Feb 27, 2024
2f7697c
Cleanup idls
guibescos Feb 28, 2024
89eb8e8
Compute units
guibescos Feb 28, 2024
0e362c5
Make program addresses configurable
guibescos Feb 28, 2024
99b76b6
Handle arrays
guibescos Feb 28, 2024
117a166
Handle arrays
guibescos Feb 28, 2024
2e044b0
Move PythSolanaReceiver
guibescos Feb 28, 2024
66bdbc7
Cleanup constants
guibescos Feb 28, 2024
0068d5f
Contants
guibescos Feb 28, 2024
dcdd39f
Refactor constants
guibescos Feb 28, 2024
9a13bb6
Gitignore refactor
guibescos Feb 28, 2024
3a2562c
package lock
guibescos Feb 28, 2024
6b2d09b
Cleanup idl
guibescos Feb 28, 2024
ecd2c4d
Add useful static
guibescos Feb 28, 2024
4b0094a
Add useful static
guibescos Feb 28, 2024
5926166
Add useful static
guibescos Feb 28, 2024
6290cab
Lint
guibescos Feb 28, 2024
b92e8ce
Add lint config
guibescos Feb 28, 2024
00554e9
Docs
guibescos Feb 29, 2024
a5c0fc4
Comments
guibescos Feb 29, 2024
afcfcf3
Docs
guibescos Feb 29, 2024
0825092
Merged
guibescos Feb 29, 2024
8e7d416
Don't touch this
guibescos Feb 29, 2024
c05b409
Readme
guibescos Feb 29, 2024
2e047f8
Readme
guibescos Feb 29, 2024
40adb68
Cleanup
guibescos Feb 29, 2024
0e68936
Readme
guibescos Feb 29, 2024
7ae5c93
Fix
guibescos Feb 29, 2024
09e4bc3
Merge branch 'main' into solana/js-sdk
guibescos Mar 13, 2024
8bf4dbd
address readme comments
guibescos Mar 13, 2024
64f2daf
from pyth, not pythnet
guibescos Mar 13, 2024
d0b6323
Add a couple more comments
guibescos Mar 13, 2024
3d7abc1
Rename cleanup to close
guibescos Mar 13, 2024
9165bbb
Go go go
guibescos Mar 13, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
161 changes: 161 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions target_chains/solana/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,19 @@

This folder contains:

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

# Overview of the design

Receiving a price update from Pythnet involves two steps:
Posting a Pyth price update involves two steps:

- 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.
- 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.

# Implementation

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

- `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.
- `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.
Expand Down
83 changes: 83 additions & 0 deletions target_chains/solana/sdk/js/pyth_solana_receiver/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# Pyth Solana Receiver JS SDK

This is a Javascript SDK to interact with the Pyth Solana Receiver contract whose code lives [here](/target_chains/solana).

## Pull model

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.

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.
Price update accounts can be closed by whoever wrote them to recover the rent.

## Example use

```ts
import { Connection, PublicKey } from '@solana/web3.js';
import { PriceServiceConnection } from '@pythnetwork/price-service-client';
import { PythSolanaReceiver } from '@pythnetwork/pyth-solana-receiver';
import { MyFirstPythApp, IDL } from './idl/my_first_pyth_app';


const SOL_PRICE_FEED_ID = "0xef0d8b6fda2ceba41da15d4095d1da392a0d2f8ed0c6c7bc0f4cfac8c280b56d"
const ETH_PRICE_FEED_ID = "0xff61491a931112ddf1bd8147cd1b641375f79f5825126d665480874634fd0ace"

const priceServiceConnection = new PriceServiceConnection("https://hermes.pyth.network/", { priceFeedRequestConfig: { binary: true } });
const priceUpdateData = await priceServiceConnection.getLatestVaas([SOL_PRICE_FEED_ID, ETH_PRICE_FEED_ID]); // Fetch off-chain price update data


const myFirstPythApp = new Program<MyFirstPythApp>(IDL as MyFirstPythApp, , PublicKey.unique(), {})
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: [] }] };

const pythSolanaReceiver = new PythSolanaReceiver({ connection, wallet });
const transactions = await pythSolanaReceiver.withPriceUpdate(priceUpdateData, getInstructions, {})
await pythSolanaReceiver.provider.sendAll(transactions);
```

Or, alternatively:

```ts
import { PublicKey } from "@solana/web3.js";
import { PriceServiceConnection } from "@pythnetwork/price-service-client";
import { PythSolanaReceiver } from "@pythnetwork/pyth-solana-receiver";
import { MyFirstPythApp, IDL } from "./idl/my_first_pyth_app";

const SOL_PRICE_FEED_ID =
"0xef0d8b6fda2ceba41da15d4095d1da392a0d2f8ed0c6c7bc0f4cfac8c280b56d";
const ETH_PRICE_FEED_ID =
"0xff61491a931112ddf1bd8147cd1b641375f79f5825126d665480874634fd0ace";

const priceServiceConnection = new PriceServiceConnection(
"https://hermes.pyth.network/",
{ priceFeedRequestConfig: { binary: true } }
);
const priceUpdateData = await priceServiceConnection.getLatestVaas([
SOL_PRICE_FEED_ID,
ETH_PRICE_FEED_ID,
]); // Fetch off-chain price update data

const pythSolanaReceiver = new PythSolanaReceiver({ connection, wallet });
const { postInstructions, closeInstructions, priceFeedIdToPriceUpdateAccount } =
await pythSolanaReceiver.buildPostPriceUpdateInstructions(priceUpdateData); // Get instructions to post the price update data and to close the accounts later

const myFirstPythApp = new Program<MyFirstPythApp>(
IDL as MyFirstPythApp,
PublicKey.unique(),
{}
);
const consumerInstruction: InstructionWithEphemeralSigners = {
instruction: await myFirstPythApp.methods
.consume()
.accounts({
solPriceUpdate: priceFeedIdToPriceUpdateAccount[SOL_PRICE_FEED_ID],
ethPriceUpdate: priceFeedIdToPriceUpdateAccount[ETH_PRICE_FEED_ID],
})
.instruction(),
signers: [],
};

const transactions = pythSolanaReceiver.batchIntoVersionedTransactions(
[...postInstructions, consumerInstruction, ...closeInstructions],
{}
); // Put all the instructions together
await pythSolanaReceiver.provider.sendAll(transactions);
```
Loading