BARU: Helius mengakuisisi Light Protocol
Cara Mulai Membangun dengan Solana Web3.js 2.0 SDK
Blog/Pengembangan

Cara Mulai Membangun dengan Solana Web3.js 2.0 SDK

Engineer Pengalaman DeveloperAnam Ansari di XAnam Ansari di LinkedIn
Edukasi DeveloperMike MacCana di XMike MacCana di LinkedIn
Bacaan 10 menit

Sebelum memulai, kami ingin berterima kasih kepada Evan dan Nick karena telah meninjau artikel ini. Kami sangat menghargai masukan dan wawasan berharga mereka.

Pendahuluan

Solana Web3.js SDK adalah library TypeScript dan JavaScript yang andal untuk membangun aplikasi Solana di platform Node.js, web, dan React Native. Pada 7 November 2024, Anza memperkenalkan pembaruan 2.0 SDK yang sangat dinantikan, dengan menghadirkan berbagai fitur dan peningkatan JavaScript modern. Sorotan utamanya mencakup tipe JS standar untuk bigint dan kriptografi serta ukuran bundel yang lebih kecil, menjadikannya peningkatan penting bagi developer. 

Jika Anda telah menggunakan @solana/web3.js, Anda perlu mem-porting perangkat lunak Anda ke paket v2.0 yang baru atau menentukan versinya secara eksplisit agar tetap menggunakan v1.x. 

Dalam artikel ini, kita akan membahas pembaruan terbaru di Web3.js 2.0 SDK, memandu Anda melalui proses migrasi, dan memberikan contoh untuk membantu Anda memulai. 

Artikel ini mengasumsikan bahwa Anda memahami konsep dasar Solana dengan baik, seperti mengirim transaksi, model akun Solana, blockhash, dan biaya prioritas, serta memiliki pengalaman menggunakan TypeScript atau JavaScript. Meskipun disarankan untuk memahami versi Web3.js SDK sebelumnya, hal ini tidak wajib. Mari kita mulai!

Apa yang baru di Web3.js 2.0?

Mari kita lihat sekilas apa saja yang ditawarkan Web3.js 2.0 SDK baru: 

1. Peningkatan Performa

Operasi kriptografi yang lebih cepat: pembuatan keypair, penandatanganan transaksi, dan verifikasi pesan menjadi hingga 10 kali lebih cepat dengan memanfaatkan API kriptografi native di lingkungan JavaScript modern seperti Node.js dan browser terkini.

2. Aplikasi yang Lebih Kecil dan Efisien

Web3.js 2.0 sepenuhnya mendukung tree-shaking, sehingga Anda hanya perlu menyertakan bagian library yang digunakan untuk meminimalkan ukuran bundel. Selain itu, SDK baru ini tidak memiliki dependensi eksternal sehingga menghasilkan build yang ringan dan aman.

3. Fleksibilitas yang Lebih Baik

Developer kini dapat membuat solusi khusus dengan:

  • Mendefinisikan instans RPC dengan metode khusus  
  • Menggunakan transportasi jaringan atau penanda tangan transaksi khusus  
  • Menyusun primitive khusus untuk jaringan, konfirmasi transaksi, dan codec  

‍Client TypeScript baru untuk program on-chain kini tersedia di organisasi GitHub @solana-program. Client ini dibuat secara otomatis menggunakan Codama, sehingga developer dapat membuat client untuk program khusus dengan cepat. 

Apakah Anda Sudah Perlu Beralih ke Web3.js v2?

Per Februari 2025:

  • Jika Anda membuat aplikasi Solana baru dengan JS/TS dan menggunakan program yang sudah ada seperti system program, token program, associated token program, dan program umum lainnya, Anda sudah dapat menggunakan web3.js v2.
  • Jika Anda membuat aplikasi on-chain khusus menggunakan Anchor, sebaiknya tunggu terlebih dahulu—Anchor belum mendukung web3.js v2 secara langsung. Anda mungkin perlu menunggu pembaruan Anchor mendatang. Sebagai alternatif, gunakan Codama untuk membuat client TypeScript bagi aplikasi on-chain Anda, meskipun cara ini memerlukan sedikit lebih banyak pekerjaan.

Bermigrasi dari web3.js versi 1

‍Jika Anda pernah menggunakan web3.js v1, berikut ringkasan singkat tentang perbedaan pentingnya:

Keypair

Di setiap tempat Anda sebelumnya menggunakan Keypair, kini gunakan KeyPairSigner. Keypair.generate() kini menjadi generateKeyPairSigner(). Selain itu, keypair kini selalu ditulis sebagai keyPair, mengikuti camelCase JS/TS standar.

Secret key kini disebut privateKey dan dapat diakses melalui keyPairSigner.privateKey. Secara umum, di web3.js v2 Anda menggunakan KeyPairSigner di setiap tempat secretKey digunakan dalam web3.js v1.

Alamat / Public key

Bagian yang menggunakan PublicKey dalam web3.js v1 kini cukup menggunakan address dalam web3.js v2. Sebagai contoh,  KeyPairSigner memiliki properti keypairSigner.address, yang merupakan public key-nya. Anda dapat mengubah string Public Key menjadi address menggunakan fungsi address.

Jumlah SOL dan Token

Jumlah menggunakan tipe native JS BigInt. Jadi, tambahkan n di akhir angka, sehingga menjadi  1n, bukan 1. 

Factory

Banyak fitur dapat dikonfigurasi. Jadi, alih-alih menggunakan implementasi yang telah ditetapkan (misalnya, doThing()), tersedia factory (bernama doThingFactory()) yang dapat digunakan untuk membuat fungsi doThing() Anda sendiri. Contohnya:

  • Untuk mengirim dan mengonfirmasi transaksi, jalankan sendAndConfirmTransactionFactory() satu kali dengan opsi pilihan Anda, lalu Anda akan mendapatkan fungsi sendAndConfirmTransaction() khusus. Setelah itu, gunakan sendAndConfirmTransaction() kapan pun Anda perlu mengirim dan mengonfirmasi transaksi. 
  • Untuk mendapatkan airdrop di devnet atau localnet, jalankan airdropFactory() satu kali, lalu Anda akan mendapatkan fungsi airdrop() khusus yang dapat digunakan kapan pun Anda menginginkan airdrop.

Cara Mengirim Transaksi dengan Web3.js 2.0

Kita akan membangun program sisi client menggunakan Web3.js 2.0 untuk mentransfer lamport ke wallet lain. Program ini akan menunjukkan teknik untuk meningkatkan tingkat keberhasilan transaksi dan mempercepat waktu konfirmasi. 

Kita akan mengikuti praktik terbaik berikut untuk mengirim transaksi: 

  1. Mengambil blockhash terbaru dengan tingkat commitment confirmed  
  2. Menetapkan biaya prioritas sesuai rekomendasi Priority Fee API Helius
  3. Mengoptimalkan unit komputasi  
  4. Mengirim transaksi dengan maxRetries ditetapkan ke 0 dan skipPreflight ditetapkan ke true  

Pendekatan ini memastikan performa dan keandalan yang optimal, bahkan saat terjadi kemacetan jaringan. 

Prasyarat

  • Instal Node.js  
  • IDE yang kompatibel (misalnya, VS Code atau Cursor)  

Instalasi

Mulailah dengan membuat proyek Node.js dasar untuk menyusun struktur aplikasi Anda.

Jalankan perintah berikut untuk membuat file package.json yang mengelola dependensi dan metadata proyek Anda:

Shell commands
npm init -y

Buat direktori src, lalu tambahkan file index.ts di dalamnya sebagai tempat kode utama:

Shell commands
mkdir src  
touch src/index.ts

Selanjutnya, gunakan npm untuk menginstal dependensi yang diperlukan saat bekerja dengan Solana Web3.js 2.0 SDK:

Shell commands
npm install @solana/web3.js@2 @solana-program/system @solana-program/compute-budget esrun

Berikut deskripsi setiap paket:

  • @solana/web3.js: Solana Web3.js 2.0 SDK yang penting untuk membangun dan mengelola transaksi Solana
  • @solana-program/system: menyediakan akses ke Solana System Program sehingga memungkinkan operasi seperti transfer lamport
  • @solana-program/compute-budget: digunakan untuk menetapkan biaya prioritas dan mengoptimalkan unit komputasi transaksi
  • esrun adalah cara sederhana untuk menjalankan aplikasi TypeScript dari command line tanpa memerlukan konfigurasi atau fungsi wrapper.

Tentukan Alamat Transfer

Di index.ts, mari tentukan alamat sumber dan tujuan untuk mentransfer lamport. Kita akan menggunakan fungsi address() untuk menghasilkan public key tujuan dari string yang diberikan.

Untuk sumber, kita akan mendapatkan KeyPair menggunakan secretKey miliknya.

send-transaction.ts
import { address, createKeyPairSignerFromBytes, getBase58Encoder } from "@solana/web3.js";

const destinationAddress = address("public-key-to-send-lamports-to");
const secretKey = "add-your-private-key";
const sourceKeypair = await createKeyPairSignerFromBytes(getBase58Encoder().encode(secretKey));

Konfigurasikan Koneksi RPC

Selanjutnya, kita dapat menyiapkan koneksi RPC yang diperlukan. Fungsi createSolanaRpc menjalin komunikasi dengan server RPC menggunakan transportasi HTTP default, yang memadai untuk sebagian besar kasus penggunaan.

Demikian pula, kita menggunakan createSolanaRpcSubscriptions untuk membuat koneksi WebSocket. rpc_url dan wss_url tersedia di Dasbor Helius—cukup daftar atau masuk, lalu buka bagian “Endpoints”.

Fungsi sendAndConfirmTransactionFactory membuat pengirim transaksi yang dapat digunakan kembali. Pengirim ini memerlukan koneksi RPC untuk mengirim transaksi dan langganan RPC untuk memantau status transaksi.

send-transaction.ts
import {
  // ...
  createSolanaRpcSubscriptions,
  createSolanaRpc,
  sendAndConfirmTransactionFactory,
} from "@solana/web3.js";

const rpc_url = "https://mainnet.helius-rpc.com/?api-key=<your-key>";
const wss_url = "wss://mainnet.helius-rpc.com/?api-key=<your-key>";

const rpc = createSolanaRpc(rpc_url);
const rpcSubscriptions = createSolanaRpcSubscriptions(wss_url);

const sendAndConfirmTransaction = sendAndConfirmTransactionFactory({
  rpc,
  rpcSubscriptions,
});

Buat Instruksi Transfer

Menyertakan blockhash terbaru akan mencegah duplikasi dan memberikan masa berlaku pada transaksi—setiap transaksi harus menyertakan blockhash yang valid agar dapat diterima untuk dieksekusi. Untuk transaksi ini, kita akan mengambil blockhash terbaru menggunakan tingkat commitment confirmed.

Selanjutnya, kita akan menggunakan getTransferSolInstruction() untuk membuat instruksi transfer bawaan yang disediakan oleh System Program. Ini memerlukan penentuan jumlah dan sumber

, serta tujuan. Sumber harus selalu berupa Signer, sedangkan tujuan harus berupa alamat publik.

send-transaction.ts
import {
  // ...
  lamports,
} from "@solana/web3.js";
import { getTransferSolInstruction } from "@solana-program/system";

/**
 * STEP 1: CREATE THE TRANSFER TRANSACTION
 */
const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();

const instruction = getTransferSolInstruction({
  amount: lamports(1n),
  destination: destinationAddress,
  source: sourceKeypair,
});

Buat Pesan Transaksi

Kemudian, kita akan membuat pesan transaksi. Semua pesan transaksi kini mengenali versi sehingga Anda tidak perlu menangani tipe yang berbeda (misalnya, Transaction dan VersionedTransaction). 

Kita akan menetapkan sumber sebagai pembayar biaya, menyertakan blockhash, dan menambahkan instruksi untuk mentransfer lamport.

send-transaction.ts
import {
  // ...
  pipe,
  createTransactionMessage,
  setTransactionMessageFeePayer,
  setTransactionMessageLifetimeUsingBlockhash,
  appendTransactionMessageInstruction,
} from "@solana/web3.js";

// ...

const transactionMessage = pipe(
  createTransactionMessage({ version: 0 }),
  (message) => setTransactionMessageFeePayer(sourceKeypair.address, message),
  (message) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, message),
  (message) => appendTransactionMessageInstruction(instruction, message),
);

console.log("Transaction message created");

Fungsi pipe, yang umum digunakan dalam pemrograman fungsional, membuat urutan fungsi dengan output satu fungsi menjadi input bagi fungsi berikutnya. Di sini, fungsi tersebut membangun pesan transaksi langkah demi langkah dengan menerapkan transformasi seperti menetapkan pembayar biaya dan masa berlaku serta menambahkan instruksi.

Inisialisasi Pesan Transaksi:

createTransactionMessage({ version: 0 }) dimulai dengan pesan transaksi dasar.

Tetapkan Pembayar Biaya:

message => setTransactionMessageFeePayer(fromKeypair.address, message) menambahkan alamat pembayar biaya.

Tetapkan Masa Berlaku Menggunakan Blockhash

message => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, message) memastikan transaksi tetap valid dalam jangka waktu tertentu menggunakan blockhash terbaru.

Tambahkan Instruksi Transfer

message => appendTransactionMessageInstruction(instruction, message) menambahkan tindakan (misalnya, mentransfer lamport) ke pesan.

Setiap arrow function message => (...) memodifikasi dan meneruskan pesan yang telah diperbarui ke langkah berikutnya, sehingga menghasilkan pesan transaksi baru yang telah tersusun sepenuhnya.

Tandatangani Transaksi

Kita akan menandatangani transaksi menggunakan penanda tangan yang ditentukan, yaitu Keypair sumber.

send-transaction.ts
import {
  // ...
  signTransactionMessageWithSigners,
} from "@solana/web3.js";
// ...

/**
 * STEP 2: SIGN THE TRANSACTION
 */
const signedTransaction = await signTransactionMessageWithSigners(transactionMessage);
console.log("Transaction signed");

Perkirakan Biaya Prioritas

Pada tahap ini, kita dapat melanjutkan dengan mengirim dan mengonfirmasi transaksi. Namun, kita sebaiknya mengoptimalkan transaksi dengan menetapkan biaya prioritas dan menyesuaikan unit komputasi. Pengoptimalan ini membantu meningkatkan tingkat keberhasilan transaksi dan mengurangi waktu konfirmasi, terutama saat jaringan macet.

Untuk menetapkan biaya prioritas, kita akan menggunakan Priority Fee API Helius. API ini memerlukan transaksi yang diserialisasi dalam format Base64. Meskipun API juga mendukung encoding Base58, SDK saat ini menyediakan transaksi secara langsung dalam format Base64 sehingga prosesnya menjadi lebih sederhana.

send-transaction.ts
import {
  // ...
  getBase64EncodedWireTransaction,
} from "@solana/web3.js";

/**
 * STEP 3: GET PRIORITY FEE FROM SIGNED TRANSACTION
 */

const base64EncodedWireTransaction = getBase64EncodedWireTransaction(signedTransaction);

const response = await fetch(rpc_url, {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    jsonrpc: "2.0",
    id: "helius-example",
    method: "getPriorityFeeEstimate",
    params: [
      {
        transaction: base64EncodedWireTransaction,
        options: {
          transactionEncoding: "base64",
          priorityLevel: "High",
        },
      },
    ],
  }),
});
const { result } = await response.json();
const priorityFee = result.priorityFeeEstimate;
console.log("Setting priority fee to ", priorityFee);

Menetapkan priorityLevel ke High biasanya sudah cukup. Namun, penerapan strategi biaya prioritas lanjutan seperti menggunakan transaksi yang diserialisasi dan key akun dapat meningkatkan tingkat keberhasilan transaksi secara signifikan saat jaringan macet.

Optimalkan Unit Komputasi

Selanjutnya, kita akan memperkirakan unit komputasi aktual yang digunakan oleh pesan transaksi.

Kemudian, kita menambahkan buffer 10% dengan mengalikan nilai ini dengan 1,1. Buffer ini memperhitungkan unit komputasi yang digunakan oleh biaya prioritas dan instruksi unit komputasi tambahan yang akan kita sertakan nanti. 

Beberapa instruksi, seperti mentransfer lamport, mungkin memiliki perkiraan unit komputasi yang lebih rendah. Untuk memastikan sumber daya yang memadai, kita telah menambahkan pengaman yang menetapkan unit komputasi ke nilai minimum 1000 jika hasil perkiraan berada di bawah ambang ini.

send-transaction.ts
import {
  // ...
  getComputeUnitEstimateForTransactionMessageFactory,
} from "@solana/web3.js";

/**
 * STEP 4: OPTIMIZE COMPUTE UNITS
 */
const getComputeUnitEstimateForTransactionMessage = getComputeUnitEstimateForTransactionMessageFactory({
  rpc,
});
// Request an estimate of the actual compute units this message will consume.
let computeUnitsEstimate = await getComputeUnitEstimateForTransactionMessage(transactionMessage);
computeUnitsEstimate = computeUnitsEstimate < 1000 ? 1000 : Math.ceil(computeUnitsEstimate * 1.1);
console.log("Setting compute units to ", computeUnitsEstimate);

Bangun Ulang dan Tandatangani Transaksi

Sekarang kita memiliki biaya prioritas dan unit komputasi yang diperlukan untuk transaksi ini. Karena transaksi sudah ditandatangani, kita tidak dapat langsung menambahkan instruksi baru. Sebagai gantinya, kita akan membangun ulang seluruh pesan transaksi dengan blockhash baru. 

Blockhash hanya berlaku sekitar 1–2 menit, sedangkan pengambilan biaya prioritas dan unit komputasi memerlukan waktu. Untuk menghindari risiko blockhash kedaluwarsa saat mengirim transaksi, lebih aman mengambil blockhash baru ketika membangun ulang transaksi.

Dalam transaksi yang dibangun ulang ini, kita akan menyertakan dua instruksi tambahan: 

  1. Satu instruksi untuk menetapkan biaya prioritas; dan
  2. Satu instruksi lainnya untuk menetapkan unit komputasi 

Terakhir, kita akan menandatangani transaksi yang telah diperbarui ini agar siap dikirim:

send-transaction.ts
import {
  // ...
  appendTransactionMessageInstructions,
} from "@solana/web3.js";
import { getSetComputeUnitLimitInstruction, getSetComputeUnitPriceInstruction } from "@solana-program/compute-budget";

/**
 * STEP 5: REBUILD AND SIGN FINAL TRANSACTION
 */
const { value: finalLatestBlockhash } = await rpc.getLatestBlockhash().send();

const finalTransactionMessage = appendTransactionMessageInstructions(
  [
    getSetComputeUnitPriceInstruction({ microLamports: priorityFee }),
    getSetComputeUnitLimitInstruction({ units: computeUnitsEstimate }),
  ],
  transactionMessage,
);

setTransactionMessageLifetimeUsingBlockhash(finalLatestBlockhash, finalTransactionMessage);

const finalSignedTransaction = await signTransactionMessageWithSigners(finalTransactionMessage);
console.log("Rebuilt the transaction and signed it");

Kirim dan Konfirmasikan Transaksi

Selanjutnya, transaksi yang telah ditandatangani dikirim dan dikonfirmasi menggunakan fungsi sendAndConfirmTransaction.

Tingkat commitment ditetapkan ke confirmed agar konsisten dengan blockhash yang diambil sebelumnya, sedangkan maxRetries ditetapkan ke 0. Opsi skipPreflight ditetapkan ke true untuk melewati pemeriksaan preflight agar eksekusi lebih cepat. Namun, opsi ini hanya boleh digunakan jika Anda yakin bahwa tanda tangan transaksi telah diverifikasi dan tidak ada error lain.

sendAndConfirmTransaction telah dibuat sebelumnya dengan menyediakan URL RPC dan langganan RPC. Penggunaan URL langganan RPC akan memeriksa status transaksi sehingga Anda tidak perlu melakukan polling secara manual.

Di bagian penanganan error, kode memeriksa error yang terjadi selama pemeriksaan preflight. Karena kita menetapkan skipPreflight ke true, pemeriksaan ini bersifat redundan. Namun, pemeriksaan ini akan berguna jika Anda tidak menetapkannya ke true.

send-transaction.ts
import {
  getSignatureFromTransaction,
  isSolanaError,
  SOLANA_ERROR__JSON_RPC__SERVER_ERROR_SEND_TRANSACTION_PREFLIGHT_FAILURE,
} from "@solana/web3.js";
import { getSystemErrorMessage, isSystemError } from "@solana-program/system";

/**
 * STEP 6: SEND AND CONFIRM THE FINAL TRANSACTION
 */

console.log("Sending and confirming transaction");
await sendAndConfirmTransaction(finalSignedTransaction, {
  commitment: "confirmed",
  maxRetries: 0n,
  skipPreflight: true,
});
console.log("Transfer confirmed: ", getSignatureFromTransaction(finalSignedTransaction));

Jalankan Kode

Terakhir, kita dapat menjalankan kode: npx esrun send-transaction.ts

Kesimpulan

Peluncuran Solana Web3.js 2.0 SDK merupakan pembaruan transformatif yang memungkinkan developer membuat aplikasi yang lebih cepat, efisien, dan skalabel di Solana. Dengan mengadopsi standar JavaScript modern dan memperkenalkan fitur seperti API kriptografi native, dukungan tree-shaking, serta client TypeScript yang dibuat secara otomatis, SDK ini secara signifikan meningkatkan pengalaman developer dan performa aplikasi.

Kode lengkap untuk contoh pemrograman ini tersedia di GitHub.

Jika Anda sudah membaca sejauh ini, terima kasih, anon! Pastikan Anda memasukkan alamat email di bawah agar tidak pernah melewatkan kabar terbaru tentang Solana. Siap mempelajari lebih lanjut? Jelajahi artikel terbaru di blog Helius dan lanjutkan perjalanan Solana Anda hari ini.

Referensi

Berlangganan Helius

Ikuti perkembangan terbaru dalam pengembangan Solana dan dapatkan pembaruan saat kami memublikasikan postingan

Gambar diperbesar