~singpolyma/dev

This thread contains a patchset. You're looking at the original emails, but you may wish to use the patch review UI. Review patch
1

[PATCH] add registration w/ bch

Details
Message ID
<20241112171852.69882-1-phdavis1027@gmail.com>
DKIM signature
pass
Download raw message
Patch: +219 -22
---
 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")
				)
				@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
Details
Message ID
<ZzOQlZb5kQ+OMoQ8@singpolyma-beefy.lan>
In-Reply-To
<20241112171852.69882-1-phdavis1027@gmail.com> (view parent)
DKIM signature
pass
Download raw message
>---
> 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/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

Why did this change?

> 						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
>
Reply to thread Export thread (mbox)