This project provides a Rust-based SDK for integrating Solana blockchain functionality with C programs. The SDK enables developers to perform tasks such as creating wallets, transferring SOL and SPL tokens, interacting with smart contracts, and managing accounts on the Solana blockchain.
- Wallet Management: Create, load, and manage Solana wallets.
- Token Management: Transfer SOL and SPL tokens, mint new SPL tokens, and fetch token balances.
- Smart Contract Integration: Interact with smart contracts and send custom transactions.
- Account Operations: Fetch and manage account data.
- Rust: Ensure you have the latest version of Rust installed. Install Rust
- Solana CLI: Install the Solana CLI for blockchain interaction. Install Solana CLI
- C Compiler: Ensure you have a C compiler installed (e.g.,
gcc
orclang
).
-
Clone the repository:
git clone https://github.com/VAR-META-Tech/solana-c-sdk.git cd solana-c-sdk
-
Build the project:
sh build.sh
sh test.sh
-
Place the IDL file in source folder (ex: anchor_counter.json)
sh generate.sh anchor_counter.json
-
Locate the Generated Interface File:
header/anchor_counter_interface.c
Include the solana_sdk.h
header file in your C project to access the SDK functions.
#include "solana_sdk.h"
#include "solana_sdk.h"
#include <stdio.h>
int main() {
// Create a new wallet
SolKeyPair *wallet = new_keypair();
if (wallet == NULL) {
printf("Failed to create a wallet\n");
return 1;
}
// Get wallet address
char *address = get_wallet_address(wallet);
printf("Wallet Address: %s\n", address);
// Free allocated memory
free(wallet);
free(address);
return 0;
}
#include "solana_sdk.h"
#include <stdio.h>
int main() {
// Initialize Solana client
SolClient *client = new_sol_client("https://api.devnet.solana.com");
if (client == NULL) {
printf("Failed to initialize Solana client\n");
return 1;
}
// Create sender wallet
SolKeyPair *sender = new_keypair();
char *sender_address = get_wallet_address(sender);
printf("Sender Address: %s\n", sender_address);
// Generate recipient public key
SolPublicKey recipient;
// Set recipient public key bytes (replace with actual public key)
memset(recipient.data, 0, sizeof(recipient.data));
// Transfer 1 SOL
uint64_t lamports = 1000000000; // 1 SOL in lamports
bool success = transfer_sol(client, sender, &recipient, lamports);
if (success) {
printf("Transfer successful\n");
} else {
printf("Transfer failed\n");
}
// Free allocated resources
free_client(client);
free(sender);
free(sender_address);
return 0;
}
void test_counter()
{
// Try run test anchor program https://github.com/thanhngoc541/anchor-counter, deploy the project to get program id
// RPC URL and paths
const char *rpc_url = "https://api.devnet.solana.com";
const char *payer_path = file_path;
const char *program_id = "3CkKwWzHTvwnAURu8TD4JijeuYZkaPkU14QRGeGLHbSw";
// Initialize Solana client and wallet
SolClient *client = new_sol_client(rpc_url);
SolKeyPair *payer = load_wallet_from_file(payer_path);
SolKeyPair *account = new_keypair();
// Get system program ID
SolPublicKey SYSTEM_PROGRAM_ID = get_system_program_id();
// Prepare to initialize account
SolPublicKey initialize_accounts[3] = {
account->pubkey,
payer->pubkey,
SYSTEM_PROGRAM_ID};
SolKeyPair *initialize_signers[2] = {payer, account};
// Call initialize
char *initialize_result = anchor_counter_initialize_c(
client,
program_id,
initialize_accounts,
3,
initialize_signers,
2);
if (initialize_result != NULL)
{
printf("Initialize Result: %s\n", initialize_result);
free(initialize_result);
}
else
{
printf("β Failed to initialize account.\n");
}
// Call increment method
SolPublicKey increment_accounts[2] = {
account->pubkey,
payer->pubkey};
SolKeyPair *increment_signers[1] = {payer};
for (int i = 0; i < 2; i++)
{
char *increment_result = anchor_counter_increment_c(
client,
program_id,
increment_accounts,
2,
increment_signers,
1);
if (increment_result != NULL)
{
printf("Increment Result: %s\n", increment_result);
free(increment_result);
}
else
{
printf("β Failed to increment account.\n");
}
// Fetch and print the updated account value
uint8_t account_data[512]; // Larger buffer to handle future expansion
size_t data_offset = 8;
size_t bytes_copied = get_account_data_c(
client,
&account->pubkey,
account_data,
sizeof(account_data),
data_offset);
if (bytes_copied > 0)
{
printf("β
Data Copied: %zu bytes\n", bytes_copied);
uint64_t *counter = (uint64_t *)account_data;
printf("π’ Counter Value: %lu\n", *counter);
}
else
{
printf("β Failed to fetch account data.\n");
}
}
// Clean up resources
free_client(client);
free_payer(payer);
}
-
SolClient *new_sol_client(const char *url);
Initializes a Solana client for the given RPC URL.
-
void free_client(SolClient *client);
Frees the memory allocated for the client.
-
SolKeyPair *new_keypair();
Creates a new wallet (keypair).
-
SolKeyPair *load_wallet_from_file(const char *file_path);
Loads a wallet from a file.
-
char *get_wallet_address(SolKeyPair *wallet);
Retrieves the wallet's public address as a string.
-
SolPublicKey *get_public_key(SolKeyPair *wallet);
Retrieves the wallet's public key.
-
SolSecretKey *get_secret_key(SolKeyPair *wallet);
Retrieves the wallet's private key.
-
struct SolPublicKey *get_pubkey_from_address(const char *address);
Converts an address string to a public key.
-
char *get_address_from_pubkey(const struct SolPublicKey *pubkey);
Converts a public key to an address string.
-
void free_payer(SolKeyPair *payer);
Frees the memory allocated for the wallet.
-
bool transfer_sol(SolClient *client, SolKeyPair *sender, SolPublicKey *recipient, uint64_t lamports);
Transfers SOL from the sender to the recipient.
-
bool transfer_spl(SolClient *client, SolKeyPair *sender, SolPublicKey *recipient, SolPublicKey *mint, uint64_t amount);
Transfers SPL tokens from the sender to the recipient.
-
uint64_t get_associated_token_balance(SolClient *client, SolPublicKey *owner, SolPublicKey *mint);
Retrieves the balance of an associated token account.
-
bool create_spl_token(SolClient *client, SolKeyPair *payer, SolKeyPair *mint);
Creates a new SPL token.
-
bool mint_spl(SolClient *client, SolKeyPair *payer, SolKeyPair *mint_authority, SolPublicKey *recipient, uint64_t amount);
Mints new SPL tokens.
-
struct SolPublicKey *get_or_create_associated_token_account(SolClient *client, SolKeyPair *payer, SolPublicKey *owner, SolKeyPair *mint);
Gets or creates an associated token account for the owner and mint.
-
uintptr_t get_account_data_c(struct SolClient *client, struct SolPublicKey *account_pubkey, uint8_t *data_ptr, uintptr_t data_len, uintptr_t data_offset);
Fetches account data and copies it into a provided buffer.
-
struct SolMint *get_mint_info(struct SolClient *client, struct SolPublicKey *mint_pubkey);
Retrieves information about an SPL token mint.
-
char *send_generic_transaction_c(SolClient *client, const char *program_id, const char *method_name, const SolPublicKey *account_pubkeys, uintptr_t account_count, SolKeyPair *const *signers, uintptr_t signer_count, const uint8_t *data_ptr, uintptr_t data_len);
Sends a generic transaction to a smart contract.
-
void initialize_account_c(SolClient *client, SolKeyPair *payer, SolKeyPair *account, const char *program_id);
Initializes an account for a program.
This repository benchmarks Solana wallet operations using Rust (FFI via C) and C# (Solnet) to compare performance and efficiency.
Language | Description |
---|---|
π Rust (FFI via C) | Uses C to call Rust functions via Foreign Function Interface (FFI). |
π― C# (Solnet) | Uses the Solnet .NET SDK to interact with the Solana blockchain. |
Function | Rust (FFI via C) | C# (Solnet) |
---|---|---|
Wallet Creation | 0.05 - 1.7 ms | 50 - 80 ms |
Wallet Loading | 0.05 - 1.7 ms | 15 - 20 ms |
Airdrop Request | 0.05 ms (Async) - 3000 ms (Sync) | 59ms (The function does not wait for confirmation) |
Mint SPL Token | ~300 ms | N/A |
Transfer SPL Token | ~280 ms | N/A |
Transfer SOL | 230 - 280 ms | 300 - 500 ms |
-
Rust (FFI via C) is significantly faster than C# (Solnet) β‘
- Faster in wallet operations (creation, loading).
- Lower overhead than Solnet's managed memory approach.
-
C# (Solnet) is easier for .NET developers π―
- High-level API for easy Solana integration.
- Slower due to garbage collection and runtime overhead.
-
Network-bound operations (Airdrops, SPL Token Minting, Transfers) take a similar amount of time, as execution time is measured from the same starting point π
- These operations rely on blockchain processing time, meaning the execution speed is mostly determined by Solana network conditions and validator processing.
- Language choice affects only transaction preparation (e.g., constructing, signing, and submitting transactions), but the actual confirmation time depends on Solana.
- If the network is congested, all languages will experience delays equally.
This project is licensed under the MIT License.
Contributions are welcome! Please fork the repository and submit a pull request.
This SDK uses the following crates:
solana-client
solana-sdk
spl-token
borsh
serde
For detailed usage examples and advanced functionality, refer to the source code and the Solana documentation.