Skip to content

Commit 66c9a0a

Browse files
committed
feat(lazer): add client to solana example program
1 parent 69fc257 commit 66c9a0a

File tree

3 files changed

+213
-1
lines changed

3 files changed

+213
-1
lines changed

lazer/solana/Cargo.lock

Lines changed: 94 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lazer/solana/Cargo.toml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,24 @@ edition = "2021"
77
name = "pyth_lazer_solana_example"
88
crate-type = ["cdylib", "lib"]
99

10+
[[bin]]
11+
name = "client"
12+
required-features = ["client"]
13+
1014
[dependencies]
1115
pyth-lazer-sdk = "0.1.0"
1216

1317
solana-program = "1.18.26"
1418
bytemuck = { version = "1.18.0", features = ["derive"] }
1519
num-traits = "0.2.19"
1620
num-derive = "0.4.2"
21+
tokio = { version = "1.40.0", features = ["full"], optional = true }
22+
solana-client = { version = "1.18", optional = true }
23+
anyhow = { version = "1.0.93", optional = true }
24+
solana-sdk = { version = "1.18.26", optional = true }
25+
hex = { version = "0.4.3", optional = true }
26+
pyth-lazer-solana-contract = { version = "0.1.0", optional = true }
27+
env_logger = { version = "0.11.5", optional = true }
1728

1829
[dev-dependencies]
1930
hex = "0.4.3"
@@ -23,3 +34,13 @@ tokio = { version = "1.40.0", features = ["full"] }
2334
byteorder = "1.5.0"
2435
pyth-lazer-solana-contract = "0.1.0"
2536
anchor-lang = "0.30.1"
37+
38+
[features]
39+
tokio = ["dep:tokio"]
40+
solana-client = ["dep:solana-client"]
41+
anyhow = ["dep:anyhow"]
42+
solana-sdk = ["dep:solana-sdk"]
43+
hex = ["dep:hex"]
44+
pyth-lazer-solana-contract = ["dep:pyth-lazer-solana-contract"]
45+
env_logger = ["dep:env_logger"]
46+
client = ["tokio", "solana-client", "anyhow", "solana-sdk", "hex", "pyth-lazer-solana-contract", "env_logger"]

lazer/solana/src/bin/client.rs

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
use {
2+
anyhow::Context,
3+
bytemuck::bytes_of,
4+
pyth_lazer_sdk::ed25519_program_args,
5+
pyth_lazer_solana_example::{InitializeArgs, Instruction as ExampleInstruction, UpdateArgs},
6+
solana_client::rpc_client::RpcClient,
7+
solana_sdk::{
8+
instruction::{AccountMeta, Instruction},
9+
message::Message,
10+
pubkey::Pubkey,
11+
signature::read_keypair_file,
12+
signer::Signer,
13+
system_program, sysvar,
14+
transaction::Transaction,
15+
},
16+
std::env,
17+
};
18+
19+
#[tokio::main]
20+
async fn main() -> anyhow::Result<()> {
21+
env_logger::init();
22+
let client = RpcClient::new(env::var("SOLANA_RPC_URL")?);
23+
let latest_blockhash = client.get_latest_blockhash()?;
24+
let keypair = read_keypair_file(env::var("SOLANA_KEYPAIR_FILE")?).unwrap();
25+
let program_id: Pubkey = env::var("EXAMPLE_PROGRAM_PUBKEY")?.parse()?;
26+
27+
let (data_pda_key, _) = Pubkey::find_program_address(&[b"data"], &program_id);
28+
let cmd = env::args().nth(1).context("missing arg")?;
29+
30+
if cmd == "init" {
31+
let mut init_data = vec![ExampleInstruction::Initialize as u8];
32+
init_data.extend_from_slice(bytes_of(&InitializeArgs { price_feed_id: 2 }));
33+
34+
let tx = Transaction::new(
35+
&[&keypair],
36+
Message::new(
37+
&[Instruction::new_with_bytes(
38+
program_id,
39+
&init_data,
40+
vec![
41+
AccountMeta::new(keypair.pubkey(), true),
42+
AccountMeta::new(data_pda_key, false),
43+
AccountMeta::new_readonly(system_program::ID, false),
44+
],
45+
)],
46+
Some(&keypair.pubkey()),
47+
),
48+
latest_blockhash,
49+
);
50+
let signature = client.send_and_confirm_transaction(&tx)?;
51+
println!("OK {signature:?}");
52+
} else if cmd == "update" {
53+
let message = hex::decode(env::var("LAZER_UPDATE_HEX")?)?;
54+
let mut update_data = vec![ExampleInstruction::Update as u8];
55+
update_data.extend_from_slice(bytes_of(&UpdateArgs { hello: 42 }));
56+
update_data.extend_from_slice(&message);
57+
58+
// Instruction #0 will be ed25519 instruction;
59+
// Instruction #1 will be our contract instruction.
60+
let instruction_index = 1;
61+
// Total offset of Pyth Lazer update within the instruction data;
62+
// 1 byte is the instruction type.
63+
let message_offset = (size_of::<UpdateArgs>() + 1).try_into().unwrap();
64+
let ed25519_args =
65+
pyth_lazer_sdk::signature_offsets(&update_data, instruction_index, message_offset);
66+
let tx = Transaction::new(
67+
&[&keypair],
68+
Message::new(
69+
&[
70+
Instruction::new_with_bytes(
71+
solana_program::ed25519_program::ID,
72+
&ed25519_program_args(&[ed25519_args]),
73+
vec![],
74+
),
75+
Instruction::new_with_bytes(
76+
program_id,
77+
&update_data,
78+
vec![
79+
AccountMeta::new_readonly(sysvar::instructions::ID, false),
80+
AccountMeta::new(data_pda_key, false),
81+
AccountMeta::new_readonly(
82+
pyth_lazer_solana_contract::storage::ID,
83+
false,
84+
),
85+
],
86+
),
87+
],
88+
Some(&keypair.pubkey()),
89+
),
90+
latest_blockhash,
91+
);
92+
let signature = client.send_and_confirm_transaction(&tx)?;
93+
println!("OK {signature:?}");
94+
} else {
95+
panic!("unknown cmd");
96+
}
97+
Ok(())
98+
}

0 commit comments

Comments
 (0)