Lokal na Pag-gawa
Pagsisimula ng Lokal na Validator
Ang pagsubok sa iyong program code nang lokal ay maaaring maging mas maaasahan kaysa pagsubok sa devnet, at makakatulong sa iyong subukan bago ito subukan sa devnet.
Maaari mong i-setup ang iyong local-test-validator sa pamamagitan ng pag-install ng solana tool suite at tumatakbo
solana-test-validator
Ang mga pakinabang ng paggamit ng local-test-validator ay kinabibilangan ng:
- Walang mga limitasyon sa rate ng RPC
- Walang limitasyon sa airdrop
- Direktang on-chain program deployment (
--bpf-program ...
) - I-clone ang mga account mula sa isang pampublikong cluster, kabilang ang mga programa (
--clone ...
) - Nako-configure ang pagpapanatili ng kasaysayan ng transaksyon (
--limit-ledger-size ...
) - Nako-configure na haba ng panahon (
--slots-per-epoch ...
) - Tumalon sa isang arbitrary slot (
--warp-slot ...
)
Kumokonekta sa Mga Environment
Kapag nagtatrabaho ka sa pagbuo ng Solana, kakailanganin mong kumonekta sa isang partikular na endpoint ng RPC API. May 3 pampublikong pag-gawa ang Solana environment:
- mainnet-beta https://api.mainnet-beta.solana.com
- devnet https://api.devnet.solana.com
- testnet https://api.testnet.solana.com
import { clusterApiUrl, Connection } from "@solana/web3.js";
(async () => {
const connection = new Connection(clusterApiUrl("mainnet-beta"), "confirmed");
})();
const connection = new Connection(clusterApiUrl("mainnet-beta"), "confirmed");
from solana.rpc.api import Client
client = Client("https://api.mainnet-beta.solana.com")
client = Client("https://api.mainnet-beta.solana.com")
#include "solana.hpp"
using namespace many::solana;
int main() {
Connection connection("https://api.mainnet-beta.solana.com");
return 0;
}
Connection connection("https://api.mainnet-beta.solana.com");
use solana_client::rpc_client::RpcClient;
use solana_sdk::commitment_config::CommitmentConfig;
fn main() {
let rpc_url = String::from("https://api.mainnet-beta.solana.com");
let client = RpcClient::new_with_commitment(rpc_url, CommitmentConfig::confirmed());
}
let rpc_url = String::from("https://api.mainnet-beta.solana.com");
let client = RpcClient::new_with_commitment(rpc_url, CommitmentConfig::confirmed());
solana config set --url https://api.mainnet-beta.solana.com
solana config set --url https://api.mainnet-beta.solana.com
Sa wakas, maaari ka ring kumonekta sa isang pribadong kumpol, alinman sa isang lokal o tumatakbo nang malayuan kasama ang mga sumusunod:
import { Connection } from "@solana/web3.js";
(async () => {
// This will connect you to your local validator
const connection = new Connection("http://127.0.0.1:8899", "confirmed");
})();
const connection = new Connection("http://127.0.0.1:8899", "confirmed");
from solana.rpc.api import Client
client = Client("http://127.0.0.1:8899")
client = Client("http://127.0.0.1:8899")
#include "solana.hpp"
using namespace many::solana;
int main() {
Connection connection("http://127.0.0.1:8899");
return 0;
}
Connection connection("http://127.0.0.1:8899");
use solana_client::rpc_client::RpcClient;
use solana_sdk::commitment_config::CommitmentConfig;
fn main() {
let rpc_url = String::from("http://127.0.0.1:8899");
let client = RpcClient::new_with_commitment(rpc_url, CommitmentConfig::confirmed());
}
let rpc_url = String::from("http://127.0.0.1:8899");
let client = RpcClient::new_with_commitment(rpc_url, CommitmentConfig::confirmed());
solana config set --url http://privaterpc.com
solana config set --url http://privaterpc.com
Pag-subscribe sa Mga Kaganapan
Nagbibigay ang mga websocket ng interface ng pub/sub kung saan maaari kang makinig sa ilang partikular na kaganapan. Sa halip na i-ping ang isang tipikal na HTTP endpoint sa isang agwat upang makakuha ng madalas na mga update, maaari mo na lang matanggap ang mga update na iyon kapag nangyari ang mga ito.
Ang web3 ni Solana Connection
sa ilalim ng hood ay bumubuo ng endpoint ng websocket at nagrerehistro ng websocket client kapag gumawa ka ng bagong ` Halimbawa ng koneksyon (tingnan ang source code dito).
Ang klase ng Connection
ay naglalantad ng mga pub/sub na pamamaraan - lahat sila ay nagsisimula sa on
, tulad ng mga emitter ng kaganapan. Kapag tinawag mo ang mga pamamaraan ng listener na ito, nagrerehistro ito ng bagong subscription sa websocket client ng instance na Connection
na iyon. Ang halimbawang paraan ng pub/sub na ginagamit namin sa ibaba ay onAccountChange
. Ibibigay ng callback ang na-update na data ng estado sa pamamagitan ng mga argumento (tingnan ang AccountChangeCallback
bilang isang halimbawa).
import { clusterApiUrl, Connection, Keypair } from "@solana/web3.js";
(async () => {
// Establish new connect to devnet - websocket client connected to devnet will also be registered here
const connection = new Connection(clusterApiUrl("devnet"), "confirmed");
// Create a test wallet to listen to
const wallet = Keypair.generate();
// Register a callback to listen to the wallet (ws subscription)
connection.onAccountChange(
wallet.publicKey(),
(updatedAccountInfo, context) =>
console.log("Updated account info: ", updatedAccountInfo),
"confirmed"
);
})();
// Establish new connect to devnet - websocket client connected to devnet will also be registered here
const connection = new Connection(clusterApiUrl("devnet"), "confirmed");
// Create a test wallet to listen to
const wallet = Keypair.generate();
// Register a callback to listen to the wallet (ws subscription)
connection.onAccountChange(
wallet.publicKey(),
(updatedAccountInfo, context) =>
console.log("Updated account info: ", updatedAccountInfo),
"confirmed"
);
import asyncio
from solders.keypair import Keypair
from solana.rpc.websocket_api import connect
async def main():
async with connect("wss://api.devnet.solana.com") as websocket:
# Create a Test Wallet
wallet = Keypair()
# Subscribe to the Test wallet to listen for events
await websocket.account_subscribe(wallet.pubkey())
# Capture response from account subscription
first_resp = await websocket.recv()
print("Subscription successful with id {}, listening for events \n".format(first_resp.result))
updated_account_info = await websocket.recv()
print(updated_account_info)
asyncio.run(main())
async with connect("wss://api.devnet.solana.com") as websocket:
# Create a Test Wallet
wallet = Keypair()
# Subscribe to the Test wallet to listen for events
await websocket.account_subscribe(wallet.pubkey())
# Capture response from account subscription
first_resp = await websocket.recv()
print("Subscription successful with id {}, listening for events \n".format(first_resp.result))
updated_account_info = await websocket.recv()
print(updated_account_info)
// clang++ on_account_change.cpp -o on_account_change -std=c++17 -lssl -lcrypto -lsodium
#include "solana.hpp"
using namespace many::solana;
int main() {
Connection connection("https://api.devnet.solana.com");
auto key_pair = Keypair::generate();
int subscriptionId = connection.on_account_change(key_pair.public_key, [&](Result<Account> result) {
Account account = result.unwrap();
std::cout << "owner = " << account.owner.to_base58() << std::endl;
std::cout << "lamports = " << account.lamports << std::endl;
std::cout << "data = " << account.data << std::endl;
std::cout << "executable = " << (account.executable ? "true" : "false") << std::endl;
});
sleep(1);
std::string tx_hash = connection.request_airdrop(key_pair.public_key).unwrap();
std::cout << "tx hash = " << tx_hash << std::endl;
for (int i = 0; i < 10; i++) {
connection.poll();
sleep(1);
}
connection.remove_account_listener(subscriptionId);
return 0;
}
auto key_pair = Keypair::generate();
int subscriptionId = connection.on_account_change(key_pair.public_key, [&](Result<Account> result) {
Account account = result.unwrap();
std::cout << "owner = " << account.owner.to_base58() << std::endl;
std::cout << "lamports = " << account.lamports << std::endl;
std::cout << "data = " << account.data << std::endl;
std::cout << "executable = " << (account.executable ? "true" : "false") << std::endl;
});
for (int i = 0; i < 10; i++) {
connection.poll();
sleep(1);
}
connection.remove_account_listener(subscriptionId);
use solana_client::pubsub_client::PubsubClient;
use solana_client::rpc_config::RpcAccountInfoConfig;
use solana_sdk::commitment_config::CommitmentConfig;
use solana_sdk::signature::{Keypair, Signer};
fn main() {
let wallet = Keypair::new();
let pubkey = Signer::pubkey(&wallet);
let ws_url = String::from("wss://api.devnet.solana.com/");
println!("{}", ws_url);
if let Ok(subscription) = PubsubClient::account_subscribe(
&ws_url,
&pubkey,
Some(RpcAccountInfoConfig {
encoding: None,
data_slice: None,
commitment: Some(CommitmentConfig::confirmed()),
}),
) {
let (mut ws_client, receiver) = subscription;
println!("Subscription successful, listening for events");
let handle = std::thread::spawn(move || loop {
println!("Waiting for a message");
match receiver.recv() {
Ok(message) => println!("{:?}", message),
Err(err) => {
println!("Connection broke with {:}", err);
break;
}
}
});
handle.join().unwrap();
ws_client.shutdown().unwrap()
} else {
println!("Errooooor");
}
}
let ws_url = String::from("wss://api.devnet.solana.com/");
let (mut client, receiver) = PubsubClient::account_subscribe(
&ws_url,
&pubkey,
Some(RpcAccountInfoConfig {
encoding: None,
data_slice: None,
commitment: Some(CommitmentConfig::confirmed()),
}),
).unwrap();
let message = match receiver.recv().unwrap();
println!("{:?}", message)
Pagkuha ng Test SOL
Kapag nagtatrabaho ka nang lokal, kailangan mo ng ilang SOL para makapagpadala mga transaksyon. Sa mga hindi mainnet na environment maaari kang makatanggap ng SOL sa pamamagitan ng i-airdrop ito sa iyong address
import { Connection, Keypair, LAMPORTS_PER_SOL } from "@solana/web3.js";
(async () => {
const keypair = Keypair.generate();
const connection = new Connection("http://127.0.0.1:8899", "confirmed");
const signature = await connection.requestAirdrop(
keypair.publicKey,
LAMPORTS_PER_SOL
);
const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash();
await connection.confirmTransaction({
blockhash,
lastValidBlockHeight,
signature
});
})();
const airdropSignature = await connection.requestAirdrop(
keypair.publicKey,
LAMPORTS_PER_SOL
);
await connection.confirmTransaction(airdropSignature);
from solders.keypair import Keypair
from solana.rpc.api import Client
wallet = Keypair()
client = Client("https://api.devnet.solana.com")
#Input Airdrop amount in LAMPORTS
client.request_airdrop(wallet.pubkey(), 1000000000)
#Airdrops 1 SOL
#Input Airdrop amount in LAMPORTS
client.request_airdrop(wallet.pubkey(), 1000000000)
#Airdrops 1 SOL
// clang++ request_airdrop.cpp -o request_airdrop -std=c++17 -lssl -lcrypto -lsodium
#include "solana.hpp"
using namespace many::solana;
int main() {
Connection connection("https://api.devnet.solana.com");
auto key_pair = Keypair::generate();
std::string tx_hash = connection.request_airdrop(key_pair.public_key).unwrap();
std::cout << "tx hash = " << tx_hash << std::endl;
return 0;
}
connection.request_airdrop(key_pair.public_key).unwrap();
use solana_client::rpc_client::RpcClient;
use solana_sdk::commitment_config::CommitmentConfig;
use solana_sdk::native_token::LAMPORTS_PER_SOL;
use solana_sdk::signature::{Keypair, Signer};
fn main() {
let wallet = Keypair::new();
let pubkey = Signer::pubkey(&wallet);
let rpc_url = String::from("https://api.devnet.solana.com");
let client = RpcClient::new_with_commitment(rpc_url, CommitmentConfig::confirmed());
match client.request_airdrop(&pubkey, LAMPORTS_PER_SOL) {
Ok(sig) => loop {
if let Ok(confirmed) = client.confirm_transaction(&sig) {
if confirmed {
println!("Transaction: {} Status: {}", sig, confirmed);
break;
}
}
},
Err(_) => println!("Error requesting airdrop"),
};
}
match client.request_airdrop(&pubkey, LAMPORTS_PER_SOL) {
Ok(sig) => loop {
if let Ok(confirmed) = client.confirm_transaction(&sig) {
if confirmed {
println!("Transaction: {} Status: {}", sig, confirmed);
break;
}
}
},
Err(_) => println!("Error requesting airdrop"),
};
solana airdrop 1
# Return
# "1 SOL"
solana airdrop 1
Paggamit ng Mainnet Accounts at Programs
Kadalasan, umaasa ang mga lokal na pagsubok sa mga programa at account na available lang sa mainnet. Ang Solana CLI ay nagbibigay-daan sa parehong:
- Mag-download ng Mga Programa at Account
- Mag-load ng Mga Programa at Account sa isang lokal na validator
Paano mag-load ng mga account mula sa mainnet
Posibleng i-download ang SRM token mint account para mag-file:
# solana account -u <source cluster> --output <output format> --output-file <destination file name/path> <address of account to fetch>
solana account -u m --output json-compact --output-file SRM_token.json SRMuApVNdxXokk5GT7XD5cUUgXMBCoAz2LHeuAoKWRt
solana account -u m --output json-compact --output-file SRM_token.json SRMuApVNdxXokk5GT7XD5cUUgXMBCoAz2LHeuAoKWRt
Ang paglo-load nito sa iyong localnet ay ginagawa sa pamamagitan ng pagpasa sa file ng account at patutunguhang address (sa lokal na cluster) kapag sinimulan ang validator:
# solana-test-validator --account <address to load the account to> <path to account file> --reset
solana-test-validator --account SRMuApVNdxXokk5GT7XD5cUUgXMBCoAz2LHeuAoKWRt SRM_token.json --reset
solana-test-validator --account SRMuApVNdxXokk5GT7XD5cUUgXMBCoAz2LHeuAoKWRt SRM_token.json --reset
Paano mag-load ng mga programa mula sa mainnet
Katulad nito, posibleng i-download ang Serum Dex v3 program:
# solana program dump -u <source cluster> <address of account to fetch> <destination file name/path>
solana program dump -u m 9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin serum_dex_v3.so
solana program dump -u m 9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin serum_dex_v3.so
Ang paglo-load nito sa iyong localnet ay tapos na sa pamamagitan ng pagpasa sa file ng programa at patutunguhang address (sa lokal na kumpol) kapag sinimulan ang validator:
# solana-test-validator --bpf-program <address to load the program to> <path to program file> --reset
solana-test-validator --bpf-program 9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin serum_dex_v3.so --reset
solana-test-validator --bpf-program 9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin serum_dex_v3.so --reset