Satoxi
Satoxi is a general purpose library for building Bitcoin applications in Elixir.
Features
Currently supported features:
- Keypair generation with address encoding and decoding (Legacy, SegWit, Nested SegWit)
- BIP-39 mnemonic phrase generation and BIP-32 hierarchical deterministic keys
- Script and smart contract builder for defining locking/unlocking scripts
- Transaction builder with signing for both legacy and SegWit transactions
-
Full SegWit support including
P2WPKH,P2WSH, andP2SH-P2WPKH(nested SegWit)
Installation
The package can be installed by adding satoxi to your list of dependencies in mix.exs:
def deps do
[
{:satoxi, "~> 1.0.0"}
]
endConfiguration
Optionally, Satoxi can be configured for testnet network by editing your application's configuration:
config :satoxi,
network: :test # defaults to :mainUsage
Satoxi is a comprehensive Bitcoin library. Many examples can be found through the documentation. See the following for some quick-start examples:
Keypairs, Addresses, BIP-32
Generate a new random keypair and derive its address.
iex> keypair = Satoxi.Keys.new_keypair()
%Satoxi.Keys.KeyPair{
privkey: %Satoxi.Keys.PrivKey{
d: <<119, 134, 104, 227, 196, 255, 3, 163, 39, 9, 0, 43, ...>>
},
pubkey: %Satoxi.Keys.PubKey{
point: %Curvy.Point{
x: 80675204119348790085831157628459085855227400073327708725575496785606354176436,
y: 9270420727654506759611377999115473532064051910093243567168505762017618809348
}
}
}
iex> address = Satoxi.Address.from_pubkey(keypair.pubkey)
iex> Satoxi.Address.to_string(address)
"19D5DoRKchdZbsP3fXYhopbFDdCJCPaLjr"
# Generate a SegWit address
iex> segwit_address = Satoxi.Address.from_pubkey(keypair.pubkey, type: :p2wpkh)
iex> Satoxi.Address.to_string(segwit_address)
"bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4"Generate a BIP-32 HD wallet, derive a child and its address.
iex> mnemonic = Satoxi.Mnemonic.new()
"taste canvas eternal brain rent cement fat dilemma duty fame floor defy"
iex> seed = Satoxi.Mnemonic.to_seed(mnemonic)
iex> extkey = Satoxi.Keys.extkey_from_seed!(seed)
%Satoxi.Keys.ExtKey{
chain_code: <<110, 26, 215, 117, 61, 123, 141, 33, ...>>,
child_index: 0,
depth: 0,
fingerprint: <<0, 0, 0, 0>>,
privkey: %Satoxi.Keys.PrivKey{...},
pubkey: %Satoxi.Keys.PubKey{...},
version: <<4, 136, 173, 228>>
}
# Derive child key and address
iex> child = Satoxi.Keys.extkey_derive(extkey, "m/0/1")
iex> address = Satoxi.Address.from_pubkey(child.pubkey)
iex> Satoxi.Address.to_string(address)
"1Cax2dCtapJZtwzYXCdLuTkZ1egG8JSugA"Building transactions
The Builder module provides a simple declarative way to build any type of transaction.
iex> alias Satoxi.Contract.P2PKH
iex> utxo = Satoxi.Transaction.utxo_from_params!(utxo_params)
iex> builder = %Satoxi.Transaction.Builder{
...> inputs: [
...> P2PKH.unlock(utxo, %{keypair: keypair})
...> ],
...> outputs: [
...> P2PKH.lock(10000, %{address: address})
...> ]
...> }
iex> tx = Satoxi.Transaction.builder_to_tx(builder)
iex> rawtx = Satoxi.Transaction.to_binary(tx, encoding: :hex)
"0100000001121a9ac1e0..."
For SegWit transactions, use the P2WPKH or P2SH_P2WPKH contracts:
iex> alias Satoxi.Contract.P2WPKH
iex> builder = %Satoxi.Transaction.Builder{
...> inputs: [
...> P2WPKH.unlock(utxo, %{keypair: keypair})
...> ],
...> outputs: [
...> P2WPKH.lock(10000, %{address: segwit_address})
...> ]
...> }Creating custom contracts
The Satoxi.Contract module provides a way to define locking and unlocking scripts in pure Elixir.
# Define a module that implements the `Contract` behaviour
defmodule P2PKH do
use Satoxi.Contract
def locking_script(ctx, %{address: address}) do
ctx
|> op_dup
|> op_hash160
|> push(address.pubkey_hash)
|> op_equalverify
|> op_checksig
end
def unlocking_script(ctx, %{keypair: keypair}) do
ctx
|> sig(keypair.privkey)
|> push(Satoxi.Keys.PubKey.to_binary(keypair.pubkey))
end
endLicense
Satoxi is open source and released under the MIT License.