Solana - SDK for the Solana blockchain & ecosystem

solana is an unofficial Elixir package for interacting with the Solana blockchain.

There’s also solana_spl, an unofficial Elixir package for interacting with the Solana Program Library.

You can use these packages to build clients for your Solana programs in Elixir, as opposed to using the official JavaScript and Rust SDKs or any of the unofficial SDKs in other languages.

Here’s an article explaining part of the motivation for me building this: Announcing the Solana Elixir SDK. Bringing Elixir to the Solana… | by e^{i} Ventures | Nov, 2021 | Medium

JSON-RPC API Client

At its core, solana provides a simple interface for interacting with Solana’s JSON-RPC API. Here’s an example of requesting an airdrop to a new Solana account via the requestAirdrop method:

key = Solana.keypair() |> Solana.pubkey!()
client = Solana.RPC.client(network: "localhost")
{:ok, signature} = Solana.RPC.send(client, Solana.RPC.Request.request_airdrop(key, 1))

Solana.Transaction.check(signature) # {:ok, ^signature}

I haven’t implemented all the API methods yet since I don’t need all of them. All the commonly-used ones are supported.

Using a custom HTTP client

Since this module uses Tesla for its API client, you can use whichever HTTP client you wish, just be sure to include it in your dependencies:

def deps do
  [
    # Gun, for example
    {:gun, "~> 1.3"},
    {:idna, "~> 6.0"},
    {:castore, "~> 0.1"},
    # SSL verification
    {:ssl_verify_hostname, "~> 1.0"},
  ]
end

Then, specify the corresponding Tesla.Adapter when creating your client:

client = Solana.RPC.client(network: "localhost", adapter: {Tesla.Adapter.Gun, certificates_verification: true})

See the Solana.RPC module for more details about which options are available when creating an API client.

On-chain program interaction

Since solana's JSON-RPC API client supports sendTransaction, you can use it to interact with on-chain Solana programs. solana provides utilities to craft transactions, send them, and confirm them on-chain. It also includes the Solana.SystemProgram module, which allows you to create SystemProgram instructions.

Also check out the solana_spl package documentation to interact with the Solana Program Library.

Writing a custom program client

By providing an interface for the Solana.SystemProgram, solana provides guidelines for how to build interfaces to your own programs. For more examples, see the solana_spl package.

Testing custom programs

Once you’ve built your custom program’s client, you should probably write some tests for it. solana provides example tests for the Solana.SystemProgram in test/solana/system_program_test.exs, along with an Elixir-managed Solana Test Validator process to test your program locally. See Solana.TestValidator for more details about how to set this up.

Future work

I plan on adding additional JSON-RPC API methods and on-chain program interfaces as I need them (and as the Solana JSON-RPC API changes). Contributions are welcome on GitHub.

6 Likes

Nice work! I have one doubt ( [solana_spl), for sample: if I use file system wallet the keypair, how I can load it in lib context to sign transactions to transfer my own tokens from one wallet to another? I can provide another account to PAY the gas? Any sample.

A file system wallet is basically a combining the bytes from the private key and public key, then putting them into a json-encoded list. This code snippet should take the contents of a file system wallet and turn it into a keypair:

def read(path) do
  with {:ok, contents} <- File.read(path),
       {:ok, list} <- Jason.decode(contents),
       <<sk::binary-size(32), pk::binary-size(32)>> <- :erlang.list_to_binary(list) do
    {:ok, {sk, pk}}
  else
    {:error, _} = error -> error
    _string -> {:error, "invalid file contents"}
  end
end

Then, you can use that keypair to sign a transaction and/or pay for it. (I’ll probably add this into the main solana package soon!)

To answer your second question, you can specify the payer’s pubkey separately in the Solana.Transaction struct with the payer attribute. See the documentation here: Solana.Transaction — Solana v0.1.3

1 Like

v0.2.0

This release fixes some bugs, decodes some more fields in RPC API results, and adds some new functionality:

  • Transaction.parse/1 for turning a binary-encoded transaction into Solana.Transaction struct
  • Key.pair_from_file/1 for reading a keypair from a file system wallet.
  • RPC.Request.get_multiple_accounts/2 for calling the RPC API’s getMultipleAccounts method.
1 Like

Hi @dcrck
do you plan support Solana V0 message