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 def listaddresses
31 rpc_call(:listaddresses, {})["result"]
32 end
33
34 def notify(address, url)
35 rpc_call(:notify, address: address, URL: url)["result"]
36 end
37
38 class Transaction
39 def initialize(electrum, tx_hash, tx)
40 @electrum = electrum
41 @tx_hash = tx_hash
42 @tx = tx
43 end
44
45 def confirmations
46 @electrum.get_tx_status(@tx_hash)["confirmations"]
47 end
48
49 def amount_for(*addresses)
50 BigDecimal(
51 @tx["outputs"]
52 .select { |o| addresses.include?(o["address"]) }
53 .map { |o| o["value_sats"] }
54 .sum
55 ) * 0.00000001
56 end
57 end
58
59protected
60
61 def rpc_call(method, params)
62 JSON.parse(post_json(
63 jsonrpc: "2.0",
64 id: SecureRandom.hex,
65 method: method.to_s,
66 params: params
67 ).body)
68 end
69
70 def post_json_req(data)
71 req = Net::HTTP::Post.new(
72 @rpc_uri,
73 "Content-Type" => "application/json"
74 )
75 req.basic_auth(@rpc_username, @rpc_password)
76 req.body = data.to_json
77 req
78 end
79
80 def post_json(data)
81 Net::HTTP.start(
82 @rpc_uri.hostname,
83 @rpc_uri.port,
84 use_ssl: @rpc_uri.scheme == "https"
85 ) do |http|
86 http.request(post_json_req(data))
87 end
88 end
89end