Skip to content

Commit 1d01b84

Browse files
authored
Merge pull request #6 from thrishank/examples
update Examples
2 parents 0a06060 + 5b772ef commit 1d01b84

6 files changed

Lines changed: 196 additions & 197 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ async fn main() {
4848
let quote = client.get_ultra_order(&ultra).await
4949
.expect("Failed to get ultra order");
5050

51-
// sign the transaction. Checkout examples/src/ultra.rs on how to sign the transaction
51+
// sign the transaction. Checkout examples/src/lib.rs on how to sign the transaction
5252

5353
// execute the signed transaction
5454
let execute = UltraExecuteOrderRequest {

examples/src/lib.rs

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
use base64::Engine;
2+
use base64::engine::general_purpose::STANDARD;
3+
use bincode::{deserialize, serialize};
4+
use dotenv::dotenv;
5+
6+
use solana_sdk::{
7+
signature::{Keypair, Signer},
8+
transaction::VersionedTransaction,
9+
};
10+
use std::env;
11+
12+
/// Signs a base64-encoded Solana transaction using a private key from `.env` file,
13+
/// and returns the signed transaction re-encoded in base64 format.
14+
///
15+
/// # Environment Variables
16+
/// - `PRIVATE_KEY`: A base58-encoded private key (64-byte array) stored in the `.env` file.
17+
///
18+
/// # Arguments
19+
/// - `transaction` - A base64-encoded `VersionedTransaction` to be signed.
20+
///
21+
/// # Returns
22+
/// - A base64-encoded, signed `VersionedTransaction`.
23+
///
24+
/// # Panics
25+
/// - If the `.env` file can't be loaded.
26+
/// - If the `PRIVATE_KEY` is not set or is invalid.
27+
/// - If decoding/encoding fails at any step (base64, base58, bincode).
28+
///
29+
/// # Notes
30+
/// - This function assumes the transaction requires a single signature.
31+
/// - Modify the signature insertion logic if multiple signatures are needed.
32+
///
33+
/// # Example
34+
/// ```
35+
/// let signed_tx = sign_transaction(base64_tx_string);
36+
/// ```
37+
pub fn sign_transaction(transaction: String) -> String {
38+
// Load .env file
39+
dotenv().ok();
40+
41+
// Fetch the base58-encoded private key from the environment
42+
let key = env::var("PRIVATE_KEY").expect("PRIVATE_KEY not set in .env");
43+
44+
// Decode the private key from base58 to raw bytes. If you have raw bytes, you can skip decode
45+
// and just pass them directly to Keypair::from_bytes.
46+
let key_bytes = bs58::decode(key)
47+
.into_vec()
48+
.expect("Failed to decode base58 private key");
49+
50+
// Construct a Keypair from the private key bytes
51+
let keypair = Keypair::from_bytes(&key_bytes).expect("Failed to create Keypair");
52+
53+
// Decode the incoming base64-encoded transaction into raw bytes
54+
let swap_tx_bytes = STANDARD
55+
.decode(transaction)
56+
.expect("Failed to decode base64 transaction");
57+
58+
// Deserialize the raw bytes into a VersionedTransaction struct
59+
let mut tx: VersionedTransaction = deserialize(&swap_tx_bytes).unwrap();
60+
61+
// Serialize the message to be signed (excluding signatures)
62+
let message = tx.message.serialize();
63+
64+
// sign the transaction with the keypair
65+
let signature = keypair.sign_message(&message);
66+
67+
// If there is a need for multiple signatures (fee payer), you can modify this part accordingly.
68+
69+
// Inject the signature into the transaction
70+
if tx.signatures.is_empty() {
71+
tx.signatures.push(signature);
72+
} else {
73+
tx.signatures[0] = signature;
74+
};
75+
76+
// Serialize the signed transaction
77+
let signed_tx_bytes = serialize(&tx).unwrap();
78+
79+
// Encode the signed transaction back to base64
80+
STANDARD.encode(&signed_tx_bytes)
81+
}

examples/src/main.rs

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,5 @@ mod ultra;
66

77
#[tokio::main]
88
async fn main() {
9-
// The Jupiter Ultra API is the only API you ever need to experience or build the best trading experience on Solana.
10-
// Ultra API is the spiritual successor to Swap API, and is much simpler to use than Swap API.
11-
// If you are first starting out on your Solana development journey, using Ultra API is highly recommended over Swap API.
12-
// https://dev.jup.ag/docs/ultra-api/
13-
// ultra::ultra().await;
14-
15-
// swap::swap().await; // swap tokens using Jupiter swap api
16-
// swap::swap_with_instructions().await; // build the transaction with Jupiter swap instructions
17-
18-
// token::token_balances().await; // get token balances using Jupiter token api
19-
// token::token_price().await; // get token price using Jupiter token api
20-
// token::token_info().await // get token malicious info
9+
ultra::ultra().await;
2110
}

examples/src/recurring.rs

Lines changed: 15 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,69 +1,41 @@
1-
use base64::Engine;
2-
use base64::engine::general_purpose::STANDARD;
3-
use bincode::{deserialize, serialize};
4-
use dotenv::dotenv;
1+
use jup::sign_transaction;
52
use jup_ag_sdk::{
63
JupiterClient,
74
types::{CreateRecurringOrderRequest, ExecuteRecurringRequest},
85
};
9-
use solana_sdk::{
10-
signature::{Keypair, Signer},
11-
transaction::VersionedTransaction,
12-
};
13-
use std::env;
146

157
async fn recurring() {
168
let client = JupiterClient::new("https://lite-api.jup.ag");
9+
1710
// create a recurring time based order to swap 100 USDC for SOL every 10 days, with a duration
18-
// of 84600 seconds (1 day)
19-
let data = CreateRecurringOrderRequest::new_time_order(
11+
// of 86400 seconds (1 day)
12+
let recurring_order_request = CreateRecurringOrderRequest::new_time_order(
2013
"your wallet address",
2114
"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
2215
"So11111111111111111111111111111111111111112",
2316
1_000_000_000,
2417
10,
25-
84600,
18+
86400,
2619
);
2720

28-
let response = client
29-
.create_recurring_order(&data)
21+
let create_order_response = client
22+
.create_recurring_order(&recurring_order_request)
3023
.await
3124
.expect("Failed to create recurring order");
3225

33-
dotenv().ok();
34-
35-
let key = env::var("PRIVATE_KEY").expect("PRIVATE_KEY not set in .env");
36-
37-
let key_bytes = bs58::decode(key)
38-
.into_vec()
39-
.expect("Failed to decode base58 private key");
40-
41-
let keypair = Keypair::from_bytes(&key_bytes).expect("Failed to create Keypair");
42-
43-
let swap_tx_bytes = STANDARD
44-
.decode(response.transaction)
45-
.expect("Failed to decode base64 transaction");
26+
let base64_signed_tx = sign_transaction(create_order_response.transaction);
4627

47-
let mut tx: VersionedTransaction = deserialize(&swap_tx_bytes).unwrap();
48-
let message = tx.message.serialize();
49-
50-
// sign the transaction with the keypair
51-
let signature = keypair.sign_message(&message);
52-
53-
tx.signatures[0] = signature;
54-
55-
let signed_tx_bytes = serialize(&tx).unwrap();
56-
let base64_signed_tx = STANDARD.encode(&signed_tx_bytes);
57-
58-
let execute = ExecuteRecurringRequest {
59-
request_id: response.request_id,
28+
let execute_request = ExecuteRecurringRequest {
29+
request_id: create_order_response.request_id,
6030
signed_transaction: base64_signed_tx,
6131
};
6232

63-
client
64-
.execute_recurring_order(&execute)
33+
let execute_res = client
34+
.execute_recurring_order(&execute_request)
6535
.await
6636
.expect("Failed to execute recurring order");
6737

68-
println!("{}", signature)
38+
println!("signature: {}", execute_res.signature)
39+
40+
// TODO: add other api calls here
6941
}

examples/src/trigger.rs

Lines changed: 66 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1,113 +1,96 @@
1-
use base64::Engine;
2-
use base64::engine::general_purpose::STANDARD;
3-
use bincode::{deserialize, serialize};
4-
use dotenv::dotenv;
5-
1+
use jup::sign_transaction;
62
use jup_ag_sdk::{
73
JupiterClient,
8-
types::{CreateTriggerOrder, ExecuteTriggerOrder, GetTriggerOrders, OrderStatus},
9-
};
10-
use solana_sdk::{
11-
signature::{Keypair, Signer},
12-
transaction::VersionedTransaction,
4+
types::{
5+
CreateTriggerOrder,
6+
ExecuteTriggerOrder,
7+
GetTriggerOrders,
8+
OrderStatus,
9+
// CancelTriggerOrder,
10+
},
1311
};
14-
use std::env;
1512

16-
async fn trigger() {
13+
pub async fn trigger() {
14+
// Initialize the Jupiter client
1715
let client = JupiterClient::new("https://lite-api.jup.ag");
1816

19-
// create order parmas
20-
let data = CreateTriggerOrder::new(
21-
"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
22-
"JUPyiwrYJFskUPiHa7hkeR8VUtAeFoSYbKedZNsDvCN",
23-
"372sKPyyiwU5zYASHzqvYY48Sv4ihEujfN5rGFKhVQ9j",
24-
"372sKPyyiwU5zYASHzqvYY48Sv4ihEujfN5rGFKhVQ9j",
25-
10_000_000, // swap 10 USDC for 20 JUP
26-
20_000_000,
17+
// User's wallet address
18+
let user_address = "your wallet address"; // Replace with your actual wallet address
19+
20+
// Create a trigger order to swap 10 USDC for 20 JUP
21+
let input_mint = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"; // USDC
22+
let output_mint = "JUPyiwrYJFskUPiHa7hkeR8VUtAeFoSYbKedZNsDvCN"; // JUP
23+
let input_amount = 10_000_000; // 10 USDC
24+
let output_amount = 20_000_000; // 20 JUP
25+
26+
// Construct the trigger order request
27+
let create_order_request = CreateTriggerOrder::new(
28+
input_mint,
29+
output_mint,
30+
user_address,
31+
user_address,
32+
input_amount,
33+
output_amount,
2734
);
2835

29-
// get the unsigned transaction to create the order
30-
let create_order = client
31-
.create_trigger_order(&data)
36+
// Get the unsigned transaction and request ID for creating the order
37+
let create_response = client
38+
.create_trigger_order(&create_order_request)
3239
.await
3340
.expect("Failed to create trigger order");
3441

35-
println!("Create Trigger Order: {:?}", create_order);
36-
37-
// Load .env variables into std::env
38-
dotenv().ok();
39-
40-
// Read the variable
41-
let key = env::var("PRIVATE_KEY").expect("PRIVATE_KEY not set in .env");
42-
43-
// if you have the private key in base58 format. Else skip this decode
44-
let key_bytes = bs58::decode(key)
45-
.into_vec()
46-
.expect("Failed to decode base58 private key");
47-
48-
let keypair = Keypair::from_bytes(&key_bytes).expect("Failed to create Keypair");
49-
50-
let swap_tx_bytes = STANDARD
51-
.decode(create_order.transaction)
52-
.expect("Failed to decode base64 transaction");
53-
54-
let mut tx: VersionedTransaction = deserialize(&swap_tx_bytes).unwrap();
55-
let message = tx.message.serialize();
56-
57-
// sign the transaction with the keypair
58-
let signature = keypair.sign_message(&message);
42+
println!("📦 Created Trigger Order: {:?}", create_response);
5943

60-
if tx.signatures.is_empty() {
61-
tx.signatures.push(signature);
62-
} else {
63-
tx.signatures[0] = signature;
64-
};
65-
66-
let signed_tx_bytes = serialize(&tx).unwrap();
67-
let base64_signed_tx = STANDARD.encode(&signed_tx_bytes);
44+
// Sign the transaction locally
45+
let signed_tx_base64 = sign_transaction(create_response.transaction);
6846

69-
// here we execute the trigger order. Instead this you can directly send the transaction using a rpc
70-
let exe = ExecuteTriggerOrder {
71-
request_id: create_order.request_id,
72-
signed_transaction: base64_signed_tx,
47+
// Send the signed transaction for execution
48+
let execute_request = ExecuteTriggerOrder {
49+
request_id: create_response.request_id,
50+
signed_transaction: signed_tx_base64,
7351
};
7452

75-
let execute = client
76-
.execute_trigger_order(&exe)
53+
let execute_response = client
54+
.execute_trigger_order(&execute_request)
7755
.await
7856
.expect("Failed to execute trigger order");
7957

80-
println!("Execute Trigger Order: {:?}", execute);
58+
println!(
59+
"🚀 Executed Trigger Order, singnature: {}",
60+
execute_response.signature
61+
);
8162

82-
// get trigger orders for user address
83-
let params = GetTriggerOrders {
84-
user: "372sKPyyiwU5zYASHzqvYY48Sv4ihEujfN5rGFKhVQ9j".to_string(),
63+
// Fetch the list of trigger orders for the user
64+
let get_orders_params = GetTriggerOrders {
65+
user: user_address.to_string(),
8566
order_status: OrderStatus::History,
8667
input_mint: None,
8768
output_mint: None,
8869
include_failed_tx: None,
8970
page: None,
9071
};
9172

92-
let orders = client
93-
.get_trigger_orders(&params)
73+
let order_history = client
74+
.get_trigger_orders(&get_orders_params)
9475
.await
9576
.expect("Failed to get trigger orders");
9677

97-
println!("Trigger Orders: {:?}", orders);
98-
99-
// cance a trigger order
100-
// let cancel = CancelTriggerOrder::new(
101-
// "372sKPyyiwU5zYASHzqvYY48Sv4ihEujfN5rGFKhVQ9j",
102-
// "HeyWQcYd9t6BFGDfwh3w13F9KmiSNyPJuRPm49kiynFs",
103-
// );
104-
//
105-
// let cancel_order = client
106-
// .cancel_trigger_order(&cancel)
107-
// .await
108-
// .expect("Failed to cancel trigger order");
109-
//
110-
// println!("Cancel Trigger Order: {:?}", cancel_order);
111-
//
112-
// and then sign the transaction and excute same as the create_order
78+
println!("📖 Trigger Order History: {:?}", order_history);
79+
80+
// --- Cancel a trigger order ---
81+
/*
82+
let cancel_request = CancelTriggerOrder::new(
83+
user_address,
84+
"HeyWQcYd9t6BFGDfwh3w13F9KmiSNyPJuRPm49kiynFs", // Order ID to cancel
85+
);
86+
87+
let cancel_response = client
88+
.cancel_trigger_order(&cancel_request)
89+
.await
90+
.expect("Failed to cancel trigger order");
91+
92+
println!("❌ Cancelled Trigger Order: {:?}", cancel_response);
93+
94+
// Sign and execute cancel transaction same as above
95+
*/
11396
}

0 commit comments

Comments
 (0)