Project

pochette

0.01
No commit activity in last 3 years
No release in over 3 years
Pochette is a Bitcoin Wallet backend offering a common interface to several bitcoin nodes so you can build single purpose wallets. You can pass in a bunch of addresses and outputs and it will select the appropriate unspent outputs for each of them, calculate change, fees, etc.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Development

~> 1.9
~> 10.0
~> 3
~> 0.8.0
~> 1.21

Runtime

~> 0.1.1
~> 0.0.13
~> 0.12.0
~> 0.9.0
 Project Readme

Pochette

Pochette is a Bitcoin Wallet for developers, or more accurately a tool for building "single purpose wallets".

It's used extensively at Bitex.la from checking and crediting customer bitcoin deposits to preparing transactions with bip32 paths instead of input addresess, ready to be signed with a Trezor Device

Pochette offers a common interface to full bitcoin nodes like Bitcoin Core Blockchain.info or Toshi and will let you run several instances of each one of them simultaneously always choosing the most recent node to query.

It also provides a Pochette::TransactionBuilder class which receives a list of 'source' addresses and a list of recipients as "address/amount" pairs and uses them to select unspent outputs and build a raw transaction to be signed and broadcasted.

The Pochette::TrezorTransactionBuilder class extends Pochette::TransactionBuilder including transactions, inputs and outputs that are formatted in a way they can be passed directly to a Trezor device for signing. You can even build transactions for multisig addresses to be signed by several trezors.

Table of contents

  • Installation and Setup
  • Pochette::TransactionBuilder
  • Pochette::TrezorTransactionBuilder
  • Backend API
    • incoming_for(addresses, min_date)
    • balances_for(addresses, confirmations)
    • list_unspent(addresses)
    • list_transactions(txids)
    • block_height
    • pushtx(hex)
  • Supported Backends
    • BitcoinCore Backend
    • BlockchainInfo Backend
    • Toshi Backend
    • Trendy Backend

Installation and Setup

Add this line to your application's Gemfile:

gem 'pochette'

And then execute:

$ bundle

Or install it yourself as:

$ gem install pochette

You will probably want to setup Pochette with a global default backend, the backend can also be configured separately for each instance of a Pochette::TransactionBuilder

  > Pochette.backend = Pochette::Backends::BlockchainInfo.new
  > Pochette::TransactionBuilder.backend = Pochette::Backends::BlockchainInfo.new
  > Pochette::TrezorTransactionBuilder.backend = Pochette::Backends::BlockchainInfo.new

Pochette can also be configured to use the bitcoin testnet, this will change the default network used by the Bitcoin gem and may alter the way backends work too.

  > Pochette.testnet = true

The Pochette::TransactionBuilder

The TransactionBuilder builds transactions from a list of source addresses and a list of recipients, using a configured backend to fetch unspent outputs and related transaction data. Instantiating will perform all the required queries, you'll be left with a TransactionBuilder object that is either valid? or not, and if valid, you can query the results via to_hash.

Receives

The TransactionBuilder's initializer receives a single options hash with:

addresses:
List of addresses in wallet. We will be spending their unspent outputs.
outputs:
List of pairs [recipient_address, amount] This will not be all the final outputs in the transaction, as a 'change' output may be added if needed.
utxo_blacklist:
Optional. List of utxos to ignore, a list of pairs [transaction hash, position]
change_address:
Optional. Change address to use. Will default to the first source address.
fee_per_kb:
Optional. Defaults to 10000 satoshis.
spend_all:
Optional. Boolean. Wether to spend all available utxos or just select enough to cover the given outputs.

Returns

A hash with

input_total:
The sum of all input amounts, in satoshis.
output_total:
The sum of all outputs, in satoshis.
fee:
fee to pay (input_total - output_total).
outputs:
Array of [destination address, amount in satoshis]
inputs:
Array of [input address, utxo transaction hash, utxo position, amount, scriptPubKey]
utxos_to_blacklist:
Transaction inputs formatted to be used as utxo_blacklist on another TransactionBuilder.
  > require 'pochette'
  > backend = Pochette::Backends::BlockchainInfo.new
  > transaction = Pochette::TransactionBuilder.new({
        addresses: ["2NAHscN6XVqUPzBSJHC3fhkeF5SQVxiR9p9"],
        outputs: [
          ["mvtUvWSWCU7knrcMVzjcKJgjL1LdekLK5q", 1_0000_0000],
        ],
        utxo_blacklist: [
          ["0ded7f014fa3213e9b000bc81b8151bc6f2f926b9afea6e3643c8ad658353c72", 1]
        ],
        change_address: 'mgaTEUM4ZE9kLiK58FcffwHfvxpte5CfvE',
        fee_per_kb: 10000,
        spend_all: false,
        backend: backend
      })
  > transaction.valid?
  => true
  > transaction.as_hash
  => {
      input_total: 2_0000_0000,
      output_total: 1_9999_0000,
      fee: 10000,
      outputs: [
        ["mvtUvWSWCU7knrcMVzjcKJgjL1LdekLK5q", 1_0000_0000],
        ["mgaTEUM4ZE9kLiK58FcffwHfvxpte5CfvE", 9999_0000],
      ],
      inputs: [
        [ "2NAHscN6XVqUPzBSJHC3fhkeF5SQVxiR9p9",
          "956b30c3c4335f019dbee60c60d76994319473acac356f774c7858cd5c968e40",
          1,
          200000000,
          'public_key_in_hex_format'
        ],
      ],
      utxos_to_blacklist: [
        ["956b30c3c4335f019dbee60c60d76994319473acac356f774c7858cd5c968e40", 1]
      ],
     }

The Pochette::TrezorTransactionBuilder

Builds a transaction like TransactionBuilder but includes transaction data and formats inputs and outputs in a way that can be sent directly to your trezor device. If you're using Trezor Connect for signing then you won't need to pass in the transactions.

Receives

The TrezorTransactionBuilder's initializer receives a single options hash with:

bip32_addresses:
List of addresses in wallet. We will be spending their unspent outputs. Each address is represented as a pair, with the public address string and the BIP32 path as a list of integers, for example:
  ['public-address-as-string', [44, 1, 3, 11]]
  

If you're spending from a multisig address then you should provide all the root xpubs ( session.getPublicKey([]) ) from your different trezor devices, the path as a list of integers and the M number (as in M out of N). The actual bitcoin address will be derived from these. The following example is for a multi-sig address where 2 out of 3 trezors can sign. The address is generated from the public key at path [42, 1, 1] in each trezor.

  [['xpub661MyMwAqRbcGCmcnz4JtnieVyuvgQFGqZqw3KS1g9khndpF3segkAYbYCKKaQ9Di2ZuWLaZU4Axt7TrKq41aVYx8XTbDbQFzhhDMntKLU5',
    'xpub661MyMwAqRbcFwc3Nmz8WmMU9okGmeVSmuprwNHCVsfhy6vMyg6g79octqwNftK4g62TMWmb7UtVpnAWnANzqwtKrCDFe2UaDCv1HoErssE'
    'xpub661MyMwAqRbcGkqPSKVkwTMtFZzEpbWXjM4t1Dv1XQbfMxtyLRGupWkp3fcSCDtp6nd1AUrRtq8tnFGTYgkY1pB9muwzaBDnJSMo2rVENhz'],
   [42,1,1],
   2]
  
outputs:
List of pairs [recipient_address, amount] This will not be all the final outputs in the transaction, as a 'change' output may be adted if needed.
utxo_blacklist:
Optional. List of utxos to ignore, a list of pairs [transaction hash, position]
change_address:
Optional. Change address to use. Will default to the first source address.
fee_per_kb:
Optional. Defaults to 10000 satoshis.
spend_all:
Optional. Boolean. Wether to spend all available utxos or just select enough to cover the given outputs.
#### Returns A hash with
input_total:
The sum of all input amounts, in satoshis.
output_total:
The sum of all outputs, in satoshis.
fee:
fee to pay (input_total - output_total).
outputs:
Array of [destination address, amount in satoshis]
inputs:
Array of [input address, utxo transaction hash, utxo position, amount]
utxos_to_blacklist:
Transaction inputs formatted to be used as utxo_blacklist on another TransactionBuilder.
transactions:
Transaction data for each input.
trezor_inputs:
List of inputs as hashes with bip32 paths instead of addresses { address_n: [42,1,1], prev_hash: "956b30c3c4335f019dbee60c60d76994319473acac356f774c7858cd5c968e40", prev_index: 1} When spending from a multisig address, the inputs will also include the multisig structure, with nodes and everything your trezor needs to sign. Notice there's a 'signatures' key inside 'multisig', you should sign the transaction as is, then populate the corresponding value in 'signatures' and keep signing until you have all the required signatures. { address_n: [42,1,1], prev_hash: "eeeb30c3c4335f019dbee60c60d76994319473acac356f774c7858cd5c968eee", prev_index: 0, script_type: 'SPENDMULTISIG', multisig: { signatures: ['','',''], m: 2, pubkeys: [ { address_n: [42,1,1], node: { chain_code: 'a6d47170817f78094180f1a7a3a9df7634df75fa9604d71b87e92a5a6bf9d30a', depth: 0, child_num: 0, fingerprint: 0, public_key: '03142b0a6fa6943e7276ddc42582c6b169243d289ff17e7c8101797047eed90c9b', } }, { address_n: [42,1,1], node: { chain_code: '8c9151740446b9e0063ca934df66c5e14121a0b4d8a360748f1b19bfef675460', depth: 0, child_num: 0, fingerprint: 0, public_key: '027565ceb190647ec5c566805ebc5cb6166ae2ee1d4995495f61b9eff371ec0e61', } }, { address_n: [42,1,1], node: { chain_code: 'de5bc5918414df3777ff52ae733bdbc87431485cfd39aea65da6133e183ef68a', depth: 0, child_num: 0, fingerprint: 0, public_key: '028776ff18f0f3808d6d42749a6e2baee5c75c3f7ae07445403a3a5690d580a0af', } } ] }
trezor_outputs:
List of outputs as Hashes with: { script_type: 'PAYTOADDRESS', address: '1address-as-string', amount: amount in satoshis }
``` > require 'pochette' > backend = Pochette::Backends::BlockchainInfo.new > transaction = Pochette::TransactionBuilder.new({ addresses: [ ["2NAHscN6XVqUPzBSJHC3fhkeF5SQVxiR9p9", [44, 1, 3, 11]] ], outputs: [ ["mvtUvWSWCU7knrcMVzjcKJgjL1LdekLK5q", 1_0000_0000], ], utxo_blacklist: [ ["0ded7f014fa3213e9b000bc81b8151bc6f2f926b9afea6e3643c8ad658353c72", 1] ], change_address: 'mgaTEUM4ZE9kLiK58FcffwHfvxpte5CfvE', fee_per_kb: 10000, spend_all: false }) > transaction.valid? => true >>> transaction.as_hash => { input_total: 2_0000_0000, output_total: 1_9999_0000, fee: 10000, outputs: [ ["mvtUvWSWCU7knrcMVzjcKJgjL1LdekLK5q", 1_0000_0000], ["mgaTEUM4ZE9kLiK58FcffwHfvxpte5CfvE", 9999_0000], ], trezor_outputs: [ { script_type: 'PAYTOADDRESS', address: "mvtUvWSWCU7knrcMVzjcKJgjL1LdekLK5q", amount: 1_0000_0000 }, { script_type: 'PAYTOADDRESS', address: "mgaTEUM4ZE9kLiK58FcffwHfvxpte5CfvE", amount: 9999_0000 }, ], inputs: [ [ "2NAHscN6XVqUPzBSJHC3fhkeF5SQVxiR9p9", "956b30c3c4335f019dbee60c60d76994319473acac356f774c7858cd5c968e40", 1, 200000000, "script_pubkey" ], ], trezor_inputs: [ { address_n: [43,1,3,11], prev_hash: "956b30c3c4335f019dbee60c60d76994319473acac356f774c7858cd5c968e40", prev_index: 1 }, ], transactions: [ { hash: "956b30c3c4335f019dbee60c60d76994319473acac356f774c7858cd5c968e40", version: "1", lock_time: "0", inputs: [ { prev_hash: "158d6bbe586b4e00347f992e8296532d69f902d0ead32d964b6c87d4f8f0d3ea", prev_index: 0, sequence: 4294967295, script_sig: "SCRIPTSCRIPTSCRIPT" } ], bin_outputs: [ { amount: 1234568, script_pubkey: "76a914988cb8253f4e28be6e8bfded1b4aa11c646e1a8588ac" }, { amount: 200000000, script_pubkey: "76a914988cb8253f4e28be6e8bfded1b4aa11c646e1a8588ac"} ] } ], utxos_to_blacklist: [ ["956b30c3c4335f019dbee60c60d76994319473acac356f774c7858cd5c968e40", 1] ], } ``` ## Backend API Pochette offers a common interface to full bitcoin nodes like [Bitcoin Core](https://bitcoin.org/en/download) [Blockchain.info](https://blockchain.info/api) or [Toshi](http://toshi.io) and will let you run several instances of each one of them simultaneously always choosing the most recent node to query. ## incoming_for(addresses, min_date) The incoming_for method is useful when registering deposits received to a number of bitcoin addresses. #### Receives - addresses: A list of public bitcoin addresses to check for incoming transactions. - min_date: Do not check for deposits earlier than this date. This is only to prevent fetching too many results if the backend was to return too many, each backend may apply its own limits so higher value here is not guaranteed to fetch more results. #### Returns A list with - Amount received, in satoshis. - Address which received the deposit. - Transaction hash for the deposit. - Confirmations for the transaction. - Position of this deposit in the transaction outputs list. - Senders, as a comma-separated list of addresses (no whitespaces) ``` > require 'pochette' > backend = Pochette::Backends::BlockchainInfo.new > addresses = [ 'mjfa56Keq7PXRKgdPSDB6eWLp4aaAVcj6L', 'mwZE4QfzzriE7nsgHSWbgmtT7s6SDysYvP', 'mvrDG7Ts6Mq9ejhZxdsQLjbScycVaktqsg', 'mxYzRdJfPk8PcaKSsSzNkX85mMfNcr2CGr', 'mzbXim4u1Nq4J2kVggu471pZL3ahxNkmE9', 'mhLAgRz5f1YogfYBZCDFSRt3ceeKBPVEKg', ] > Pochette.backend.incoming_for(addresses, 1.day.ago) => [ [ 500000, "mjfa56Keq7PXRKgdPSDB6eWLp4aaAVcj6L", "fb401691795a73e0160252c00af18327a15006fcdf877ccca0c116809669032e", 1629, 0, "my2hmDuD9XjmtQWFu9HyyNAsE5WGSDBKpQ"], [100000, "mxYzRdJfPk8PcaKSsSzNkX85mMfNcr2CGr", "250978b77fe1310d6c72239d9e9589d7ac3dc6edf1b2412806ace5104553da34", 1648, 1, "mv9ES7SmQQQ8dpMravBKsLWukgxU2DXfFs"], [500000, "mvrDG7Ts6Mq9ejhZxdsQLjbScycVaktqsg", "d9afd460b0a5e065fdd87bf97cb1843a29ea588c59daabd1609794e8166bb75f", 1648, 0, "my2hmDuD9XjmtQWFu9HyyNAsE5WGSDBKpQ"], [ 100000, "mxYzRdJfPk8PcaKSsSzNkX85mMfNcr2CGr", "5bd72a4aa7818f47ac8943e3e17519be00c46530760860e608d898d728b9d46e", 553, 1, "mvUhgW1ZcUju181bvwEhmZu2x2sRdbV4y2"], [ 500000, "mwZE4QfzzriE7nsgHSWbgmtT7s6SDysYvP", "b252037526ecb616ab5901552abb903f00bf73400a1fc49b5b5bd699b84bce77", 1632, 0, "my2hmDuD9XjmtQWFu9HyyNAsE5WGSDBKpQ"], [ 500000, "mzbXim4u1Nq4J2kVggu471pZL3ahxNkmE9", "ff768084764a05d1de72628432c0a4419538b2786089ec8ad009f6096bc69fe1", 1660, 0, "my2hmDuD9XjmtQWFu9HyyNAsE5WGSDBKpQ"] ] ``` ## balances_for(addresses, confirmations) Gets confirmed and unconfirmed sent, received and total balances for the given addresses. It's useful for payment processing as you can see what's the total amount seen on the network for a given address, and the final confirmed amount as well. #### Receives - addresses: A list of public bitcoin addresses to check balances for. - confirmations: How many confirmations to use for the 'confirmed' amounts. #### Returns A hash where keys are public addresses and values ara a list of - Confirmed received - Confirmed sent - Confirmed balance - Unconfirmed received - Unconfirmed sent - Unconfirmed balance ```ruby > require 'pochette' > backend = Pochette::Backends::BlockchainInfo.new > addresses = [ 'mjfa56Keq7PXRKgdPSDB6eWLp4aaAVcj6L', 'mwZE4QfzzriE7nsgHSWbgmtT7s6SDysYvP', 'mvrDG7Ts6Mq9ejhZxdsQLjbScycVaktqsg', 'mxYzRdJfPk8PcaKSsSzNkX85mMfNcr2CGr', 'mzbXim4u1Nq4J2kVggu471pZL3ahxNkmE9', 'mhLAgRz5f1YogfYBZCDFSRt3ceeKBPVEKg', ] > backend.balances_for(addresses, 6) => { "mhLAgRz5f1YogfYBZCDFSRt3ceeKBPVEKg" => [0.00544426, 0.00544426, 0.0, 0.00544426, 0.00544426, 0.0], "mjfa56Keq7PXRKgdPSDB6eWLp4aaAVcj6L" => [0.005, 0.0, 0.005, 0.006, 0.0, 0.006], "mvrDG7Ts6Mq9ejhZxdsQLjbScycVaktqsg" => [0.005, 0.0, 0.005, 0.005, 0.0, 0.005], "mwZE4QfzzriE7nsgHSWbgmtT7s6SDysYvP" => [0.005, 0.0, 0.005, 0.005, 0.0, 0.005], "mxYzRdJfPk8PcaKSsSzNkX85mMfNcr2CGr" => [0.002, 0.0, 0.002, 0.002, 0.0, 0.002], "mzbXim4u1Nq4J2kVggu471pZL3ahxNkmE9" => [0.005, 0.0, 0.005, 0.005, 0.0, 0.005], } ``` ## list_unspent(addresses) Gets unspent transaction outputs (a.k.a. utxos) for all the given addresses. You may not need to use this directly, but rather through a Pochette::TransactionBuilder which is smart about selecting utxos. #### Receives - addresses: A list of public bitcoin addresses to check balances for. #### Returns A list of list, each of them is - Address - Transaction Hash - Output position in transaction - Unspent amount ``` > require 'pochette' > backend = Pochette::Backends::BlockchainInfo.new > addresses = [ 'mjfa56Keq7PXRKgdPSDB6eWLp4aaAVcj6L', 'mwZE4QfzzriE7nsgHSWbgmtT7s6SDysYvP', 'mvrDG7Ts6Mq9ejhZxdsQLjbScycVaktqsg', 'mxYzRdJfPk8PcaKSsSzNkX85mMfNcr2CGr', 'mzbXim4u1Nq4J2kVggu471pZL3ahxNkmE9', 'mhLAgRz5f1YogfYBZCDFSRt3ceeKBPVEKg', ] > backend.list_unspent(addresses).should == [ ["mjfa56Keq7PXRKgdPSDB6eWLp4aaAVcj6L", "fb401691795a73e0160252c00af18327a15006fcdf877ccca0c116809669032e", 0, 500000, "script_pub_key"], ["mxYzRdJfPk8PcaKSsSzNkX85mMfNcr2CGr", "250978b77fe1310d6c72239d9e9589d7ac3dc6edf1b2412806ace5104553da34", 1, 100000, "script_pub_key"], ["mvrDG7Ts6Mq9ejhZxdsQLjbScycVaktqsg", "d9afd460b0a5e065fdd87bf97cb1843a29ea588c59daabd1609794e8166bb75f", 0, 500000, "script_pub_key"], ["mxYzRdJfPk8PcaKSsSzNkX85mMfNcr2CGr", "5bd72a4aa7818f47ac8943e3e17519be00c46530760860e608d898d728b9d46e", 1, 100000, "script_pub_key"], ["mwZE4QfzzriE7nsgHSWbgmtT7s6SDysYvP", "b252037526ecb616ab5901552abb903f00bf73400a1fc49b5b5bd699b84bce77", 0, 500000, "script_pub_key"], ["mjfa56Keq7PXRKgdPSDB6eWLp4aaAVcj6L", "9142d7a8e96124a36db9708dd21afa4ac81f15a77bd85c06f16e808a4d700da2", 1, 100000, "script_pub_key"], ["mzbXim4u1Nq4J2kVggu471pZL3ahxNkmE9", "ff768084764a05d1de72628432c0a4419538b2786089ec8ad009f6096bc69fe1", 0, 500000, "script_pub_key"] ] ``` ## list_transactions(txids) List full transaction data for the given transaction hashes. The output is formatted for Trezor as required by their multi-step signature process. You may not want to use this directly and use Pochette::TrezorTransactionBuilder instead. #### Receives - Transactions: A list of Transaction ids #### Returns A list of ruby hashes will transaction data for each id passed. ``` > require 'pochette' > backend = Pochette::Backends::BlockchainInfo.new > transactions = [ "fb401691795a73e0160252c00af18327a15006fcdf877ccca0c116809669032e", "250978b77fe1310d6c72239d9e9589d7ac3dc6edf1b2412806ace5104553da34", ] > backend.list_transactions(transactions) => [{ hash: "fb401691795a73e0160252c00af18327a15006fcdf877ccca0c116809669032e", version: 1, lock_time: 0, inputs: [ { prev_hash: "f948600a52719ec63947bd47105411c2cb032bda91b08b25bb7b1de22f1f7458", prev_index: 1, sequence: 4294967295, script_sig: "483045022100898b773c1cf095d5c1608a892673ad067387663e00327e7b88dd48cc4eb9cf2a02203a53336afd4440ea52c6a55e07ac60035dc386cb01b5b6810efac018f0346fad01210316cff587a01a2736d5e12e53551b18d73780b83c3bfb4fcf209c869b11b6415e" } ], bin_outputs: [ { amount: 500000, script_pubkey: "76a9142d81b210deb7e22475cd7f2fda0bf582dddc9da788ac" }, { amount: 276607256, script_pubkey: "76a914c01a7ca16b47be50cbdbc60724f701d52d75156688ac"} ] }, { hash: "250978b77fe1310d6c72239d9e9589d7ac3dc6edf1b2412806ace5104553da34", version: 1, lock_time: 0, inputs: [ { prev_hash: "8505c663d0414b678827eed85ba9e7652e616c19ff1be871f6b083d5ed400a20", prev_index: 0, sequence: 4294967295, script_sig: "47304402203ac7cb9afe1a14189b63807aff301ef6bb8507f6dc0471bcee5362282a8c3e38022012c3bfe9680f013735f0d6d012d6420383c0e3a1dbf010f97be9cc834a93d1f601210221af8672ff613d2ea198d8dadcc387a36ef47d7cba6f541221db61b96aa20149" } ], bin_outputs: [ { amount: 999293000, script_pubkey: "76a91426beab63a5fb7b2103929e91b65f339a2c5b285088ac"}, { amount: 100000, script_pubkey: "76a914badcbfae4d83a52dc2c8f68605663adc9d4922a688ac"} ] } ] ``` ## block_height Get the latest block height for this backend. Always in the main branch. ``` > require 'pochette' > backend = Pochette::Backends::BlockchainInfo.new > backend.get_height => 376152 ``` ## pushtx Propagates a raw transaction to the network. #### Receives - transaction: A raw transaction in hex format #### Returns The transaction id (hash) ``` > require 'pochette' > hex = "0100000001d11a6cc978fc41aaf5b24fc5c8ddde71fb91ffdba9579cd62ba20fc284b2446c000000008a47304402206d2f98829a9e5017ade2c084a8b821625c35aeaa633f718b1c348906afbe68b00220094cb8ee519adcebe866e655532abab818aa921144bd98a12491481931d2383a014104e318459c24b89c0928cec3c9c7842ae749dcca78673149179af9155c80f3763642989df3ffe34ab205d02e2efd07e9a34db2f00ed8b821dd5bb087ff64df2c9effffffff0280f0fa02000000001976a9149b754a70b9a3dbb64f65db01d164ef51101c18d788ac40aeeb02000000001976a914aadf5d54eda13070d39af72eb5ce40b1d3b8282588ac00000000" > backend = Pochette::Backends::BlockchainInfo.new > backend.pushtx(hex) => 'fb92420f73af6d25f5fab93435bc6b8ebfff3a07c02abd053f0923ae296fe380' ``` ## BitcoinCore backend Pochette will connect to your bitcoin-core node via JSON-RPC, using the [bitcoin-rpc gem](https://github.com/bitex-la/bitcoin-rpc) To properly use Pochette you need to be running your bitcoin node with setting the "-txindex=1" option to get a full transaction index. [Learn more about -txindex=1](http://bitcoin.stackexchange.com/questions/35707/what-are-pros-and-cons-of-txindex-option) Also, if you're creating new addresses and want bitcoin-core to track them you'll want to import them using the bitcoin-rpc gem, like so: ``` > BitcoinRpc::Client.new('http://user:pass@your_server').importaddress('1PUBLICADDRESS', '', false) ``` Setting up bitcoin-core as a backend can be done like this: ``` > Pochette.backend = Pochette::Backends::BitcoinCore.new('http://user:pass@your_server') ``` ## BlockchainInfo backend Pochette can use blockchain.info's public API to fetch unspent outputs, sleeping a bit after each request to prevent blockchain.info from banning your IP. This backend is probably the slowest one but also the one that's more convenient for testing and managing small wallets. This backend is not usable for testnet transactions, all queries will be done to the main network. You can create a blockchain.info backend like this ``` > Pochette::Backends::BlockchainInfo.new ``` The default cooldown time is 1 second after each request, but if you have a Blockchain.info API key you can configure your backend like so: ``` > Pochette::Backends::BlockchainInfo.cooldown = 0.1 # Make the cooldown a tenth of a second > Pochette.backend = Pochette::Backends::BlockchainInfo.new("your_api_key") ``` ## Toshi backend Pochette will connect to your Toshi node's postgres database directly. It's provided as a separate gem as it depends on the pg gem which needs local postgres extensions to work. You may need to add some extra indexes to your postgres to speed things up when using Pochette. [See the gem readme](https://github.com/bitex-la/pochette-toshi) for more info. ## Trendy Backend Pochette provides a higher level Backend Pochette::Backends::Trendy which chooses between a pool of available backends always using the one at the highest block height, (but biased towards using the incumbent backend). This is useful for automatic fallbacks and redundancy, you could also mix Toshi and Bitcoin-Core backends and use whatever looks more up to date. ``` > alpha = Pochette::Backends::BitcoinCore.new('http://user:pass@alpha_host') > beta = Pochette::Backends::BitcoinCore.new('http://user:pass@beta_host') > Pochette.backend = Pochette::Backends::Trendy.new([alpha, beta]) ``` ## Development After checking out the repo, run `bin/setup` to install dependencies. Then, run `bin/console` for an interactive prompt that will allow you to experiment. To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release` to create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org). ## Contributing 1. Fork it ( https://github.com/[my-github-username]/pochette/fork ) 2. Create your feature branch (`git checkout -b my-new-feature`) 3. Commit your changes (`git commit -am 'Add some feature'`) 4. Push to the branch (`git push origin my-new-feature`) 5. Create a new Pull Request