utxoracle 0.0.2 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - data/.gitignore +1 -0
 - data/README.md +36 -7
 - data/bin/benchmarks/run +39 -0
 - data/bin/benchmarks/run_range +40 -0
 - data/bin/run +6 -6
 - data/bin/run_range +16 -0
 - data/lib/utxoracle/batch_oracle.rb +34 -0
 - data/lib/utxoracle/oracle.rb +9 -8
 - data/lib/utxoracle/provider.rb +2 -0
 - data/lib/utxoracle/providers/node.rb +2 -2
 - data/lib/utxoracle/version.rb +1 -1
 - data/lib/utxoracle.rb +1 -1
 - data/utxoracle.gemspec +2 -0
 - metadata +34 -4
 - data/lib/utxoracle/rpc.rb +0 -30
 - data/spec/utxoracle/rpc_spec.rb +0 -34
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA256:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 27c98fbe262713835893d7590648c0e566ac35cf837d5c1b6514961b54c99324
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 8cf05e364850de7f330a4c833640d58c69b8a0c048aaec4fbaa8f4dbe54b529c
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 932541e0474fbdbe9515629cfa7f4f4b35a1a04b4f993fc21542b063f46f1273bf66b77cc91c457301af2f81fe95bd782ec0c31bd16d8060b4509f870e1806a6
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: dcabd03dcf97198240167c5ad9449345340c85f49b39f31e80a77cab3ba4a5c68f02736a8d09c988246af34ea2a35238795a3a7b4b3cd4bcdad38ef4a36310e8
         
     | 
    
        data/.gitignore
    CHANGED
    
    
    
        data/README.md
    CHANGED
    
    | 
         @@ -44,29 +44,58 @@ All examples below assume that the gem has been required. 
     | 
|
| 
       44 
44 
     | 
    
         
             
            require 'utxoracle'
         
     | 
| 
       45 
45 
     | 
    
         
             
            ```
         
     | 
| 
       46 
46 
     | 
    
         | 
| 
       47 
     | 
    
         
            -
             
     | 
| 
       48 
47 
     | 
    
         
             
            ### Fetching price
         
     | 
| 
       49 
48 
     | 
    
         | 
| 
       50 
49 
     | 
    
         
             
            #### Using a specific bitcoin node
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
            `bitcoin.conf` would look like:
         
     | 
| 
      
 52 
     | 
    
         
            +
            ```txt
         
     | 
| 
      
 53 
     | 
    
         
            +
            server=1
         
     | 
| 
      
 54 
     | 
    
         
            +
            rpcuser=aUser
         
     | 
| 
      
 55 
     | 
    
         
            +
            rpcpassword=aPassword
         
     | 
| 
      
 56 
     | 
    
         
            +
            ```
         
     | 
| 
       51 
57 
     | 
    
         
             
            ```ruby
         
     | 
| 
       52 
58 
     | 
    
         
             
            provider = Utxoracle::Node.new("aUser", "aPassword", "127.0.0.1", 8332)
         
     | 
| 
      
 59 
     | 
    
         
            +
            oracle = Utxoracle::Oracle.new(provider, log = false)
         
     | 
| 
      
 60 
     | 
    
         
            +
            oracle.price("2023-10-30")
         
     | 
| 
      
 61 
     | 
    
         
            +
            34840
         
     | 
| 
       53 
62 
     | 
    
         
             
            ```
         
     | 
| 
       54 
63 
     | 
    
         | 
| 
       55 
64 
     | 
    
         
             
            #### Using mempool.space node
         
     | 
| 
       56 
     | 
    
         
            -
            ```ruby
         
     | 
| 
       57 
     | 
    
         
            -
            provider = Utxoracle::Mempool.new
         
     | 
| 
       58 
     | 
    
         
            -
            ```
         
     | 
| 
       59 
65 
     | 
    
         | 
| 
       60 
     | 
    
         
            -
            ####
         
     | 
| 
       61 
66 
     | 
    
         
             
            ```ruby
         
     | 
| 
       62 
     | 
    
         
            -
             
     | 
| 
      
 67 
     | 
    
         
            +
            # Mempool will throttle you without an enterprise license
         
     | 
| 
      
 68 
     | 
    
         
            +
            provider = Utxoracle::Mempool.new
         
     | 
| 
      
 69 
     | 
    
         
            +
            oracle = Utxoracle::Oracle.new(provider, log = false)
         
     | 
| 
       63 
70 
     | 
    
         
             
            oracle.price("2023-10-30")
         
     | 
| 
       64 
71 
     | 
    
         
             
            34840
         
     | 
| 
       65 
72 
     | 
    
         
             
            ```
         
     | 
| 
       66 
73 
     | 
    
         | 
| 
      
 74 
     | 
    
         
            +
            ### Command line usage
         
     | 
| 
      
 75 
     | 
    
         
            +
            ```bash
         
     | 
| 
      
 76 
     | 
    
         
            +
            $ ./bin/run aUser aPassword 127.0.0.1 8332 2023-10-10
         
     | 
| 
      
 77 
     | 
    
         
            +
            Reading all blocks on 2023-10-12 00:00:00 -0400...
         
     | 
| 
      
 78 
     | 
    
         
            +
            This will take a few minutes (~144 blocks)...
         
     | 
| 
      
 79 
     | 
    
         
            +
            Height  Time(utc)       Completion %
         
     | 
| 
      
 80 
     | 
    
         
            +
            811769  00:18:31        1.25
         
     | 
| 
      
 81 
     | 
    
         
            +
            811770  00:22:48        1.53
         
     | 
| 
      
 82 
     | 
    
         
            +
            811771  00:24:24        1.67
         
     | 
| 
      
 83 
     | 
    
         
            +
            811772  00:33:32        2.29
         
     | 
| 
      
 84 
     | 
    
         
            +
            811773  00:38:14        2.64
         
     | 
| 
      
 85 
     | 
    
         
            +
            811774  01:06:40        4.58
         
     | 
| 
      
 86 
     | 
    
         
            +
            811775  01:09:07        4.79
         
     | 
| 
      
 87 
     | 
    
         
            +
            ...
         
     | 
| 
      
 88 
     | 
    
         
            +
            811931  23:41:09        98.68
         
     | 
| 
      
 89 
     | 
    
         
            +
            811932  23:44:01        98.89
         
     | 
| 
      
 90 
     | 
    
         
            +
            811933  23:48:40        99.17
         
     | 
| 
      
 91 
     | 
    
         
            +
            blocks_on_this_day: 165
         
     | 
| 
      
 92 
     | 
    
         
            +
            Price Estimate: $27,045
         
     | 
| 
      
 93 
     | 
    
         
            +
            ```
         
     | 
| 
      
 94 
     | 
    
         
            +
             
     | 
| 
      
 95 
     | 
    
         
            +
             
     | 
| 
       67 
96 
     | 
    
         
             
            ## Development
         
     | 
| 
       68 
97 
     | 
    
         | 
| 
       69 
     | 
    
         
            -
            After checking out the repo, run `bundle  
     | 
| 
      
 98 
     | 
    
         
            +
            After checking out the repo, run `bundle install` to install dependencies.
         
     | 
| 
       70 
99 
     | 
    
         | 
| 
       71 
100 
     | 
    
         
             
            To install this gem onto your local machine, run `bundle exec rake install`.
         
     | 
| 
       72 
101 
     | 
    
         | 
    
        data/bin/benchmarks/run
    ADDED
    
    | 
         @@ -0,0 +1,39 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #!/usr/bin/env ruby
         
     | 
| 
      
 2 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            # This is a copy of bin/run but with timing code.
         
     | 
| 
      
 5 
     | 
    
         
            +
            # Usage:
         
     | 
| 
      
 6 
     | 
    
         
            +
            #
         
     | 
| 
      
 7 
     | 
    
         
            +
            # Basic wall clock measurement:
         
     | 
| 
      
 8 
     | 
    
         
            +
            # $ ./bin/benchmarks/run aUser aPassword 127.0.0.1 8332 2023-10-01
         
     | 
| 
      
 9 
     | 
    
         
            +
            #
         
     | 
| 
      
 10 
     | 
    
         
            +
            # With StackProf measurement:
         
     | 
| 
      
 11 
     | 
    
         
            +
            # ./bin/benchmarks/run aUser aPassword 127.0.0.1 8332 2023-10-01 true
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            require 'bundler/setup'
         
     | 
| 
      
 14 
     | 
    
         
            +
            require 'utxoracle'
         
     | 
| 
      
 15 
     | 
    
         
            +
            require 'benchmark'
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
            user        = ARGV[0]
         
     | 
| 
      
 18 
     | 
    
         
            +
            password    = ARGV[1]
         
     | 
| 
      
 19 
     | 
    
         
            +
            ip          = ARGV[2]
         
     | 
| 
      
 20 
     | 
    
         
            +
            port        = ARGV[3]
         
     | 
| 
      
 21 
     | 
    
         
            +
            date        = ARGV[4]
         
     | 
| 
      
 22 
     | 
    
         
            +
            profile     = ARGV[5]
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
            if profile
         
     | 
| 
      
 25 
     | 
    
         
            +
              require 'stackprof'
         
     | 
| 
      
 26 
     | 
    
         
            +
              # See https://github.com/tmm1/stackprof#sampling: for :cpu, :wall, :object
         
     | 
| 
      
 27 
     | 
    
         
            +
              StackProf.run(mode: :wall, out: 'tmp/stackprof-wall.dump', raw: true) do
         
     | 
| 
      
 28 
     | 
    
         
            +
                provider = Utxoracle::Node.new(user, password, ip, port)
         
     | 
| 
      
 29 
     | 
    
         
            +
                oracle = Utxoracle::Oracle.new(provider, log = false)
         
     | 
| 
      
 30 
     | 
    
         
            +
                puts oracle.price(date)
         
     | 
| 
      
 31 
     | 
    
         
            +
              end
         
     | 
| 
      
 32 
     | 
    
         
            +
            else
         
     | 
| 
      
 33 
     | 
    
         
            +
              time = Benchmark.measure do
         
     | 
| 
      
 34 
     | 
    
         
            +
                provider = Utxoracle::Node.new(user, password, ip, port)
         
     | 
| 
      
 35 
     | 
    
         
            +
                oracle = Utxoracle::Oracle.new(provider, log = false)
         
     | 
| 
      
 36 
     | 
    
         
            +
                puts oracle.price(date)
         
     | 
| 
      
 37 
     | 
    
         
            +
              end
         
     | 
| 
      
 38 
     | 
    
         
            +
              puts time
         
     | 
| 
      
 39 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,40 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #!/usr/bin/env ruby
         
     | 
| 
      
 2 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            # This is a copy of bin/run_range but with timing code.
         
     | 
| 
      
 5 
     | 
    
         
            +
            # Usage:
         
     | 
| 
      
 6 
     | 
    
         
            +
            #
         
     | 
| 
      
 7 
     | 
    
         
            +
            # ./bin/benchmarks/run_range aUser aPassword 127.0.0.1 8332 2023-10-01 2023-10-05
         
     | 
| 
      
 8 
     | 
    
         
            +
            #
         
     | 
| 
      
 9 
     | 
    
         
            +
            # Note: Too long of a range will crash the program.
         
     | 
| 
      
 10 
     | 
    
         
            +
            # Bitcoin Core has limits:
         
     | 
| 
      
 11 
     | 
    
         
            +
            # https://github.com/bitcoin/bitcoin/blob/c0ddd32bf629bb48426b0651def497ca1a78e6b1/src/httpserver.h#L12-L14
         
     | 
| 
      
 12 
     | 
    
         
            +
            # for threads, queue and timeout.
         
     | 
| 
      
 13 
     | 
    
         
            +
            #
         
     | 
| 
      
 14 
     | 
    
         
            +
            # With default settings, 20 days works fine.
         
     | 
| 
      
 15 
     | 
    
         
            +
            #
         
     | 
| 
      
 16 
     | 
    
         
            +
            # To run for a full month, I've found the following settings to work fine:
         
     | 
| 
      
 17 
     | 
    
         
            +
            #
         
     | 
| 
      
 18 
     | 
    
         
            +
            # rpcworkqueue=32
         
     | 
| 
      
 19 
     | 
    
         
            +
            # rpcthreads=16
         
     | 
| 
      
 20 
     | 
    
         
            +
            # rpctimeout=60
         
     | 
| 
      
 21 
     | 
    
         
            +
            # Database cache 1024 MiB
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
            require 'bundler/setup'
         
     | 
| 
      
 24 
     | 
    
         
            +
            require 'utxoracle'
         
     | 
| 
      
 25 
     | 
    
         
            +
            require 'benchmark'
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
            user        = ARGV[0]
         
     | 
| 
      
 28 
     | 
    
         
            +
            password    = ARGV[1]
         
     | 
| 
      
 29 
     | 
    
         
            +
            ip          = ARGV[2]
         
     | 
| 
      
 30 
     | 
    
         
            +
            port        = ARGV[3]
         
     | 
| 
      
 31 
     | 
    
         
            +
            start_date  = ARGV[4]
         
     | 
| 
      
 32 
     | 
    
         
            +
            end_date    = ARGV[5]
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
            time = Benchmark.measure do
         
     | 
| 
      
 35 
     | 
    
         
            +
              provider = Utxoracle::Node.new(user, password, ip, port)
         
     | 
| 
      
 36 
     | 
    
         
            +
              batch_oracle = Utxoracle::BatchOracle.new(provider)
         
     | 
| 
      
 37 
     | 
    
         
            +
              batch_oracle.prices(start_date, end_date)
         
     | 
| 
      
 38 
     | 
    
         
            +
            end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
            puts time.real
         
     | 
    
        data/bin/run
    CHANGED
    
    | 
         @@ -4,12 +4,12 @@ 
     | 
|
| 
       4 
4 
     | 
    
         
             
            require 'bundler/setup'
         
     | 
| 
       5 
5 
     | 
    
         
             
            require 'utxoracle'
         
     | 
| 
       6 
6 
     | 
    
         | 
| 
       7 
     | 
    
         
            -
            user 
     | 
| 
       8 
     | 
    
         
            -
            password 
     | 
| 
       9 
     | 
    
         
            -
            ip 
     | 
| 
       10 
     | 
    
         
            -
            port 
     | 
| 
       11 
     | 
    
         
            -
            date 
     | 
| 
      
 7 
     | 
    
         
            +
            user      = ARGV[0]
         
     | 
| 
      
 8 
     | 
    
         
            +
            password  = ARGV[1]
         
     | 
| 
      
 9 
     | 
    
         
            +
            ip        = ARGV[2]
         
     | 
| 
      
 10 
     | 
    
         
            +
            port      = ARGV[3]
         
     | 
| 
      
 11 
     | 
    
         
            +
            date      = ARGV[4]
         
     | 
| 
       12 
12 
     | 
    
         | 
| 
       13 
13 
     | 
    
         
             
            provider = Utxoracle::Node.new(user, password, ip, port)
         
     | 
| 
       14 
     | 
    
         
            -
            oracle = Utxoracle::Oracle.new(provider, true)
         
     | 
| 
      
 14 
     | 
    
         
            +
            oracle = Utxoracle::Oracle.new(provider, log = true)
         
     | 
| 
       15 
15 
     | 
    
         
             
            oracle.price(date)
         
     | 
    
        data/bin/run_range
    ADDED
    
    | 
         @@ -0,0 +1,16 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #!/usr/bin/env ruby
         
     | 
| 
      
 2 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            require 'bundler/setup'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require 'utxoracle'
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            user        = ARGV[0]
         
     | 
| 
      
 8 
     | 
    
         
            +
            password    = ARGV[1]
         
     | 
| 
      
 9 
     | 
    
         
            +
            ip          = ARGV[2]
         
     | 
| 
      
 10 
     | 
    
         
            +
            port        = ARGV[3]
         
     | 
| 
      
 11 
     | 
    
         
            +
            start_date  = ARGV[4]
         
     | 
| 
      
 12 
     | 
    
         
            +
            end_date    = ARGV[5]
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
            provider = Utxoracle::Node.new(user, password, ip, port)
         
     | 
| 
      
 15 
     | 
    
         
            +
            batch_oracle = Utxoracle::BatchOracle.new(provider)
         
     | 
| 
      
 16 
     | 
    
         
            +
            batch_oracle.prices(start_date, end_date)
         
     | 
| 
         @@ -0,0 +1,34 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Utxoracle
         
     | 
| 
      
 4 
     | 
    
         
            +
              class BatchOracle
         
     | 
| 
      
 5 
     | 
    
         
            +
                def initialize(provider, log = false)
         
     | 
| 
      
 6 
     | 
    
         
            +
                  @provider   = provider
         
     | 
| 
      
 7 
     | 
    
         
            +
                  @log        = log
         
     | 
| 
      
 8 
     | 
    
         
            +
                end
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                def prices(start_date, end_date)
         
     | 
| 
      
 11 
     | 
    
         
            +
                  formatted_start_date  = Time.parse start_date.tr('\n', '')
         
     | 
| 
      
 12 
     | 
    
         
            +
                  formatted_end_date    = Time.parse end_date.tr('\n', '')
         
     | 
| 
      
 13 
     | 
    
         
            +
                  ret                   = {}
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                  date = formatted_start_date
         
     | 
| 
      
 16 
     | 
    
         
            +
                  threads = []
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                  while date < formatted_end_date
         
     | 
| 
      
 19 
     | 
    
         
            +
                    # Bind `date` to thread scope: https://ruby-doc.org/core-2.0.0/Thread.html#method-c-new
         
     | 
| 
      
 20 
     | 
    
         
            +
                    threads << Thread.new(date) do |t_date|
         
     | 
| 
      
 21 
     | 
    
         
            +
                      oracle = Utxoracle::Oracle.new(@provider, log = @log)
         
     | 
| 
      
 22 
     | 
    
         
            +
                      date_str = t_date.to_s[0..9]
         
     | 
| 
      
 23 
     | 
    
         
            +
                      ret[date_str] = oracle.price(date_str)
         
     | 
| 
      
 24 
     | 
    
         
            +
                    end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                    date += Utxoracle::Oracle::SECONDS_PER_DAY
         
     | 
| 
      
 27 
     | 
    
         
            +
                  end
         
     | 
| 
      
 28 
     | 
    
         
            +
                  threads.each(&:join)
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                  puts ret
         
     | 
| 
      
 31 
     | 
    
         
            +
                  ret
         
     | 
| 
      
 32 
     | 
    
         
            +
                end
         
     | 
| 
      
 33 
     | 
    
         
            +
              end
         
     | 
| 
      
 34 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/utxoracle/oracle.rb
    CHANGED
    
    | 
         @@ -1,9 +1,10 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
       1 
3 
     | 
    
         
             
            require 'time'
         
     | 
| 
       2 
     | 
    
         
            -
            require_relative 'rpc'
         
     | 
| 
       3 
4 
     | 
    
         | 
| 
       4 
5 
     | 
    
         
             
            module Utxoracle
         
     | 
| 
       5 
6 
     | 
    
         
             
              class Oracle
         
     | 
| 
       6 
     | 
    
         
            -
                 
     | 
| 
      
 7 
     | 
    
         
            +
                SECONDS_PER_DAY       = 86_400
         
     | 
| 
       7 
8 
     | 
    
         
             
                FOUR_HOURS            = 14_400
         
     | 
| 
       8 
9 
     | 
    
         
             
                MAINNET_PORT          = 8332
         
     | 
| 
       9 
10 
     | 
    
         
             
                TESTNET_PORT          = 18_332
         
     | 
| 
         @@ -25,7 +26,7 @@ module Utxoracle 
     | 
|
| 
       25 
26 
     | 
    
         
             
                  end
         
     | 
| 
       26 
27 
     | 
    
         | 
| 
       27 
28 
     | 
    
         
             
                  if price_estimate = @cache[requested_date]
         
     | 
| 
       28 
     | 
    
         
            -
                    puts " 
     | 
| 
      
 29 
     | 
    
         
            +
                    puts "Price Estimate: $#{price_estimate.to_s.reverse.gsub(/(\d{3})(?=\d)/, '\\1,').reverse}" if @log
         
     | 
| 
       29 
30 
     | 
    
         
             
                    return price_estimate
         
     | 
| 
       30 
31 
     | 
    
         
             
                  end
         
     | 
| 
       31 
32 
     | 
    
         | 
| 
         @@ -52,7 +53,7 @@ module Utxoracle 
     | 
|
| 
       52 
53 
     | 
    
         
             
                  latest_utc_midnight = Time.new(latest_year, latest_month, latest_day).utc
         
     | 
| 
       53 
54 
     | 
    
         | 
| 
       54 
55 
     | 
    
         
             
                  latest_time_in_seconds = blockheader['time']
         
     | 
| 
       55 
     | 
    
         
            -
                  yesterday_seconds = latest_time_in_seconds -  
     | 
| 
      
 56 
     | 
    
         
            +
                  yesterday_seconds = latest_time_in_seconds - SECONDS_PER_DAY
         
     | 
| 
       56 
57 
     | 
    
         
             
                  latest_price_day = Time.at(yesterday_seconds).utc
         
     | 
| 
       57 
58 
     | 
    
         
             
                  latest_price_date = latest_price_day.utc.strftime('%Y-%m-%d')
         
     | 
| 
       58 
59 
     | 
    
         | 
| 
         @@ -60,7 +61,7 @@ module Utxoracle 
     | 
|
| 
       60 
61 
     | 
    
         
             
                  price_day_date_utc = @requested_date
         
     | 
| 
       61 
62 
     | 
    
         | 
| 
       62 
63 
     | 
    
         
             
                  seconds_since_price_day = latest_time_in_seconds - price_day_seconds
         
     | 
| 
       63 
     | 
    
         
            -
                  blocks_ago_estimate = (144 * seconds_since_price_day.to_f /  
     | 
| 
      
 64 
     | 
    
         
            +
                  blocks_ago_estimate = (144 * seconds_since_price_day.to_f / SECONDS_PER_DAY.to_f).round
         
     | 
| 
       64 
65 
     | 
    
         
             
                  price_day_block_estimate = (block_count - blocks_ago_estimate).to_i
         
     | 
| 
       65 
66 
     | 
    
         | 
| 
       66 
67 
     | 
    
         
             
                  block_hash_b       = @provider.getblockhash(price_day_block_estimate)
         
     | 
| 
         @@ -68,7 +69,7 @@ module Utxoracle 
     | 
|
| 
       68 
69 
     | 
    
         
             
                  time_in_seconds = block_header['time']
         
     | 
| 
       69 
70 
     | 
    
         | 
| 
       70 
71 
     | 
    
         
             
                  seconds_difference = time_in_seconds - price_day_seconds
         
     | 
| 
       71 
     | 
    
         
            -
                  block_jump_estimate = (144.0 * seconds_difference /  
     | 
| 
      
 72 
     | 
    
         
            +
                  block_jump_estimate = (144.0 * seconds_difference / SECONDS_PER_DAY).round
         
     | 
| 
       72 
73 
     | 
    
         | 
| 
       73 
74 
     | 
    
         
             
                  last_estimate = 0
         
     | 
| 
       74 
75 
     | 
    
         
             
                  last_last_estimate = 0
         
     | 
| 
         @@ -82,7 +83,7 @@ module Utxoracle 
     | 
|
| 
       82 
83 
     | 
    
         | 
| 
       83 
84 
     | 
    
         
             
                    time_in_seconds = block_header['time']
         
     | 
| 
       84 
85 
     | 
    
         
             
                    seconds_difference = time_in_seconds - price_day_seconds
         
     | 
| 
       85 
     | 
    
         
            -
                    block_jump_estimate = (144.0 * seconds_difference /  
     | 
| 
      
 86 
     | 
    
         
            +
                    block_jump_estimate = (144.0 * seconds_difference / SECONDS_PER_DAY).round
         
     | 
| 
       86 
87 
     | 
    
         
             
                  end
         
     | 
| 
       87 
88 
     | 
    
         | 
| 
       88 
89 
     | 
    
         
             
                  if time_in_seconds > price_day_seconds
         
     | 
| 
         @@ -261,7 +262,7 @@ module Utxoracle 
     | 
|
| 
       261 
262 
     | 
    
         
             
                  w2 = a2 / (a1 + a2)
         
     | 
| 
       262 
263 
     | 
    
         
             
                  price_estimate = (w1 * btc_in_usd_best + w2 * btc_in_usd_2nd).to_i
         
     | 
| 
       263 
264 
     | 
    
         | 
| 
       264 
     | 
    
         
            -
                  puts " 
     | 
| 
      
 265 
     | 
    
         
            +
                  puts "Price Estimate: $#{price_estimate.to_s.reverse.gsub(/(\d{3})(?=\d)/, '\\1,').reverse}" if @log
         
     | 
| 
       265 
266 
     | 
    
         | 
| 
       266 
267 
     | 
    
         
             
                  price_estimate
         
     | 
| 
       267 
268 
     | 
    
         
             
                end
         
     | 
    
        data/lib/utxoracle/provider.rb
    CHANGED
    
    
| 
         @@ -1,10 +1,10 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            require_relative '../provider'
         
     | 
| 
       2 
     | 
    
         
            -
             
     | 
| 
      
 2 
     | 
    
         
            +
            require 'cleanrpc'
         
     | 
| 
       3 
3 
     | 
    
         | 
| 
       4 
4 
     | 
    
         
             
            module Utxoracle
         
     | 
| 
       5 
5 
     | 
    
         
             
              class Node < Provider
         
     | 
| 
       6 
6 
     | 
    
         
             
                def initialize(rpcuser, rpcpassword, ip, port)
         
     | 
| 
       7 
     | 
    
         
            -
                  @rpc = Rpc.new("http://#{rpcuser}:#{rpcpassword}@#{ip}:#{port}")
         
     | 
| 
      
 7 
     | 
    
         
            +
                  @rpc = Cleanrpc::Rpc.new("http://#{rpcuser}:#{rpcpassword}@#{ip}:#{port}")
         
     | 
| 
       8 
8 
     | 
    
         
             
                end
         
     | 
| 
       9 
9 
     | 
    
         | 
| 
       10 
10 
     | 
    
         
             
                def getblockcount
         
     | 
    
        data/lib/utxoracle/version.rb
    CHANGED
    
    
    
        data/lib/utxoracle.rb
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # frozen_string_literal: true
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
     | 
    
         
            -
            require_relative 'utxoracle/rpc'
         
     | 
| 
       4 
3 
     | 
    
         
             
            require_relative 'utxoracle/version'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require_relative 'utxoracle/batch_oracle'
         
     | 
| 
       5 
5 
     | 
    
         
             
            require_relative 'utxoracle/oracle'
         
     | 
| 
       6 
6 
     | 
    
         
             
            require_relative 'utxoracle/providers/mempool'
         
     | 
| 
       7 
7 
     | 
    
         
             
            require_relative 'utxoracle/providers/node'
         
     | 
    
        data/utxoracle.gemspec
    CHANGED
    
    | 
         @@ -21,6 +21,7 @@ Gem::Specification.new do |spec| 
     | 
|
| 
       21 
21 
     | 
    
         
             
              spec.bindir                 = 'bin'
         
     | 
| 
       22 
22 
     | 
    
         
             
              spec.require_path           = 'lib'
         
     | 
| 
       23 
23 
     | 
    
         | 
| 
      
 24 
     | 
    
         
            +
              spec.add_dependency 'cleanrpc', '~> 0.0.2'
         
     | 
| 
       24 
25 
     | 
    
         
             
              spec.add_dependency 'typhoeus', '~> 1.4.0'
         
     | 
| 
       25 
26 
     | 
    
         | 
| 
       26 
27 
     | 
    
         
             
              spec.add_development_dependency 'pry'
         
     | 
| 
         @@ -30,4 +31,5 @@ Gem::Specification.new do |spec| 
     | 
|
| 
       30 
31 
     | 
    
         
             
              spec.add_development_dependency 'rubocop-rspec'
         
     | 
| 
       31 
32 
     | 
    
         
             
              spec.add_development_dependency 'simplecov'
         
     | 
| 
       32 
33 
     | 
    
         
             
              spec.add_development_dependency 'simplecov-console'
         
     | 
| 
      
 34 
     | 
    
         
            +
              spec.add_development_dependency 'stackprof'
         
     | 
| 
       33 
35 
     | 
    
         
             
            end
         
     | 
    
        metadata
    CHANGED
    
    | 
         @@ -1,15 +1,29 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            --- !ruby/object:Gem::Specification
         
     | 
| 
       2 
2 
     | 
    
         
             
            name: utxoracle
         
     | 
| 
       3 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version
         
     | 
| 
       4 
     | 
    
         
            -
              version: 0.0 
     | 
| 
      
 4 
     | 
    
         
            +
              version: 0.1.0
         
     | 
| 
       5 
5 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       6 
6 
     | 
    
         
             
            authors:
         
     | 
| 
       7 
7 
     | 
    
         
             
            - Keith Gardner
         
     | 
| 
       8 
8 
     | 
    
         
             
            autorequire:
         
     | 
| 
       9 
9 
     | 
    
         
             
            bindir: bin
         
     | 
| 
       10 
10 
     | 
    
         
             
            cert_chain: []
         
     | 
| 
       11 
     | 
    
         
            -
            date: 2023-11- 
     | 
| 
      
 11 
     | 
    
         
            +
            date: 2023-11-08 00:00:00.000000000 Z
         
     | 
| 
       12 
12 
     | 
    
         
             
            dependencies:
         
     | 
| 
      
 13 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 14 
     | 
    
         
            +
              name: cleanrpc
         
     | 
| 
      
 15 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 16 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 17 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 18 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 19 
     | 
    
         
            +
                    version: 0.0.2
         
     | 
| 
      
 20 
     | 
    
         
            +
              type: :runtime
         
     | 
| 
      
 21 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 22 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 23 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 24 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 25 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 26 
     | 
    
         
            +
                    version: 0.0.2
         
     | 
| 
       13 
27 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       14 
28 
     | 
    
         
             
              name: typhoeus
         
     | 
| 
       15 
29 
     | 
    
         
             
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
         @@ -122,6 +136,20 @@ dependencies: 
     | 
|
| 
       122 
136 
     | 
    
         
             
                - - ">="
         
     | 
| 
       123 
137 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       124 
138 
     | 
    
         
             
                    version: '0'
         
     | 
| 
      
 139 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 140 
     | 
    
         
            +
              name: stackprof
         
     | 
| 
      
 141 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 142 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 143 
     | 
    
         
            +
                - - ">="
         
     | 
| 
      
 144 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 145 
     | 
    
         
            +
                    version: '0'
         
     | 
| 
      
 146 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 147 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 148 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 149 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 150 
     | 
    
         
            +
                - - ">="
         
     | 
| 
      
 151 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 152 
     | 
    
         
            +
                    version: '0'
         
     | 
| 
       125 
153 
     | 
    
         
             
            description: Offline price oracle for Bitcoin. Offers programmable data providers
         
     | 
| 
       126 
154 
     | 
    
         
             
              (Bitcoin node, mempool, etc). Can be used from commandline, or integrated into existing
         
     | 
| 
       127 
155 
     | 
    
         
             
              ruby stacks.
         
     | 
| 
         @@ -136,19 +164,21 @@ files: 
     | 
|
| 
       136 
164 
     | 
    
         
             
            - LICENSE
         
     | 
| 
       137 
165 
     | 
    
         
             
            - README.md
         
     | 
| 
       138 
166 
     | 
    
         
             
            - Rakefile
         
     | 
| 
      
 167 
     | 
    
         
            +
            - bin/benchmarks/run
         
     | 
| 
      
 168 
     | 
    
         
            +
            - bin/benchmarks/run_range
         
     | 
| 
       139 
169 
     | 
    
         
             
            - bin/console
         
     | 
| 
       140 
170 
     | 
    
         
             
            - bin/run
         
     | 
| 
      
 171 
     | 
    
         
            +
            - bin/run_range
         
     | 
| 
       141 
172 
     | 
    
         
             
            - lib/utxoracle.rb
         
     | 
| 
      
 173 
     | 
    
         
            +
            - lib/utxoracle/batch_oracle.rb
         
     | 
| 
       142 
174 
     | 
    
         
             
            - lib/utxoracle/oracle.rb
         
     | 
| 
       143 
175 
     | 
    
         
             
            - lib/utxoracle/provider.rb
         
     | 
| 
       144 
176 
     | 
    
         
             
            - lib/utxoracle/providers/mempool.rb
         
     | 
| 
       145 
177 
     | 
    
         
             
            - lib/utxoracle/providers/node.rb
         
     | 
| 
       146 
178 
     | 
    
         
             
            - lib/utxoracle/request.rb
         
     | 
| 
       147 
     | 
    
         
            -
            - lib/utxoracle/rpc.rb
         
     | 
| 
       148 
179 
     | 
    
         
             
            - lib/utxoracle/version.rb
         
     | 
| 
       149 
180 
     | 
    
         
             
            - spec/spec_helper.rb
         
     | 
| 
       150 
181 
     | 
    
         
             
            - spec/utxoracle/oracle_spec.rb
         
     | 
| 
       151 
     | 
    
         
            -
            - spec/utxoracle/rpc_spec.rb
         
     | 
| 
       152 
182 
     | 
    
         
             
            - spec/utxoracle_spec.rb
         
     | 
| 
       153 
183 
     | 
    
         
             
            - utxoracle.gemspec
         
     | 
| 
       154 
184 
     | 
    
         
             
            homepage: https://github.com/Carolina-Bitcoin-Project/UTXOracle
         
     | 
    
        data/lib/utxoracle/rpc.rb
    DELETED
    
    | 
         @@ -1,30 +0,0 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            require 'net/http'
         
     | 
| 
       2 
     | 
    
         
            -
            require 'uri'
         
     | 
| 
       3 
     | 
    
         
            -
            require 'json'
         
     | 
| 
       4 
     | 
    
         
            -
             
     | 
| 
       5 
     | 
    
         
            -
            module Utxoracle
         
     | 
| 
       6 
     | 
    
         
            -
              class Rpc
         
     | 
| 
       7 
     | 
    
         
            -
                def initialize(service_url)
         
     | 
| 
       8 
     | 
    
         
            -
                  @uri = URI.parse(service_url)
         
     | 
| 
       9 
     | 
    
         
            -
                end
         
     | 
| 
       10 
     | 
    
         
            -
             
     | 
| 
       11 
     | 
    
         
            -
                def method_missing(name, *args)
         
     | 
| 
       12 
     | 
    
         
            -
                  post_body = { 'method' => name, 'params' => args, 'id' => 'jsonrpc' }.to_json
         
     | 
| 
       13 
     | 
    
         
            -
                  resp = JSON.parse(http_post_request(post_body))
         
     | 
| 
       14 
     | 
    
         
            -
                  raise JSONRPCError, resp['error'] if resp['error']
         
     | 
| 
       15 
     | 
    
         
            -
             
     | 
| 
       16 
     | 
    
         
            -
                  resp['result']
         
     | 
| 
       17 
     | 
    
         
            -
                end
         
     | 
| 
       18 
     | 
    
         
            -
             
     | 
| 
       19 
     | 
    
         
            -
                def http_post_request(post_body)
         
     | 
| 
       20 
     | 
    
         
            -
                  http    = Net::HTTP.new(@uri.host, @uri.port)
         
     | 
| 
       21 
     | 
    
         
            -
                  request = Net::HTTP::Post.new(@uri.request_uri)
         
     | 
| 
       22 
     | 
    
         
            -
                  request.basic_auth @uri.user, @uri.password
         
     | 
| 
       23 
     | 
    
         
            -
                  request.content_type = 'application/json'
         
     | 
| 
       24 
     | 
    
         
            -
                  request.body = post_body
         
     | 
| 
       25 
     | 
    
         
            -
                  http.request(request).body
         
     | 
| 
       26 
     | 
    
         
            -
                end
         
     | 
| 
       27 
     | 
    
         
            -
             
     | 
| 
       28 
     | 
    
         
            -
                class JSONRPCError < RuntimeError; end
         
     | 
| 
       29 
     | 
    
         
            -
              end
         
     | 
| 
       30 
     | 
    
         
            -
            end
         
     | 
    
        data/spec/utxoracle/rpc_spec.rb
    DELETED
    
    | 
         @@ -1,34 +0,0 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            # frozen_string_literal: true
         
     | 
| 
       2 
     | 
    
         
            -
             
     | 
| 
       3 
     | 
    
         
            -
            require 'spec_helper'
         
     | 
| 
       4 
     | 
    
         
            -
             
     | 
| 
       5 
     | 
    
         
            -
            RSpec.describe Utxoracle::Rpc do
         
     | 
| 
       6 
     | 
    
         
            -
              let(:rpc) do
         
     | 
| 
       7 
     | 
    
         
            -
                described_class.new('http://foo:bar@127.0.0.1:8332')
         
     | 
| 
       8 
     | 
    
         
            -
              end
         
     | 
| 
       9 
     | 
    
         
            -
             
     | 
| 
       10 
     | 
    
         
            -
              describe '.new' do
         
     | 
| 
       11 
     | 
    
         
            -
                it 'creates an instance of Rpc with given uri' do
         
     | 
| 
       12 
     | 
    
         
            -
                  expect(rpc.class).to eq(Utxoracle::Rpc)
         
     | 
| 
       13 
     | 
    
         
            -
                end
         
     | 
| 
       14 
     | 
    
         
            -
              end
         
     | 
| 
       15 
     | 
    
         
            -
             
     | 
| 
       16 
     | 
    
         
            -
              it 'exposes http request interface' do
         
     | 
| 
       17 
     | 
    
         
            -
                allow(rpc).to receive(:http_post_request).and_return(true)
         
     | 
| 
       18 
     | 
    
         
            -
                expect(rpc.http_post_request('')).to eq true
         
     | 
| 
       19 
     | 
    
         
            -
              end
         
     | 
| 
       20 
     | 
    
         
            -
             
     | 
| 
       21 
     | 
    
         
            -
              it 'forwards methods over http' do
         
     | 
| 
       22 
     | 
    
         
            -
                allow(rpc).to receive(:http_post_request).and_return(
         
     | 
| 
       23 
     | 
    
         
            -
                  "{\"result\":814521,\"error\":null,\"id\":\"jsonrpc\"}\n"
         
     | 
| 
       24 
     | 
    
         
            -
                )
         
     | 
| 
       25 
     | 
    
         
            -
                expect(rpc.getblockcount).to eq 814_521
         
     | 
| 
       26 
     | 
    
         
            -
              end
         
     | 
| 
       27 
     | 
    
         
            -
             
     | 
| 
       28 
     | 
    
         
            -
              it 'returns error from http endpoint when indicated' do
         
     | 
| 
       29 
     | 
    
         
            -
                expect(rpc).to receive(:http_post_request).and_return(
         
     | 
| 
       30 
     | 
    
         
            -
                  "{\"result\":814521,\"error\":\"test error\",\"id\":\"jsonrpc\"}\n"
         
     | 
| 
       31 
     | 
    
         
            -
                )
         
     | 
| 
       32 
     | 
    
         
            -
                expect { rpc.test_rpc_call }.to raise_error(Utxoracle::Rpc::JSONRPCError)
         
     | 
| 
       33 
     | 
    
         
            -
              end
         
     | 
| 
       34 
     | 
    
         
            -
            end
         
     |