Receive Bitcoin
Mix.install([
{:bsv, "~> 2.1"},
{:httpoison, "~> 2.0"},
{:jason, "~> 1.4"},
{:qr_code, "~> 3.0"},
{:kino, "~> 0.14"}
])
network =
case System.get_env("LB_NETWORK", "test") do
"main" -> :main
"test" -> :test
other -> raise ArgumentError, "LB_NETWORK must be \"main\" or \"test\", got: #{inspect(other)}"
end
if network == :main and System.get_env("LIVEWALLET_HOSTED") == "true" do
raise "This is a hosted LiveWallet. Mainnet is only for a Livebook you run yourself."
end
Application.put_env(:bsv, :network, network)
Setup
Receive bitcoin at an address you derived yourself, so that you can see value arrive at a key you control.
Before this: Keys and Addresses. You need the address and its index from that notebook.
network = BSV.network()
woc = "https://api.whatsonchain.com/v1/bsv/#{network}"
{label, hint} =
case network do
:main -> {"MAINNET", "Real bitcoin. Keep amounts under 1 USD."}
:test -> {"TESTNET", "Coins have no value. Addresses start with m or n, not 1."}
end
Kino.Markdown.new("""
> **Network: #{label}** (`#{network}`).
> #{hint}
> To switch, set the Livebook secret `LB_NETWORK` to `main` or `test`, then re-evaluate the setup cell.
""")
Your address is a destination
Your address is derived from a public key. That public key has a corresponding private key, which only you hold.
Anyone can send bitcoin to the address. Only the private key can spend what arrives. What arrives is counted in satoshis, the smallest unit of bitcoin. One bitcoin is 100,000,000 satoshis, and this tutorial moves a few thousand.
flowchart LR
S[sender's wallet] -->|transaction| N[bitcoin network]
N -->|output locked to your address| U[UTXO]
K[your private key] -.->|can unlock later| U
address_input = Kino.Input.text("Your address from Keys and Addresses")
address = String.trim(Kino.Input.read(address_input))
{:ok, _} = BSV.Address.from_string(address)
address
A MatchError above means the address is not valid for the #{network} network.
Mainnet addresses start with 1; testnet addresses start with m or n.
How and where to get bitcoin
Kino.Markdown.new(
case network do
:main ->
"""
You are on **mainnet**, so this is real bitcoin.
Keep it small: less than 1 USD is plenty for the whole tutorial.
* Ask a friend who uses BSV to send a small amount to your address.
* Buy a small amount from an exchange that supports BSV withdrawals, and withdraw to your address.
* Use a BSV wallet app you already have, and send from it to your address.
"""
:test ->
"""
You are on **testnet**, so the coins have no value.
* Search for a "BSV testnet faucet" and paste your address into it.
* Faucets come and go; if one is down, try another.
* If none work, switch `LB_NETWORK` to `main` and use a few real satoshis instead.
"""
end
)
Once you have sent bitcoin to the address, the sending wallet usually shows a confirmation. Now prove it from your side.
Watch the value arrive
The WhatsOnChain API lists the unspent outputs locked to an address. Re-evaluate this cell until it shows at least one.
%{status_code: 200, body: body} = HTTPoison.get!("#{woc}/address/#{address}/unspent")
utxos = Jason.decode!(body)
case utxos do
[] ->
"Nothing yet. Send bitcoin to #{address}, wait a few seconds, and re-evaluate this cell."
[first | _] ->
"""
Received.
txid: #{first["tx_hash"]}
output: #{first["tx_pos"]}
value: #{first["value"]} satoshis
height: #{first["height"]} (0 means still in the mempool)
"""
end
The tx_hash is the transaction id, or txid.
Copy it; you will look it up in the next notebook.
Review
You shared an address, someone sent bitcoin to it, and you saw the unspent output appear from the API.
checks = [
{"address is valid on #{network}", match?({:ok, _}, BSV.Address.from_string(address))},
{"at least one unspent output is locked to the address", utxos != []}
]
Enum.each(checks, fn {label, ok?} -> IO.puts("#{if ok?, do: "ok ", else: "FAIL"} #{label}") end)
failed = for {label, false} <- checks, do: label
if failed == [], do: "PASS", else: raise("FAIL: " <> Enum.join(failed, "; "))
Keep for later: the address, its index, and the txid.
Next
Verify On-Chain: look the transaction up and read its structure.
Stuck or have a question? Open an issue.