Phillip Davis: 1 add registration w/ bch 6 files changed, 219 insertions(+), 22 deletions(-)
Copy & paste the following snippet into your terminal to import this patchset into git:
curl -s https://lists.sr.ht/~singpolyma/dev/patches/55928/mbox | git am -3Learn more about email & git
--- forms/registration/bch.rb | 19 ++++++++++ lib/btc_sell_prices.rb | 48 +++++++++++++++++++----- lib/registration.rb | 71 ++++++++++++++++++++++++++++++------ sgx_jmp.rb | 1 + test/test_bch_sell_prices.rb | 41 +++++++++++++++++++++ test/test_registration.rb | 61 ++++++++++++++++++++++++++++++- 6 files changed, 219 insertions(+), 22 deletions(-) create mode 100644 forms/registration/bch.rb create mode 100644 test/test_bch_sell_prices.rb diff --git a/forms/registration/bch.rb b/forms/registration/bch.rb new file mode 100644 index 0000000..3af32de --- /dev/null +++ b/forms/registration/bch.rb @@ -0,0 +1,19 @@ +result! +title "Activate using Bitcoin Cash" + +field( + label: "Minimual initial Bitcoin Cash deposit for activation", + var: "amount", + value: "%.6f" % @amount +) + +field( + label: "Bitcoin Cash address", + var: "bch_addresses", + value: @addr +) + +instructions( + "You will received a notification when your payment is complete." \ + "#{@final_message}" +) diff --git a/lib/btc_sell_prices.rb b/lib/btc_sell_prices.rb index f1783db..771f1a2 100644 --- a/lib/btc_sell_prices.rb +++ b/lib/btc_sell_prices.rb @@ -8,7 +8,7 @@ require "nokogiri" require_relative "em" -class BTCSellPrices +class CryptoSellPrices def initialize(redis, oxr_app_id) @redis = redis @oxr = Money::Bank::OpenExchangeRatesBank.new( @@ -17,25 +17,33 @@ class BTCSellPrices @oxr.app_id = oxr_app_id end + def usd + EMPromise.all([cad, cad_to_usd]).then { |(a, b)| a * b } + end + + def ticker_row_selector + raise NotImplementedError, "Subclass must implement" + end + + def crypto_name + raise NotImplementedError, "Subclass must implement" + end + def cad fetch_canadianbitcoins.then do |http| - canadianbitcoins = Nokogiri::HTML.parse(http.response) + cb = Nokogiri::HTML.parse(http.response) - bitcoin_row = canadianbitcoins.at("#ticker > table > tbody > tr") - unless bitcoin_row.at("td").text == "Bitcoin" - raise "Bitcoin row has moved" + row = cb.at(self.ticker_row_selector) + unless row.at("td").text == self.crypto_name + raise "#{crypto_name} row has moved" end BigDecimal( - bitcoin_row.at("td:nth-of-type(4)").text.match(/^\$(\d+\.\d+)/)[1] + row.at("td:nth-of-type(4)").text.match(/^\$(\d+\.\d+)/)[1] ) end end - def usd - EMPromise.all([cad, cad_to_usd]).then { |(a, b)| a * b } - end - protected def fetch_canadianbitcoins @@ -59,3 +67,23 @@ protected end end end + +class BCHSellPrices < CryptoSellPrices + def crypto_name + "Bitcoin Cash" + end + + def ticker_row_selector + "#ticker > table > tbody > tr:nth-of-type(2)" + end +end + +class BTCSellPrices < CryptoSellPrices + def crypto_name + "Bitcoin" + end + + def ticker_row_selector + "#ticker > table > tbody > tr" + end +end diff --git a/lib/registration.rb b/lib/registration.rb index ce18987..671fc4f 100644 --- a/lib/registration.rb +++ b/lib/registration.rb @@ -276,10 +276,18 @@ class Registration }.call(customer, tel, final_message: final_message, finish: finish) end - class Bitcoin - Payment.kinds[:bitcoin] = method(:new) + class CryptoPaymentMethod + def crypto_addrs + raise NotImplementedError, "Subclass must implement" + end - THIRTY_DAYS = 60 * 60 * 24 * 30 + def reg_form_name + raise NotImplementedError, "Subclass must implement" + end + + def sell_prices + raise NotImplementedError, "Subclass must implement" + end def initialize(customer, tel, final_message: nil, **) @customer = customer @@ -288,17 +296,17 @@ class Registration @final_message = final_message end - attr_reader :customer_id, :tel - def save TEL_SELECTIONS.set(@customer.jid, @tel) end + attr_reader :customer_id, :tel + def form(rate, addr) amount = CONFIG[:activation_amount] / rate FormTemplate.render( - "registration/btc", + reg_form_name, amount: amount, addr: addr, final_message: @final_message @@ -314,9 +322,7 @@ class Registration }.then(&method(:handle_possible_prev)) end end - protected - def handle_possible_prev(iq) raise "Action not allowed" unless iq.prev? @@ -325,14 +331,57 @@ class Registration def addr_and_rate EMPromise.all([ - @customer.btc_addresses.then { |addrs| - addrs.first || @customer.add_btc_address + self.crypto_addrs.then { |addrs| + addrs.first || self.add_crypto_addr }, - BTC_SELL_PRICES.public_send(@customer.currency.to_s.downcase) + + sell_prices.public_send(@customer.currency.to_s.downcase) ]) end end + class Bitcoin < CryptoPaymentMethod + Payment.kinds[:bitcoin] = method(:new) + + def reg_form_name + "registration/btc" + end + + def sell_prices + BTC_SELL_PRICES + end + + def crypto_addrs + @customer.btc_addresses + end + + def add_crypto_addr + @customer.add_btc_address + end + end + + ## Like Bitcoin + class BCH < CryptoPaymentMethod + Payment.kinds[:bch] = method(:new) + + def reg_form_name + "registration/bch" + end + + def sell_prices + BCH_SELL_PRICES + end + + def crypto_addrs + @customer.bch_addresses + end + + def add_crypto_addr + @customer.add_bch_address + end + end + + class CreditCard Payment.kinds[:credit_card] = ->(*args, **kw) { self.for(*args, **kw) } diff --git a/sgx_jmp.rb b/sgx_jmp.rb index cd2bb12..10176f7 100644 --- a/sgx_jmp.rb +++ b/sgx_jmp.rb @@ -220,6 +220,7 @@ when_ready do REDIS = EM::Hiredis.connect MEMCACHE = EM::P::Memcache.connect BTC_SELL_PRICES = BTCSellPrices.new(REDIS, CONFIG[:oxr_app_id]) + BCH_SELL_PRICES = BCHSellPrices.new(REDIS, CONFIG[:oxr_app_id]) DB = Postgres.connect(dbname: "jmp", size: 5) TEL_SELECTIONS = TelSelections.new diff --git a/test/test_bch_sell_prices.rb b/test/test_bch_sell_prices.rb new file mode 100644 index 0000000..9b8da94 --- /dev/null +++ b/test/test_bch_sell_prices.rb @@ -0,0 +1,41 @@ +# frozen_string_literal: true + +require "em-hiredis" +require "test_helper" +require "btc_sell_prices" + +class BCHSellPricesTest < Minitest::Test + def setup + @redis = Minitest::Mock.new + @subject = BCHSellPrices.new(@redis, "") + end + + def test_cad + stub_request(:get, "https://www.canadianbitcoins.com").to_return( + body: "<div id='ticker'><table><tbody>" \ + "<tr>" \ + "<td>Monopoly Money</td><td></td><td></td><td>10 trillion</td>" \ + "</tr>" \ + "<tr>" \ + "<td>Bitcoin Cash</td><td></td><td></td><td>$123.00</td>" \ + "</tr>" + ) + assert_equal BigDecimal(123), @subject.cad.sync + end + em :test_cad + + def test_usd + stub_request(:get, "https://www.canadianbitcoins.com").to_return( + body: "<div id='ticker'><table><tbody>" \ + "<tr>" \ + "<td>Monopoly Money</td><td></td><td></td><td>10 trillion</td>" \ + "</tr>" \ + "<tr>" \ + "<td>Bitcoin Cash</td><td></td><td></td><td>$123.00</td>" \ + "</tr>" + ) + @redis.expect(:get, EMPromise.resolve("0.5"), ["cad_to_usd"]) + assert_equal BigDecimal(123) / 2, @subject.usd.sync + end + em :test_usd +end diff --git a/test/test_registration.rb b/test/test_registration.rb index e3bf4e4..9d7f0ff 100644 --- a/test/test_registration.rb +++ b/test/test_registration.rb @@ -574,6 +574,16 @@ class RegistrationTest < Minitest::Test assert_kind_of Registration::Payment::Bitcoin, result end + def test_for_bch + iq = Blather::Stanza::Iq::Command.new + iq.form.fields = [ + { var: "activation_method", value: "bch" }, + { var: "plan_name", value: "test_usd" } + ] + result = Registration::Payment.for(iq, customer, "+15555550000") + assert_kind_of Registration::Payment::BCH, result + end + def test_for_credit_card braintree_customer = Minitest::Mock.new CustomerFinancials::BRAINTREE.expect( @@ -655,7 +665,7 @@ class RegistrationTest < Minitest::Test [Matching.new do |reply| assert_equal :canceled, reply.status assert_equal "1.000000", reply.form.field("amount").value - assert_equal "testaddr", reply.form.field("btc_addresses").value + assert_equal "testaddr", reply.form.field("bch_addresses").value true end] ) @@ -673,6 +683,55 @@ class RegistrationTest < Minitest::Test em :test_write end + class BCHTest < Minitest::Test + Registration::Payment::BCH::BCH_SELL_PRICES = Minitest::Mock.new + CustomerFinancials::REDIS = Minitest::Mock.new + + def setup + @customer = Minitest::Mock.new( + customer(plan_name: "test_usd") + ) + @customer.expect( + :add_btc_address, + EMPromise.resolve("testaddr") + )
We don't expect this for bch, right?
+ @bch = Registration::Payment::BCH.new( + @customer, + "+15555550000" + ) + end + + def test_write + CustomerFinancials::REDIS.expect( + :smembers, + EMPromise.resolve([]), + ["jmp_customer_bch_addresses-test"] + ) + blather = Minitest::Mock.new + Command::COMMAND_MANAGER.expect( + :write, + EMPromise.reject(SessionManager::Timeout.new), + [Matching.new do |reply| + assert_equal :canceled, reply.status + assert_equal "1.000000", reply.form.field("amount").value + assert_equal "testaddr", reply.form.field("bch_addresses").value + true + end] + ) + Registration::Payment::BCH::BCH_SELL_PRICES.expect( + :usd, + EMPromise.resolve(BigDecimal(1)) + ) + @bch.stub(:save, EMPromise.resolve(nil)) do + execute_command(blather: blather) do + @bch.write + end + end + assert_mock blather + end + em :test_write + end + class CreditCardTest < Minitest::Test def setup @credit_card = Registration::Payment::CreditCard.new( -- 2.34.1
Why did this change?