Solana開發(fā)學習筆記(一)——從Hello World出發(fā)
筆者注:因近期筆者工作需要,開始接觸 Solana 鏈上程序開發(fā)。本系列文章是筆者的學習筆記,既是為了備忘,也是希望得到 Solana 開發(fā)者的指點與交流。本系列文章將默認讀者已經(jīng)掌握 Rust 的基礎(chǔ)語法,故不涉及對 Rust 語法細節(jié)的解釋。如果讀者對 Rust 基礎(chǔ)語法還不熟練的話,本文下方推薦的 Rust 入門書籍《Rust 編程入門、實戰(zhàn)與進階》學習。
1.1 Solana 簡介
Solana 是一個高性能、無許可的底層公鏈,專注于在不犧牲去中心化或安全性的前提下提供可擴展性。Solana 主網(wǎng)于 2020 年一季度上線,目前主網(wǎng)的全球節(jié)點超過 800 個,TPS 最高可達 6.5 萬,出塊時間約 400 毫秒。
Solana 的共識算法采用 PoH(歷史證明),其核心是一個去中心化時鐘,該時鐘旨在解決缺乏單個可信賴時間源在分布式網(wǎng)絡中的時間問題。PoH 免除了在節(jié)點網(wǎng)絡中廣播時間戳的需求,從而提高整個網(wǎng)絡的效率。
1.1.1 鏈上程序
Solana 的智能合約叫做鏈上程序(On-chain Program),Solana 官方提供了 Rust 和 C 的 SDK 來支持開發(fā)鏈上程序。鏈上程序的開發(fā)工作流如圖 1-1 所示,開發(fā)者可以使用工具將程序編譯成 Berkley Packet Filter (BPF) 字節(jié)碼(文件以 .so 為擴展名),再部署到 Solana 鏈上,通過 Sealevel 并行智能合約運行時去執(zhí)行智能合約的邏輯。此外,基于 Solana JSON RPC API,官方提供了諸多 SDK 用于客戶端與 Solana 鏈上數(shù)據(jù)交互。
圖 1-1 鏈上程序開發(fā)工作流
1.1.2 賬戶模型
與以太坊類似,Solana 也是基于賬戶模型的區(qū)塊鏈。通過將任意狀態(tài)存儲于鏈上賬戶并同步復制給集群中的所有節(jié)點,可以創(chuàng)建復雜而強大的去中心化應用程序。
Solana 提供了一套不同于以太坊的賬戶模型,賬戶定義的字段如表 1-1 所示。Solana 的賬戶可以分為可執(zhí)行賬戶和不可執(zhí)行賬戶。
- 可執(zhí)行賬戶:存儲不可變的數(shù)據(jù),主要用于存儲程序的 BPF 字節(jié)碼。
- 不可執(zhí)行賬戶:存儲可變的數(shù)據(jù),主要用于存儲程序的狀態(tài)。
表 1-1 賬戶定義字段
字段 | 描述 |
---|---|
lamports | 賬戶余額 |
owner | 賬戶所有者 |
executable | 是否為可執(zhí)行賬戶 |
data | 賬戶存儲的數(shù)據(jù) |
rent_epoch | Solana鏈上程序的部署是按其賬戶大小進行定期收費的,如果賬戶無法支付租金,系統(tǒng)將清除該賬號 |
我們知道以太坊上每個智能合約的代碼和狀態(tài)都存儲在同一個賬戶中,而 Solana 鏈上程序是只讀或無狀態(tài)的,即程序的賬戶(可執(zhí)行賬戶)只存儲 BPF 字節(jié)碼,不存儲任何狀態(tài),程序會把狀態(tài)存儲在其他獨立的賬戶(不可執(zhí)行賬戶)中。為了區(qū)分某個賬戶是用作哪個程序的狀態(tài)存儲,每個賬戶都指定了一個程序作為其所有者。程序可以讀取其不作為所有者的賬戶中的狀態(tài),但只有作為所有者的程序才能修改賬戶中的狀態(tài),任何其他程序所做的修改都會被還原并導致交易失敗。
更多關(guān)于賬戶模型的資料可以參見官方文檔:https://solana.wiki/zh-cn/docs/account-model/
1.2 搭建編程環(huán)境
在開始 Solana 鏈上程序開發(fā)之前,需要先安裝和配置相關(guān)的編程環(huán)境。首先請正確安裝 Node、NPM 和 Rust 的最新穩(wěn)定版本,下面來安裝 Solana CLI 并配置相關(guān)環(huán)境。
1.2.1 安裝 Solana CLI
Solana CLI 是與 Solana 集群進行交互的命令行管理工具,包含節(jié)點程序 solana-validator、密鑰對生成工具 solana-keygen,以及合約開發(fā)工具 cargo-build-bpf、cargo-test-bpf 等。
在終端運行以下命令,可完成 Solana CLI 最新穩(wěn)定版的下載與安裝。
sh -c "$(curl -sSfL https://release.solana.com/stable/install)"
如果安裝成功,會出現(xiàn)以下內(nèi)容。
downloading stable installer ? stable commit e9bef425 initialized Adding export PATH="~/.local/share/solana/install/active_release/bin:$PATH" to ~/.profile Adding export PATH="~/.local/share/solana/install/active_release/bin:$PATH" to ~/.bash_profile Close and reopen your terminal to apply the PATH changes or run the following in your existing shell: export PATH="~/.local/share/solana/install/active_release/bin:$PATH"
Solana CLI 的所有命令行工具都安裝在 ~/.local/share/solana/install/active_release/bin 中,并會自動將該路徑加入 ~/.profile 和 ~/.bash_profile 文件的 PATH 環(huán)境變量。
運行以下命令,檢查 PATH 環(huán)境變量是否已正確設置。
solana --version // solana-cli 1.7.18 (src:e9bef425; feat:140464022)
如果能顯示 solana-cli 的版本號、版本哈希等信息,代表環(huán)境變量設置成功。如果未看到這些信息,請檢查相關(guān)文件中 PATH 環(huán)境變量設置的路徑是否正確。
如果已安裝過 Solana CLI,想升級到最新版本,可在終端運行以下命令。
solana-install update
1.2.2 配置 Solana CLI
1. 連接到集群
Solana 的集群有本地集群(localhost)和公開集群。根據(jù)不同的用途,公開集群又分為開發(fā)者網(wǎng)絡(devnet)、測試網(wǎng)(testnet)和主網(wǎng)(mainnet-beta)。
- devnet 是適用于開發(fā)者的集群,開發(fā)者可獲得 SOL token 的空投,但這個 SOL token 不具有真實價值,僅限測試使用。devnet 的 RPC 鏈接是 https://api.devnet.solana.com 。
- testnet 是用于測試最新功能的集群,如網(wǎng)絡性能、穩(wěn)定性和驗證程序行為等。同樣可獲得 SOL token 的空投,但也僅限測試使用。testnet 的 RPC 鏈接是 https://api.testnet.solana.com 。
- mainnet-beta 是主網(wǎng)集群,在 Mainnet Beta 上發(fā)行的 SOL token 具有真實價值。mainnet-beta 的 RPC 鏈接是 https://api.mainnet-beta.solana.com 。
運行以下命令,根據(jù)實際需要來選擇集群。
// 選擇localhost集群 solana config set --url localhost // 選擇devnet集群 solana config set --url devnet
2. 創(chuàng)建賬戶
如果是第一次使用 Solana CLI,需要先創(chuàng)建一個賬戶。運行以下命令,根據(jù)操作提示可以設置一個 BIP39 規(guī)范的密碼,此密碼用來增強助記詞的安全性,當然也可以為空。生成新的賬戶后,密鑰對會被自動寫入 ~/.config/solana/id.json 文件中。需要注意的是,這種存儲密鑰對的方式是不安全的,僅限開發(fā)測試使用。
solana-keygen new
要查看當前這個賬戶的公鑰,運行以下命令。
solana-keygen pubkey
當前如果是在 devnet 集群,該賬戶的余額為 0 SOL,可以運行以下命令查詢余額。
solana balance
在 devnet 上申請 SOL 空投,運行以下命令后再次查詢當前賬戶的余額,會發(fā)現(xiàn)余額為 2 SOL。
solana airdrop 2
1.3 第一個 Solana 項目——Hello World
Hello World 是一個官方演示項目,展示了如何使用 Rust 和 C 開發(fā)鏈上程序,并使用 Solana CLI 來構(gòu)建與部署,以及使用 Solana JavaScript SDK 與鏈上程序進行交互。
1.3.1 Hello World 源碼解讀
example-helloworld 項目的目錄結(jié)構(gòu)如下所示,其中 program-rust 目錄下是 Rust 開發(fā)的程序源代碼,client 目錄下是客戶端的源代碼。
example-helloworld | +-- src | | | +-- client | | | | | +-- hello_world.ts | | | | | +-- main.ts | | | | | +-- utils.ts | | | +-- program-rust | | | | | +-- src | | | | | | | +-- lib.rs | | | | | +-- tests | | | | | | | +-- lib.rs | | | | | +-- Cargo.toml | | | | | +-- Xargo.toml | +-- .gitignore | +-- package.json | +-- tsconfig.json
1. 鏈上程序源碼解讀
program-rust/src/lib.rs 是鏈上程序的核心代碼,如代碼清單 1-1 所示,實現(xiàn)了將程序被調(diào)用次數(shù)存儲在鏈上賬戶中。
第 1 行代碼將 borsh::BorshDeserialize 和 borsh::BorshSerialize 引入本地作用域,用于序列化和反序列化數(shù)據(jù)。第 2~9 行代碼將 Solana Rust SDK 的模塊引入本地作用域,使用 Rust 編寫程序都需要這個 SDK。
第 13~16 行代碼定義了 GreetingAccount 結(jié)構(gòu)體作為存儲在賬戶中的狀態(tài)類型,里面有一個 u32 類型的字段 counter,用于記錄程序被有效調(diào)用的次數(shù)。
第 19 行代碼 entrypoint 聲明了 process_instruction 函數(shù)是程序入口,每個程序都有一個唯一的入口。第 22~26 行代碼是 process_instruction 函數(shù)簽名,它要接收 3 個參數(shù):
- program_id:鏈上程序的部署地址,在這里也就是 helloworld 程序賬戶的公鑰。
- accounts:與程序交互的賬戶列表,當前程序會使用賬戶列表中的賬戶來存儲狀態(tài)或修改賬戶中的數(shù)據(jù)。如果當前程序不是某個賬戶的所有者,那就無法使用該賬戶存儲狀態(tài)或修改數(shù)據(jù),當前交易會執(zhí)行失敗。
- instruction_data:指令數(shù)據(jù),比如要轉(zhuǎn)賬的代幣數(shù)量、轉(zhuǎn)賬地址等。
process_instruction 函數(shù)的返回值類型是 ProgramResult,ProgramResult 類型的定義如下所示。
pub type ProgramResult = Result<(), ProgramError>;
當程序的邏輯執(zhí)行成功時返回 Ok(()),否則將 ProgramError 錯誤返回。ProgramError 是自定義錯誤的枚舉類型,其中包含程序可能失敗的各種原因。
第 27 行代碼使用 msg! 宏將字符串輸出到日志中,方便觀察業(yè)務的執(zhí)行邏輯和調(diào)試信息。第 30 行代碼通過 iter 方法將賬戶列表轉(zhuǎn)換為迭代器,以安全的方式獲取賬戶地址。第 33 行代碼使用了 ? 操作符,如果迭代器中有賬戶地址,會將賬戶地址與變量 account 綁定。如果迭代器中沒有賬戶地址,? 操作符會讓程序執(zhí)行失敗。
第 36~39 行代碼判斷存儲狀態(tài)的賬戶所有者是否是當前程序。只有賬戶所有者才能修改數(shù)據(jù),否則輸出日志并返回。
第 42~44 行代碼先對賬戶中的數(shù)據(jù)進行反序列化操作,再將 counter 加一,最后將其序列化后存儲到賬戶中。
代碼清單 1-1 helloworld 鏈上程序
use borsh::{BorshDeserialize, BorshSerialize}; use solana_program::{ account_info::{next_account_info, AccountInfo}, entrypoint, entrypoint::ProgramResult, msg, program_error::ProgramError, pubkey::Pubkey, }; /// Define the type of state stored in accounts #[derive(BorshSerialize, BorshDeserialize, Debug)] pub struct GreetingAccount { /// number of greetings pub counter: u32, } // Declare and export the program's entrypoint entrypoint!(process_instruction); // Program entrypoint's implementation pub fn process_instruction( program_id: &Pubkey, // Public key of the account the hello world program was loaded into accounts: &[AccountInfo], // The account to say hello to _instruction_data: &[u8], // Ignored, all helloworld instructions are hellos ) -> ProgramResult { msg!("Hello World Rust program entrypoint"); // Iterating accounts is safer then indexing let accounts_iter = &mut accounts.iter(); // Get the account to say hello to let account = next_account_info(accounts_iter)?; // The account must be owned by the program in order to modify its data if account.owner != program_id { msg!("Greeted account does not have the correct program id"); return Err(ProgramError::IncorrectProgramId); } // Increment and store the number of times the account has been greeted let mut greeting_account = GreetingAccount::try_from_slice(&account.data.borrow())?; greeting_account.counter += 1; greeting_account.serialize(&mut &mut account.data.borrow_mut()[..])?; msg!("Greeted {} time(s)!", greeting_account.counter); Ok(()) }
2. 客戶端程序源碼解讀
要想測試鏈上程序,我們必須通過 Solana JSON RPC API 去和鏈上程序進行交互。example-helloworld 項目提供的客戶端用 Typescript 編寫,使用了 web3.js 庫這個 Solana JavaScript SDK。
在 client 目錄下,客戶端執(zhí)行的入口是 main.ts 文件,它按特定的順序執(zhí)行任務,每個任務的業(yè)務邏輯代碼在 hello_world.ts 文件。
首先,客戶端調(diào)用 establishConnection 函數(shù)與集群建立連接。
export async function establishConnection(): Promise<void> { const rpcUrl = await getRpcUrl(); connection = new Connection(rpcUrl, 'confirmed'); const version = await connection.getVersion(); console.log('Connection to cluster established:', rpcUrl, version); }
接著,客戶端調(diào)用 establishPayer 函數(shù)來確保有一個有支付能力的賬戶。
export async function establishPayer(): Promise<void> { let fees = 0; if (!payer) { const {feeCalculator} = await connection.getRecentBlockhash(); // Calculate the cost to fund the greeter account fees += await connection.getMinimumBalanceForRentExemption(GREETING_SIZE); // Calculate the cost of sending transactions fees += feeCalculator.lamportsPerSignature * 100; // wag try { // Get payer from cli config payer = await getPayer(); } catch (err) { // Fund a new payer via airdrop payer = await newAccountWithLamports(connection, fees); } } const lamports = await connection.getBalance(payer.publicKey); if (lamports < fees) { // This should only happen when using cli config keypair const sig = await connection.requestAirdrop( payer.publicKey, fees - lamports, ); await connection.confirmTransaction(sig); } console.log( 'Using account', payer.publicKey.toBase58(), 'containing', lamports / LAMPORTS_PER_SOL, 'SOL to pay for fees', ); }
然后,客戶端調(diào)用 checkProgram 函數(shù)從 src/program-rust/target/deploy/helloworld-keypair.json 中加載已部署程序的密鑰對(此操作前需先構(gòu)建鏈上程序,詳見 1.3.2 節(jié)),并使用密鑰對的公鑰來獲取程序賬戶。如果程序不存在,客戶端會報錯并停止執(zhí)行。如果程序存在,將創(chuàng)建一個新賬戶來存儲狀態(tài),并以該程序作為新賬戶所有者。這里新賬戶存儲的狀態(tài),就是程序被調(diào)用的次數(shù)。
export async function checkProgram(): Promise<void> { // Read program id from keypair file try { const programKeypair = await createKeypairFromFile(PROGRAM_KEYPAIR_PATH); programId = programKeypair.publicKey; } catch (err) { const errMsg = (err as Error).message; throw new Error( `Failed to read program keypair at '${PROGRAM_KEYPAIR_PATH}' due to error: ${errMsg}.`, ); } // Check if the program has been deployed const programInfo = await connection.getAccountInfo(programId); if (programInfo === null) { if (fs.existsSync(PROGRAM_SO_PATH)) { throw new Error( 'Program needs to be deployed with `solana program deploy dist/program/helloworld.so`', ); } else { throw new Error('Program needs to be built and deployed'); } } else if (!programInfo.executable) { throw new Error(`Program is not executable`); } console.log(`Using program ${programId.toBase58()}`); // Derive the address (public key) of a greeting account from the program so that it's easy to find later. const GREETING_SEED = 'hello'; greetedPubkey = await PublicKey.createWithSeed( payer.publicKey, GREETING_SEED, programId, ); // Check if the greeting account has already been created const greetedAccount = await connection.getAccountInfo(greetedPubkey); if (greetedAccount === null) { console.log( 'Creating account', greetedPubkey.toBase58(), 'to say hello to', ); const lamports = await connection.getMinimumBalanceForRentExemption( GREETING_SIZE, ); const transaction = new Transaction().add( SystemProgram.createAccountWithSeed({ fromPubkey: payer.publicKey, basePubkey: payer.publicKey, seed: GREETING_SEED, newAccountPubkey: greetedPubkey, lamports, space: GREETING_SIZE, programId, }), ); await sendAndConfirmTransaction(connection, transaction, [payer]); } }
客戶端再調(diào)用 sayHello 函數(shù)向鏈上程序發(fā)送交易。一個交易可以包含一個或多個不同的指令,當前該交易包含了一個指令,指令中帶有要調(diào)用鏈上程序的 Program Id 以及客戶端要交互的賬戶地址。需要注意的是,如果交易中包含多個不同的指令,其中有一個指令執(zhí)行失敗,那么所有指令所做的操作都會被還原。
export async function sayHello(): Promise<void> { console.log('Saying hello to', greetedPubkey.toBase58()); const instruction = new TransactionInstruction({ keys: [{pubkey: greetedPubkey, isSigner: false, isWritable: true}], programId, data: Buffer.alloc(0), // All instructions are hellos }); await sendAndConfirmTransaction( connection, new Transaction().add(instruction), [payer], ); }
最后,客戶端調(diào)用 reportGreetings 函數(shù)訪問賬戶數(shù)據(jù),查詢鏈上程序被有效調(diào)用的次數(shù)。
export async function reportGreetings(): Promise<void> { const accountInfo = await connection.getAccountInfo(greetedPubkey); if (accountInfo === null) { throw 'Error: cannot find the greeted account'; } const greeting = borsh.deserialize( GreetingSchema, GreetingAccount, accountInfo.data, ); console.log( greetedPubkey.toBase58(), 'has been greeted', greeting.counter, 'time(s)', ); }
1.3.2 Hello World 構(gòu)建與部署
1. 創(chuàng)建項目
使用 git clone 命令下載 example-helloworld 項目。
git clone https://github.com/solana-labs/example-helloworld.git cd example-helloworld
2. 構(gòu)建鏈上程序
運行以下命令,在 program-rust 目錄下構(gòu)建鏈上程序。
cd src/program-rust/ cargo build-bpf
構(gòu)建完成后,src/program-rust/target/deploy 目錄下的 helloworld.so 就是可在 Solana 集群部署的鏈上程序的 BPF 字節(jié)碼文件。
3. 啟動本地集群
當前項目在本地集群部署運行,因此首先選擇 localhost 集群,運行以下命令。
solana config set --url localhost
本地集群設置成功,會出現(xiàn)以下內(nèi)容。
Config File: ~/.config/solana/cli/config.yml RPC URL: http://localhost:8899 WebSocket URL: ws://localhost:8900/ (computed) Keypair Path: ~/.config/solana/id.json Commitment: confirmed
再運行以下命令,啟動 localhost 集群。
solana-test-validator
看到以下內(nèi)容,代表本地集群已成功啟動。
Ledger location: test-ledger Log: test-ledger/validator.log Identity: A4HuRgmABNCe94epY2mU7q6WqEHCo2B9iBFE5Yphiw5u Genesis Hash: 96TF9n1uuyFv4rAKECffA61jLrgYjMjNRZ3hJpP6HSr7 Version: 1.7.18 Shred Version: 13390 Gossip Address: 127.0.0.1:1024 TPU Address: 127.0.0.1:1027 JSON RPC URL: http://127.0.0.1:8899 ? 00:00:42 | Processed Slot: 45430 | Confirmed Slot: 45430 | Finalized Slot: 45398 | Snapshot Slot: 45300 | Transactions: 45452 | ◎499.772930000
4. 部署鏈上程序
運行以下命令,在 localhost 集群部署鏈上程序。
solana program deploy target/deploy/helloworld.so // Program Id: 6AArMEBpFhhtU2mBnEMEPeEH7xkhfUwPseUeG4fhLYto
鏈上程序部署成功會返回 Program Id,它類似于以太坊智能合約的地址。
5. 調(diào)用鏈上程序
helloworld 已成功部署,可以與它進行交互了!example-helloworld 項目提供了一個簡單的客戶端,在運行客戶端之前先安裝依賴軟件包。
npm install
由于我們調(diào)整了鏈上程序的構(gòu)建方式,沒有使用該項目默認的 npm run build:program-rust 命令,因此需要修改 client 目錄下的 hello_world.ts 文件,將第 48 行代碼定義的變量 PROGRAM_PATH 的路徑由“../../dist/program”改為“../program-rust/target/deploy”。 再運行以下命令,啟動客戶端去調(diào)用鏈上程序。
npm run start
客戶端成功調(diào)用鏈上程序,輸出內(nèi)容如下所示。如果再次運行客戶端,第 10 行所顯示的次數(shù)會加一。至此,我們已經(jīng)成功在 Solana 集群部署鏈上程序并與之交互了。
> helloworld@0.0.1 start > ts-node src/client/main.ts Let's say hello to a Solana account... Connection to cluster established: http://localhost:8899 { 'feature-set': 3179062686, 'solana-core': '1.6.23' } Using account 4xRm2FYmRB8WdxJk6nXicVMgsPnsxChEnpQwFDGwdcSS containing 499999999.93435186 SOL to pay for fees Using program 6AArMEBpFhhtU2mBnEMEPeEH7xkhfUwPseUeG4fhLYto Creating account Eq7bcsg5p6AaYiPnfiia99ESsuq4B4jYpVbWZhQ94Zvy to say hello to Saying hello to Eq7bcsg5p6AaYiPnfiia99ESsuq4B4jYpVbWZhQ94Zvy Eq7bcsg5p6AaYiPnfiia99ESsuq4B4jYpVbWZhQ94Zvy has been greeted 1 time(s) Success
如果沒有輸出期望值,請首先確認是否已正確啟動了本地集群,構(gòu)建并部署好了鏈上程序。此外,可以運行以下命令查看程序日志,日志包括程序日志消息以及程序失敗信息。
solana logs
包含程序失敗信息的日志如下所示,檢查日志找出程序失敗的原因。
<img src="https://learnblockchain.cn/css/default/copy.svg" /><code>Transaction executed in slot 5621: Signature: 4pya5iyvNfAZj9sVWHzByrxdKB84uA5sCxLceBwr9UyuETX2QwnKg56MgBKWSM4breVRzHmpb1EZQXFPPmJnEtsJ Status: Error processing Instruction 0: Program failed to complete Log Messages: Program G5bbS1ipWzqQhekkiCLn6u7Y1jJdnGK85ceSYLx2kKbA invoke [1] Program log: Hello World Rust program entrypoint Program G5bbS1ipWzqQhekkiCLn6u7Y1jJdnGK85ceSYLx2kKbA consumed 200000 of 200000 compute units Program failed to complete: exceeded maximum number of instructions allowed (200000) at instruction #334 Program G5bbS1ipWzqQhekkiCLn6u7Y1jJdnGK85ceSYLx2kKbA failed: Program failed to complete
1.4 本章小節(jié)
本章對 Solana 區(qū)塊鏈的基本概念進行了簡要介紹,Solana 的智能合約叫做鏈上程序。在開始 Solana 鏈上程序開發(fā)之前,需要先安裝和配置相關(guān)的編程環(huán)境,我們著重介紹了 Solana CLI 的安裝和配置。
Hello World 是一個官方演示項目,通過對這個項目源碼的解讀,我們了解了如何使用 Rust 開發(fā)鏈上程序,并使用 Solana CLI 來構(gòu)建與部署,以及使用 Solana JavaScript SDK 與鏈上程序進行交互。
你可能感興趣的文章
-
SOL價格上漲和網(wǎng)絡擁堵 Solana需要Layer2和Rollup么?
DRiP的創(chuàng)始人Vibhu在一則聲明中引發(fā)了一場迫切需要的辯論:Solana需要有L2和Rollup,本文將從Solana和擁堵、使Solana模塊化、Solana 應用鏈、Solana 第二層、推動Rollup和Ap…
2024-04-28 -
SOL是公鏈嗎?Solana(SOL)公鏈全面介紹
Solana是一個于2017年成立的可程式設計的區(qū)塊鏈,Solana 簡稱SOL鏈,而SOL幣則是該公鏈的原生加密貨幣,在SOL鏈上的一切交互都需要使用SOL幣支付手續(xù)費,那么,SOL是公鏈嗎?…
2024-04-17 -
Jupiter是投資Solana的放大器嗎?
Jupiter 是 Solana 生態(tài)核心流動性聚合器,提供最廣泛的代幣索引,以及任意交易對的最優(yōu)路徑,那么,Jupiter是投資Solana的放大器嗎?下文將為大家詳細分析…
2024-04-16 -
2024年Solana生態(tài)值得關(guān)注的10大DeFi主題
Solana 擁有最強大的聚合器之一,其中 Jupiter 處于領(lǐng)先地位,本文將為大家詳細介紹2024年Solana生態(tài)值得關(guān)注的10大DeFi主題…
2024-03-28 -
以太坊殺手Solana為什么會暴漲24倍?以太坊殺手幣行情解析
以太坊和覬覦它的「殺手」們都怎么樣了?以太坊殺手Solana近期漲勢喜人,一年多時間直接從9美元漲到208刀,是什么原因支撐以太坊的漲勢的?和以太坊殺手Solana們都有這樣的…
2024-03-27 -
Ton會不會成為Solana挑戰(zhàn)者?TON幣未來行情分析
Ton還有投資價值嗎?未來的Ton幣怎么樣?最近,TON 公鏈在經(jīng)歷長時間低迷后終于開始起步,總鎖倉量突破 7800 萬,創(chuàng)歷史新高,Ton 能否復刻 Solana Meme 狂潮?大家一起看看…
2024-03-26 -
2024年最受歡迎的區(qū)塊鏈為什么是Solana(SOL幣)?詳細解讀Solana(SOL幣)
Solana(SOL幣)為什么是2024年最受歡迎的區(qū)塊鏈?Solana生態(tài)系統(tǒng)已成為今年迄今為止最受歡迎的區(qū)塊鏈生態(tài)系統(tǒng),占全球加密貨幣投資者對特定鏈敘事興趣的49.3%,從1月1日101.4…
2024-03-25 -
一文讀懂什么是Solscan以及如何使用?
Solscan是一款Solana區(qū)塊鏈探索器,它為用戶提供了一個基于網(wǎng)絡的平臺,可用于探索和分析Solana區(qū)塊鏈上的交易、錢包地址、合約、NFT 和 DeFi 項目,本文將為大家詳細介紹什…
2024-03-25 -
Solana的黃金時代:新故事,新起點
SOL再破200美元大關(guān),較歷史高點僅剩30%的漲幅,本文將為大家深度解讀Solana的黃金時代:新故事,新起點…
2024-03-20 -
Bitget研究院:以太坊完成坎昆升級帶動Solana生態(tài)普漲
過去24小時,市場出現(xiàn)了不少新的熱門幣種和話題,或許它們就是下一個造富機會,本文將根據(jù)現(xiàn)在的市場環(huán)境,分析下面要異動的板塊代幣及用戶熱搜代幣介紹…
2024-03-15