# frozen_string_literal: true require "bigdecimal" require "json" require "net/http" require "securerandom" class Electrum def initialize(rpc_uri:, rpc_username:, rpc_password:) @rpc_uri = URI(rpc_uri) @rpc_username = rpc_username @rpc_password = rpc_password end def getaddresshistory(address) rpc_call(:getaddresshistory, address: address)["result"] end def gettransaction(tx_hash) Transaction.new(self, tx_hash, rpc_call( :deserialize, [rpc_call(:gettransaction, txid: tx_hash)["result"]] )["result"]) end def get_tx_status(tx_hash) rpc_call(:get_tx_status, txid: tx_hash)["result"] end def listaddresses rpc_call(:listaddresses, {})["result"] end def notify(address, url) rpc_call(:notify, address: address, URL: url)["result"] end class Transaction def initialize(electrum, tx_hash, tx) @electrum = electrum @tx_hash = tx_hash @tx = tx end def confirmations @electrum.get_tx_status(@tx_hash)["confirmations"] end def amount_for(*addresses) BigDecimal.new( @tx["outputs"] .select { |o| addresses.include?(o["address"]) } .map { |o| o["value_sats"] } .sum ) * 0.00000001 end end protected def rpc_call(method, params) JSON.parse(post_json( jsonrpc: "2.0", id: SecureRandom.hex, method: method.to_s, params: params ).body) end def post_json(data) req = Net::HTTP::Post.new(@rpc_uri, "Content-Type" => "application/json") req.basic_auth(@rpc_username, @rpc_password) req.body = data.to_json Net::HTTP.start( @rpc_uri.hostname, @rpc_uri.port, use_ssl: @rpc_uri.scheme == "https" ) do |http| http.request(req) end end end