hydrate_btc_transactions.rb

 1#!/usr/bin/ruby
 2# frozen_string_literal: true
 3
 4# This reads the queue of "changed addresses" from electrum webhooks in the
 5# form "<address>/<customer_id>" and turns those into <tx_hash>/<address> =>
 6# customer_id keys for the bin/process_pending_btc_transactions script to run
 7# through and process more fully
 8#
 9# Usage: bin/process_pending-btc_transactions '{
10#        pidfile : Text,
11#        electrum : env:ELECTRUM_CONFIG,
12#        }'
13
14require "dhall"
15
16CONFIG =
17	Dhall::Coder
18	.new(safe: Dhall::Coder::JSON_LIKE + [Symbol, Proc])
19	.load(ARGV[0], transform_keys: :to_sym)
20
21require "redis"
22require_relative "../lib/electrum"
23require_relative "../lib/pidfile"
24
25REDIS = Redis.new
26ELECTRUM = Electrum.new(**CONFIG[:electrum])
27
28PIDFile.new(CONFIG[:pidfile]).lock do |pid|
29	loop do
30		key, value = REDIS.brpop("exciting_#{ELECTRUM.currency}_addrs", 600)
31
32		# Rewrite the pidfile so monit can see we're still alive
33		pid.refresh
34
35		# brpop allows blocking on multiple keys, and key tells us which one
36		# signalled but in this case we know which one, so just make sure it's
37		# not nil which means the timeout fired
38		next unless key
39
40		address, customer_id = value.split("/", 2)
41
42		txids =
43			ELECTRUM
44			.getaddresshistory(address)
45			.map { |item| "#{item['tx_hash']}/#{address}" }
46
47		next if txids.empty?
48
49		REDIS.hset(
50			"pending_#{ELECTRUM.currency}_transactions",
51			*txids.flat_map { |txid| [txid, customer_id] }
52		)
53	end
54end