Skip to content

Commit df48fe2

Browse files
authored
feat(lazer): add client to solana example program (#34)
1 parent 83c15bc commit df48fe2

File tree

3 files changed

+210
-1
lines changed

3 files changed

+210
-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: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,23 @@ 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+
solana-client = { version = "1.18", optional = true }
22+
anyhow = { version = "1.0.93", optional = true }
23+
solana-sdk = { version = "1.18.26", optional = true }
24+
hex = { version = "0.4.3", optional = true }
25+
pyth-lazer-solana-contract = { version = "0.1.0", optional = true }
26+
env_logger = { version = "0.11.5", optional = true }
1727

1828
[dev-dependencies]
1929
hex = "0.4.3"
@@ -23,3 +33,12 @@ tokio = { version = "1.40.0", features = ["full"] }
2333
byteorder = "1.5.0"
2434
pyth-lazer-solana-contract = "0.1.0"
2535
anchor-lang = "0.30.1"
36+
37+
[features]
38+
solana-client = ["dep:solana-client"]
39+
anyhow = ["dep:anyhow"]
40+
solana-sdk = ["dep:solana-sdk"]
41+
hex = ["dep:hex"]
42+
pyth-lazer-solana-contract = ["dep:pyth-lazer-solana-contract"]
43+
env_logger = ["dep:env_logger"]
44+
client = ["solana-client", "anyhow", "solana-sdk", "hex", "pyth-lazer-solana-contract", "env_logger"]

lazer/solana/src/bin/client.rs

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

0 commit comments

Comments
 (0)