1# frozen_string_literal: true
2
3require "bigdecimal"
4require "json"
5require "net/http"
6require "securerandom"
7
8class Electrum
9 def initialize(rpc_uri:, rpc_username:, rpc_password:)
10 @rpc_uri = URI(rpc_uri)
11 @rpc_username = rpc_username
12 @rpc_password = rpc_password
13 end
14
15 def getaddresshistory(address)
16 rpc_call(:getaddresshistory, address: address)["result"]
17 end
18
19 def gettransaction(tx_hash)
20 Transaction.new(self, tx_hash, rpc_call(
21 :deserialize,
22 [rpc_call(:gettransaction, txid: tx_hash)["result"]]
23 )["result"])
24 end
25
26 def get_tx_status(tx_hash)
27 rpc_call(:get_tx_status, txid: tx_hash)["result"]
28 end
29
30 class Transaction
31 def initialize(electrum, tx_hash, tx)
32 @electrum = electrum
33 @tx_hash = tx_hash
34 @tx = tx
35 end
36
37 def confirmations
38 @electrum.get_tx_status(@tx_hash)["confirmations"]
39 end
40
41 def amount_for(*addresses)
42 BigDecimal.new(
43 @tx["outputs"]
44 .select { |o| addresses.include?(o["address"]) }
45 .map { |o| o["value_sats"] }
46 .sum
47 ) * 0.00000001
48 end
49 end
50
51protected
52
53 def rpc_call(method, params)
54 JSON.parse(post_json(
55 jsonrpc: "2.0",
56 id: SecureRandom.hex,
57 method: method.to_s,
58 params: params
59 ).body)
60 end
61
62 def post_json(data)
63 req = Net::HTTP::Post.new(@rpc_uri, "Content-Type" => "application/json")
64 req.basic_auth(@rpc_username, @rpc_password)
65 req.body = data.to_json
66 Net::HTTP.start(
67 @rpc_uri.hostname,
68 @rpc_uri.port,
69 use_ssl: @rpc_uri.scheme == "https"
70 ) do |http|
71 http.request(req)
72 end
73 end
74end