This guide provides a step-by-step overview of deploying a program on the Sonic HyperGrid. Familiarity with command-line tools is necessary.
1. Install CLI Tools
Ensure that the Solana command line tools are installed as you will be using these tools throughout the deployment process.
2. Write Your Program
Develop your program logic. For those using Rust with Anchor, input your program logic into the lib.rs file located in the src directory of your project. Confirm that your program compiles correctly and passes all tests.
3. Build Your Program
Compile your program to a BPF (Berkeley Packet Filter) executable, the format required for on-chain programs:
With Anchor
Run anchor build. Anchor manages the compilation details.
Without Anchor
Use cargo build-bpf for direct Rust usage.
4. Deploy Your Program
Before deploying your program, ensure your CLI is set to the Sonic Devnet network using the following command:
solanaconfigset--urlhttps://devnet.sonic.game
After deploying your building your program and configuring your RPC URL, you can deploy your program with the following command:
solana program deploy <PATH_TO_YOUR_COMPILED_PROGRAM>
Ensure that you have enough SOL in your wallet to cover deployment costs. You can get some devnet tokens by using the Sonic faucet.
After configuring your network, you may now deploy your program to Sonic. Use the following commands based on your setup:
With Anchor
If you have the Anchor CLI installed, you can deploy your program with the following command. This handles the deployment automatically.
anchordeploy
Without Anchor
If you're using the native solana method to author your program, you can also use the Solana CLI to deploy your program.
5. Verify Deployment
Post-deployment, check that your program operates as intended. Interact with your program using Solana's web3.js library or the CLI tools to send transactions.
Additional Tips:
Keep your program's keypair secure for future upgrades or interactions.
Monitor the network and your program's performance, particularly if it gains widespread usage.
Example: "Hello Sonic!" Program
This example implements a simple Greeting Counter Program on Sonic.
With Solana Native Program
use borsh::{BorshDeserialize, BorshSerialize};use solana_program::{ account_info::{next_account_info, AccountInfo}, entrypoint, entrypoint::ProgramResult, msg, program_error::ProgramError, pubkey::Pubkey,};#[derive(BorshSerialize, BorshDeserialize, Debug)]pubstructGreetingAccount {pub counter:u32,}entrypoint!(process_instruction);pubfnprocess_instruction( program_id:&Pubkey, accounts:&[AccountInfo], _instruction_data:&[u8],) ->ProgramResult {msg!("Hello, Sonic World!");let accounts_iter =&mut accounts.iter();let account =next_account_info(accounts_iter)?;if account.owner != program_id {msg!("Greeted account does not have the correct program id");returnErr(ProgramError::IncorrectProgramId); }letmut greeting_account =GreetingAccount::try_from_slice(&account.data.borrow())?; greeting_account.counter +=1; greeting_account.serialize(&mut*account.data.borrow_mut())?;msg!("Greeted {} time(s)!", greeting_account.counter);Ok(())}
With Anchor Program
If you are building with Anchor, you may use the variant below. Before deploying your program, please remember to change the program ID after building your program with anchor build.
use anchor_lang::prelude::*;// !!! Replace with your program ID after running `anchor build` !!!declare_id!("<REPLACE_WITH_YOUR_PROGRAM_ID>");#[program]pubmod hello_sonic_world {use super::*;pubfninitialize(ctx:Context<Initialize>, authority:Pubkey) ->Result<()> {let greeting_account =&mut ctx.accounts.greeting_account; greeting_account.counter =0; greeting_account.authority = authority;Ok(()) }pubfnincrement_greeting(ctx:Context<IncrementGreeting>) ->Result<()> {msg!("Hello, Sonic World!");let greeting_account =&mut ctx.accounts.greeting_account; greeting_account.counter +=1;msg!("Greeted {} time(s)!", greeting_account.counter);Ok(()) }}#[derive(Accounts)]pubstructInitialize<'info> { #[account(init, payer = user, space = 8 + 4 + 32)]pub greeting_account:Account<'info, GreetingAccount>, #[account(mut)]pub user:Signer<'info>,pub system_program:Program<'info, System>,}#[derive(Accounts)]pubstructIncrementGreeting<'info> { #[account(mut, has_one = authority)]pub greeting_account:Account<'info, GreetingAccount>,pub authority:Signer<'info>,}#[account]pubstructGreetingAccount {pub counter:u32,pub authority:Pubkey,}
import {Connection,PublicKey,Keypair,Transaction,SystemProgram, sendAndConfirmTransaction} from '@solana/web3.js';import { Program, AnchorProvider, web3 } from '@project-serum/anchor';import { IDL } from './idl/hello_sonic_world.json'; // Make sure you have the correct IDL fileconst programId = new PublicKey('<REPLACE_WITH_YOUR_PROGRAM_ID>');const connection = new Connection('https://devnet.solana.com', 'confirmed');const feePayer =Keypair.fromSecretKey( bs58.decode('<REPLACE_WITH_YOUR_PRIVATE_KEY>'));// Anchor setupconst wallet = new AnchorProvider(connection, feePayer, { preflightCommitment:'confirmed',});const program = new Program(IDL, programId, wallet);async function sayHello() {// Create the greeting accountconst greetedAccountKeypair =Keypair.generate();const greetedAccountPubkey = greetedAccountKeypair.publicKey;const lamports =await connection.getMinimumBalanceForRentExemption(8+4+32// space for the account (discriminator, counter, and authority) );const createGreetingAccountIx =SystemProgram.createAccount({ fromPubkey: feePayer.publicKey, lamports, newAccountPubkey: greetedAccountPubkey, programId: program.programId, space:8+4+32, // size of the GreetingAccount (8 discriminator + 4 counter + 32 authority) });const transaction = new Transaction().add(createGreetingAccountIx);awaitsendAndConfirmTransaction(connection, transaction, [ feePayer, greetedAccountKeypair, ]); console.log(`Greeting account created with public key:${greetedAccountPubkey.toBase58()}`);// Initialize the greeting accountawait program.rpc.initialize(feePayer.publicKey, { accounts: { greetingAccount: greetedAccountPubkey, user: feePayer.publicKey, systemProgram:SystemProgram.programId, }, signers: [greetedAccountKeypair, feePayer], }); console.log('Greeting account initialized'); // Increment the greeting counter await program.rpc.incrementGreeting({ accounts: { greetingAccount: greetedAccountPubkey, authority: feePayer.publicKey, }, }); console.log('Greeting incremented'); // Fetch the account data const account = await program.account.greetingAccount.fetch( greetedAccountPubkey ); console.log('Greeting successful.Account data:', account);}sayHello() .then(() => console.log('Done')) .catch(console.error);
Running the above script [either with Solana Native, or with Anchor] programs should output the following:
Use 'solana confirm -v TsCwj8s8meQFSfqUKdHqDQVzfUbqRcugP2gJ5kaGCj4v4D7aKvohqQQncvUFunqZVH9sS6jhESMjwe6SHGPfrXf' to see the logs
SonicGreetingsuccesful.Accountdata:GreetingAccount{counter:1}Done
An example the above executed transaction can be found here. The program address for this program is here.