Skip to content
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
70 commits
Select commit Hold shift + click to select a range
957f735
Add example contract for solana
yhzhang0128 Sep 14, 2022
8aed7a0
Add scripts for invocation in examples/sol-contract
yhzhang0128 Sep 14, 2022
0677a3e
Add readme in examples/sol-contract
yhzhang0128 Sep 14, 2022
1b9a91e
Add overflow checks in examples/sol-contract
yhzhang0128 Sep 14, 2022
685bffd
Cleanup and add comments in examples/sol-contract
yhzhang0128 Sep 14, 2022
b045b70
Remove hard-coded contract hash in examples/sol-contract
yhzhang0128 Sep 14, 2022
7432028
Improve comments wording in examples/sol-contract
yhzhang0128 Sep 14, 2022
d5f6d75
Update readme of examples/sol-contract
yhzhang0128 Sep 14, 2022
eba9da5
Remove some unnecessary dependencies in examples/sol-contract
yhzhang0128 Sep 14, 2022
aac5b9d
Remove the unwrap() in the code of examples/sol-contract
yhzhang0128 Sep 14, 2022
d0b28d9
Fix a grammar error
yhzhang0128 Sep 14, 2022
8ff6ee1
Succeed in adding state.rs and an initialization instruction
yhzhang0128 Oct 3, 2022
004b136
Cleanup
yhzhang0128 Oct 3, 2022
39d8300
Cleanup
yhzhang0128 Oct 3, 2022
32692b8
Cleanup
yhzhang0128 Oct 3, 2022
30ef43f
Add confidence interval
yhzhang0128 Oct 3, 2022
7235d20
Minor
yhzhang0128 Oct 3, 2022
d026e35
Minor
yhzhang0128 Oct 3, 2022
715de4d
Cleanup the contract
yhzhang0128 Oct 3, 2022
017030b
Cleanup the client-side code
yhzhang0128 Oct 3, 2022
9458fc0
Cleanup the contract code
yhzhang0128 Oct 3, 2022
ed7791e
Update readme
yhzhang0128 Oct 3, 2022
59dff00
Minor
yhzhang0128 Oct 3, 2022
829d38b
Minor
yhzhang0128 Oct 3, 2022
6d580bc
Add package-lock.json
yhzhang0128 Oct 4, 2022
eb7462b
Some renaming
yhzhang0128 Oct 4, 2022
9d86e9f
Hardcode loan/collateral quantity in Loan2Value instruction
yhzhang0128 Oct 5, 2022
0bdb6c1
Make loan_qty and collateral_qty parameters of instruction
yhzhang0128 Oct 5, 2022
bca85ae
Minor
yhzhang0128 Oct 5, 2022
6f4a4c0
Update dependency requirements for Solana related dependencies (#75)
dadepo Oct 6, 2022
37604d2
Update the price schema (#76)
ali-behjati Oct 6, 2022
4b7008c
Add example contract for solana
yhzhang0128 Sep 14, 2022
3a03ac3
Add scripts for invocation in examples/sol-contract
yhzhang0128 Sep 14, 2022
33c8afa
Add readme in examples/sol-contract
yhzhang0128 Sep 14, 2022
969b8ff
Add overflow checks in examples/sol-contract
yhzhang0128 Sep 14, 2022
81a4442
Cleanup and add comments in examples/sol-contract
yhzhang0128 Sep 14, 2022
ae47349
Remove hard-coded contract hash in examples/sol-contract
yhzhang0128 Sep 14, 2022
dc4d163
Improve comments wording in examples/sol-contract
yhzhang0128 Sep 14, 2022
908a3bc
Update readme of examples/sol-contract
yhzhang0128 Sep 14, 2022
d2ccf1a
Remove some unnecessary dependencies in examples/sol-contract
yhzhang0128 Sep 14, 2022
b718bb5
Remove the unwrap() in the code of examples/sol-contract
yhzhang0128 Sep 14, 2022
063f20a
Fix a grammar error
yhzhang0128 Sep 14, 2022
a6f9473
Succeed in adding state.rs and an initialization instruction
yhzhang0128 Oct 3, 2022
8f3f76d
Cleanup
yhzhang0128 Oct 3, 2022
e9911f7
Cleanup
yhzhang0128 Oct 3, 2022
0c62d7f
Cleanup
yhzhang0128 Oct 3, 2022
8ceb10d
Add confidence interval
yhzhang0128 Oct 3, 2022
0ffe5d5
Minor
yhzhang0128 Oct 3, 2022
633f266
Minor
yhzhang0128 Oct 3, 2022
a695622
Cleanup the contract
yhzhang0128 Oct 3, 2022
5e6d075
Cleanup the client-side code
yhzhang0128 Oct 3, 2022
5093ca1
Cleanup the contract code
yhzhang0128 Oct 3, 2022
38867b6
Update readme
yhzhang0128 Oct 3, 2022
26ed735
Minor
yhzhang0128 Oct 3, 2022
3406cff
Minor
yhzhang0128 Oct 3, 2022
b185b2c
Add package-lock.json
yhzhang0128 Oct 4, 2022
cb1451b
Some renaming
yhzhang0128 Oct 4, 2022
558dd0c
Hardcode loan/collateral quantity in Loan2Value instruction
yhzhang0128 Oct 5, 2022
e0d03b7
Make loan_qty and collateral_qty parameters of instruction
yhzhang0128 Oct 5, 2022
cb4bbcc
Minor
yhzhang0128 Oct 5, 2022
ebbaa16
Merge branch 'example-rs' of github.com:yhzhang0128/pyth-sdk-rs into …
yhzhang0128 Oct 8, 2022
87fe21f
Change solana version to 1.10.40, same as the Pyth SDK
yhzhang0128 Oct 9, 2022
834aa3d
Only use i64 to calculate the values, before normalizing with exponents
yhzhang0128 Oct 9, 2022
3cc600f
Normalize the values with the exponents
yhzhang0128 Oct 9, 2022
ef46095
Use borsh library for state serialize/deserialize
yhzhang0128 Oct 10, 2022
833a3fc
Resolve a few minor issues, such as renaming, from Ali's comments
yhzhang0128 Oct 10, 2022
9fc162d
Add more check in the Init instruction
yhzhang0128 Oct 10, 2022
6045e74
Fix a bug in client
yhzhang0128 Oct 10, 2022
ba7217a
Update the sol-contract example readme
yhzhang0128 Oct 10, 2022
9195001
Minor in readme
yhzhang0128 Oct 10, 2022
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
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ members = [
"pyth-sdk-solana/test-contract",
"pyth-sdk-cw",
"examples/cw-contract",
"examples/sol-contract"
]
6 changes: 6 additions & 0 deletions examples/sol-contract/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
build/example_sol_contract.so
build/example_sol_contract-keypair.json
scripts/invoke.js
scripts/invoke.js.map
scripts/node_modules/
scripts/package-lock.json
18 changes: 18 additions & 0 deletions examples/sol-contract/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[package]
name = "example-sol-contract"
version = "0.1.0"
authors = ["Pyth Data Foundation"]
edition = "2021"

[lib]
crate-type = ["cdylib", "lib"]

[dependencies]
borsh = "0.9"
pyth-sdk-solana = "0.5.0"
solana-program = "1.8.1, < 1.11"

[dev-dependencies]
solana-sdk = "1.8.1, < 1.11"
solana-client = "1.8.1, < 1.11"
solana-program-test = "1.8.1, < 1.11"
21 changes: 21 additions & 0 deletions examples/sol-contract/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Pyth SDK Example Contract for Solana

This repository contains a simple example demonstrating how to read the Pyth price from the Pyth contract on Solana.

The key functionality of this contract is in the `Loan2Value` function in `src/processor.rs`.
This function compares the value of some loan and some collateral, which is important in many lending protocols.
An example invocation of this contract on the Solana devnet can be found in `scripts/invoke.ts`.

We assume that you have installed `cargo`, `solana`, `solana-keygen`, `npm` and `node`.

## Usage

```shell
> cd examples/sol-contract
# To build the example contract
> scripts/build.sh
# To deploy the example contract
> scripts/deploy.sh
# To invoke the example contract
> scripts/invoke.ts
```
1 change: 1 addition & 0 deletions examples/sol-contract/build/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
This directory holds the output of build-bpf. See scripts/build.sh.
1 change: 1 addition & 0 deletions examples/sol-contract/scripts/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
cargo build-bpf --sbf-out-dir ./build
1 change: 1 addition & 0 deletions examples/sol-contract/scripts/deploy.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
solana program deploy --program-id build/example_sol_contract-keypair.json build/example_sol_contract.so
1 change: 1 addition & 0 deletions examples/sol-contract/scripts/invoke.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
cd scripts; npm install typescript; npm run build; node invoke.js `solana-keygen pubkey ../build/example_sol_contract-keypair.json`
52 changes: 52 additions & 0 deletions examples/sol-contract/scripts/invoke.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
const web3 = require("@solana/web3.js");
const {struct, u8} = require("@solana/buffer-layout");

export const invoke = async (loan: string, collateral: string) => {
/* Airdrop */
console.log("Airdroping...");
let payer = web3.Keypair.generate();
let keypair = web3.Keypair.generate();
let conn = new web3.Connection(web3.clusterApiUrl('devnet'));
let airdropSig = await conn.requestAirdrop(
payer.publicKey,
web3.LAMPORTS_PER_SOL,
);
await conn.confirmTransaction(airdropSig);

/* Specify accounts being touched */
const loanKey = new web3.PublicKey(loan);
const collateralKey = new web3.PublicKey(collateral);
let keys = [{pubkey: loanKey, isSigner: false, isWritable: false},
{pubkey: collateralKey, isSigner: false, isWritable: false},
{pubkey: keypair.publicKey, isSigner: true, isWritable: false}];

/* Prepare parameters */
let allocateStruct = {
index: 0, // Loan2Value is instruction #0 in the program
layout: struct([
u8('instruction'),
])
};
let data = Buffer.alloc(allocateStruct.layout.span);
let layoutFields = Object.assign({instruction: allocateStruct.index});
allocateStruct.layout.encode(layoutFields, data);

/* Invoke transaction */
let tx = new web3.Transaction({
feePayer: payer.publicKey
});
let contract = process.argv[2];
console.log("Invoking contract " + contract + "...");
tx.add(new web3.TransactionInstruction({
keys,
programId: contract,
data
}));

let txSig = await web3.sendAndConfirmTransaction(conn, tx, [payer, keypair]);
console.log("Confirmed TxHash " + txSig);
}

let ethToUSD = "EdVCmQ9FSPcVe5YySXDPCRmc8aDQLKJ9xvYBMZPie1Vw";
let usdtToUSD = "38xoQ4oeJCBrcVvca2cGk7iV1dAfrmTR1kmhSCJQ8Jto";
invoke(ethToUSD, usdtToUSD);
18 changes: 18 additions & 0 deletions examples/sol-contract/scripts/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"name": "scripts",
"version": "1.0.0",
"description": "",
"main": "invoke.js",
"scripts": {
"build": "npx tsc"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"typescript": "^4.8.3"
},
"dependencies": {
"@solana/web3.js": "^1.56.2"
}
}
10 changes: 10 additions & 0 deletions examples/sol-contract/scripts/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"compilerOptions": {
"module": "commonjs",
"esModuleInterop": true,
"target": "es6",
"moduleResolution": "node",
"sourceMap": true
},
"lib": ["es2015"]
}
20 changes: 20 additions & 0 deletions examples/sol-contract/src/entrypoint.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//! Program entrypoint

use solana_program::entrypoint;
use solana_program::pubkey::Pubkey;
use solana_program::account_info::AccountInfo;
use solana_program::entrypoint::ProgramResult;

// Every solana program has an entry point function with 3 parameters:
// the program ID, the accounts being touched by this program,
// and an arbitrary byte array as the input data for execution.
entrypoint!(process_instruction);
fn process_instruction(
program_id: &Pubkey,
accounts: &[AccountInfo],
instruction_data: &[u8],
) -> ProgramResult {
crate::processor::process_instruction(
program_id, accounts, instruction_data
)
}
11 changes: 11 additions & 0 deletions examples/sol-contract/src/instruction.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
//! Program instructions

use borsh::BorshSerialize;
use borsh::BorshDeserialize;

// A solana program contains a number of instructions.
// And this example contract contains only one instruction.
#[derive(Clone, Debug, BorshSerialize, BorshDeserialize, PartialEq)]
pub enum PythClientInstruction {
Loan2Value {}, // In this enum, Loan2Value is number 0.
}
5 changes: 5 additions & 0 deletions examples/sol-contract/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// This is the file being compiled to the bpf shared object (.so).
// It specifies the 3 modules of this example contract.
pub mod processor;
pub mod entrypoint;
pub mod instruction;
67 changes: 67 additions & 0 deletions examples/sol-contract/src/processor.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
//! Program instruction processor

use solana_program::msg;
use solana_program::pubkey::Pubkey;
use solana_program::account_info::AccountInfo;
use solana_program::entrypoint::ProgramResult;
use solana_program::program_error::ProgramError;

use borsh::BorshDeserialize;
use crate::instruction::PythClientInstruction;
use pyth_sdk_solana::load_price_feed_from_account_info;

pub fn process_instruction(
_program_id: &Pubkey,
_accounts: &[AccountInfo],
input: &[u8],
) -> ProgramResult {
// Checking the validity of parameters is important.
// This important step is skipped in this example contract.
let instruction = PythClientInstruction::try_from_slice(input)?;
match instruction {
PythClientInstruction::Loan2Value {} => {
let loan = &_accounts[0];
let collateral = &_accounts[1];
msg!("The loan key is {}.", loan.key);
msg!("The collateral key is {}.", collateral.key);
msg!("Assume 1 unit of loan and 3000 unit of collateral.");
let loan_cnt = 1;
let collateral_cnt = 3000;

// Calculate the value of the loan.
// Pyth is called to get the unit price of the loan.
let loan_value;
let feed1 = load_price_feed_from_account_info(loan)?;
let result1 = feed1.get_current_price().ok_or(ProgramError::Custom(0))?;
if let Some(v) = result1.price.checked_mul(loan_cnt) {
loan_value = v;
} else {
// An overflow occurs for result1.price * loan_cnt.
return Err(ProgramError::Custom(1))
}

// Calculate the value of the collateral.
// Pyth is called to get the unit price of the collateral.
let collateral_value;
let feed2 = load_price_feed_from_account_info(collateral)?;
let result2 = feed2.get_current_price().ok_or(ProgramError::Custom(0))?;
if let Some(v) = result2.price.checked_mul(collateral_cnt) {
collateral_value = v;
} else {
// An overflow occurs for result2.price * collateral_cnt.
return Err(ProgramError::Custom(1))
}

// Check whether the value of the collateral is higher.
if collateral_value > loan_value {
msg!("Loan unit price is {}.", result1.price);
msg!("Collateral unit price is {}.", result2.price);
msg!("The value of collateral is higher.");
return Ok(())
} else {
msg!("The value of loan is higher!");
return Err(ProgramError::Custom(2))
}
}
}
}