The Coinbase Ruby SDK enables the simple integration of crypto into your app. By calling Coinbase's Platform APIs, the SDK allows you to provision crypto wallets, send crypto into/out of those wallets, track wallet balances, and trade crypto from one asset into another.
The SDK currently supports Customer-custodied Wallets on the Base Sepolia test network.
NOTE: The Coinbase SDK is currently in Alpha. The SDK:
- may make backwards-incompatible changes between releases
- should not be used on Mainnet (i.e. with real funds)
Currently, the SDK is intended for use on testnet for quick bootstrapping of crypto wallets at hackathons, code academies, and other development settings.
Make sure that your developer environment satisfies all of the requirements before proceeding through the quickstart.
The Coinbase server-side SDK requires Ruby 2.7 or higher. To view your currently installed version of Ruby, run the following from the command-line:
ruby -v
We recommend installing and managing Ruby versions with rbenv
.
See Using Package Managers in the rbenv README for instructions on how to install rbenv
.
Once rbenv
has been installed, you can install and use Ruby 2.7 by running the following commands:
rbenv install 2.7.0
rbenv global 2.7.0
The Coinbase Platform SDK depends on the rbsecp256k1
gem, which requires certain dependencies to be installed on your system. Follow the instructions provided here to meet these requirements:
On MacOS, run the following command:
brew install automake openssl libtool pkg-config gmp libffi
On Linux, run the following command:
sudo apt-get install build-essential automake pkg-config libtool \
libffi-dev libssl-dev libgmp-dev python3-dev
:::info
If you installed libsecp256k1
but the gem cannot find it, run ldconfig
to update your library load paths.
:::
The Coinbase Platform SDK relies on the openssl
gem for certain cryptographic operations. If you encounter issues installing
the Platform SDK, ensure that OpenSSL 3+ is installed, and that the version used by Ruby matches the version required by the gem.
If you encounter an error like this:
error: incomplete definition of type 'struct evp_md_ctx_st'
pkey = EVP_PKEY_CTX_get0_pkey(EVP_MD_CTX_get_pkey_ctx(ctx));
re-install the openssl gem with the following command:
gem install openssl -- --with-openssl-dir=$(brew --prefix openssl@3)
There are two ways of installing the Coinbase Platform SDK: for use with the Interactive Ruby Shell, or for use in a Ruby project (e.g. Ruby on Rails).
Use the Interactive Ruby Shell (irb
) to leverage Ruby’s built-in REPL and quickly explore the functionality of our SDK.
Run the following from the command line:
gem install coinbase-sdk
After running irb
, require the Gem:
require 'coinbase'
Alternatively, if you want to install your Coinbase SDK gem to your Ruby on Rails project, add the following line to your Gemfile:
gem 'coinbase-sdk'
Or if you are using a Gemspec:
Gem::Specification.new do |spec|
spec.add_runtime_dependency 'coinbase-sdk'
end
Then run:
bundle install
To start, create a CDP API key. Then, initialize the Platform SDK by passing your API key name and API key's private key via the configure
method:
api_key_name = "Copy your API key name here."
# Ensure that you are using double-quotes here.
api_key_private_key = "Copy your API key's private key here."
Coinbase.configure do |config|
config.api_key_name = api_key_name
config.api_key_private_key = api_key_private_key
end
puts "Coinbase SDK has been successfully configured with CDP API key."
Another way to initialize the SDK is by sourcing the API key from the JSON file that contains your API key, downloaded from the CDP portal.
Coinbase.configure_from_json('~/Downloads/cdp_api_key.json')
puts "Coinbase SDK has been successfully configured from JSON file."
This will allow you to authenticate with the Platform APIs and get access to the
default_user
:
u = Coinbase.default_user
If you are using a CDP Server-Signer to manage your private keys, enable it with
Coinbase.configuration.use_server_signer=true
Now, create a wallet from the User. Wallets are created with a single default address.
# Create a wallet with one address by default.
w1 = u.create_wallet
Wallets come with a single default address, accessible via default_address
:
# A wallet has a default address.
a = w1.default_address
Wallets do not have funds on them to start. For Base Sepolia testnet, we provide a faucet
method to fund your wallet with
testnet ETH. You are allowed one faucet claim per 24-hour window.
# Fund the wallet with a faucet transaction.
faucet_tx = w1.faucet
puts "Faucet transaction successfully completed: #{faucet_tx}"
See Transfers for more information.
Now that your faucet transaction has successfully completed, you can send the funds in your wallet to another wallet.
The code below creates another wallet, and uses the transfer
function to send testnet ETH from the first wallet to
the second:
# Create a new wallet w2 to transfer funds to.
w2 = u.create_wallet
puts "Wallet successfully created: #{w2}"
t = w1.transfer(0.00001, :eth, w2).wait!
puts "Transfer successfully completed: #{t}"
To transfer USDC without needing to hold ETH for gas, you can use the transfer
method with the gasless
option set to true
.
# Create a new wallet w3 to transfer funds to.
w3 = u.create_wallet
puts "Wallet successfully created: #{w3}"
t = w1.transfer(0.00001, :usdc, w3, gasless: true).wait!
# Get the first transfer from the address.
address.transfers.first
# Iterate over all transfers in the address. This will lazily fetch transfers from the server.
address.transfers.each do |transfer|
puts transfer
end
# Return array of all transfers. This will paginate and fetch all transfers for the address.
address.transfers.to_a
See Trades for more information.
wallet = Coinbase::Wallet.create(network_id: "base-mainnet")
puts "Wallet successfully created: #{wallet}"
puts "Send `base-mainnet` ETH to wallets default address: #{wallet.default_address.id}"
trade = wallet.trade(0.00001, :eth, :usdc).wait!
puts "Trade successfully completed: #{trade}"
# Get the first trade from the address.
address.trades.first
# Iterate over all trades in the address. This will lazily fetch trades from the server.
address.trades.each do |trade|
puts trade
end
# Return array of all trades. This will paginate and fetch all trades for the address.
address.trades.to_a
The SDK creates wallets with developer managed keys, which means you are responsible for securely storing the keys required to re-instantiate wallets. The following code explains how to export a wallet and store it in a secure location.
# Export the data required to re-instantiate the wallet.
data = w1.export
In order to persist the data for a wallet, you will need to implement a store
method to store the exported data in a secure location. If you do not store the wallet in a secure location, you will lose access to the wallet, as well as the funds on it.
# You should implement the "store" method to securely persist the data object,
# which is required to re-instantiate the wallet at a later time. For ease of use,
# the data object is converted to a Hash first.
store(data.to_hash)
For more information on wallet persistence, see the documentation on wallets.
Alternatively, you can use the save_seed!
function to persist a wallet's seed to a local file. This is a
convenience function purely for testing purposes, and should not be considered a secure method of persisting wallets.
# Pick a file to which to save your wallet seed.
file_path = 'my_seed.json'
# Set encrypt: true to encrypt the wallet seed with your CDP API key.
w1.save_seed!(file_path, encrypt: true)
puts "Seed for wallet #{w1.id} successfully saved to #{file_path}."
To re-instantiate a wallet, fetch your export data from your secure storage, and pass it to the import
method:
# You should implement the "fetch" method to retrieve the securely persisted data object,
# keyed by the wallet ID.
fetched_data = fetch(w1.id)
# w3 will be equivalent to w1.
w3 = u.import_wallet(fetched_data)
If you used the save_seed!
function to persist a wallet's seed to a local file, then you can first fetch
the unhydrated wallet from the server, and then use the load_seed
method to re-instantiate the wallet.
# Get the unhydrated wallet from the server.
w4 = u.wallet(w1.id)
# You can now load the seed into the wallet from the local file.
# w4 will be equivalent to w1.
w4.load_seed(file_path)
Addresses that do not belong CDP wallets can still be interacted with via the Platform SDK.
You can fetch balances, request faucet funds, and eventually construct unsigned transactions that can be signed by the owner of the address (e.g. your user's self-custodied wallet).
See External Addresses docs for more information.
Developing in this repository requires Ruby >= 2.7.0. To install this on an M2 Mac, run the following command:
RUBY_CFLAGS=-DUSE_FFI_CLOSURE_ALLOC rbenv install 2.7.0
Clone the repo by running:
git clone https://github.com/coinbase/coinbase-sdk-ruby.git
To install all dependencies, run:
bundle install
This SDK transitively depends on rbsecp256k1. Follow these instructions to ensure you have the necessary dependencies installed.
The SDK assumes the existence of a BASE_SEPOLIA_RPC_URL
environment variable defined in your .env file.
By default, this is the publicly available endpoint, which is rate-limited.
To provision your own endpoint, go to the CDP Portal. Then
copy and paste your Base Sepolia RPC URL in the .env file:
BASE_SEPOLIA_RPC_URL=YOUR-URL
To autocorrect all lint errors, run:
make format
To detect all lint errors, run:
make lint
To run all tests, run:
make test
To run a specific test, run (for example):
bundle exec rspec spec/coinbase/wallet_spec.rb
The repository is equipped with a REPL to allow developers to play with the SDK. To start it, run:
make repl
To generate documentation from the Ruby comments, run:
make docs