I use Peatio based exchange. Ethereum deposit/withdraw are working, but Binance coin doesn't work. I can't generate binance coin address. My codes below. Is it wring? I reall need help.
require 'net/http'
require 'uri'
require 'json'
class CoinRPC
class JSONRPCError < RuntimeError; end
class ConnectionRefusedError < StandardError; end
def initialize(uri)
#uri = URI.parse(uri)
end
def self.[](currency)
c = Currency.find_by_code(currency.to_s)
if c && c.rpc
name = c[:handler] || 'BTC'
"::CoinRPC::#{name}".constantize.new(c.rpc)
end
end
def method_missing(name, *args)
handle name, *args
end
def handle
raise "Not implemented"
end
class BTC < self
def handle(name, *args)
post_body = { 'method' => name, 'params' => args, 'id' => 'jsonrpc' }.to_json
resp = JSON.parse( http_post_request(post_body) )
raise JSONRPCError, resp['error'] if resp['error']
result = resp['result']
result.symbolize_keys! if result.is_a? Hash
result
end
def http_post_request(post_body)
http = Net::HTTP.new(#uri.host, #uri.port)
request = Net::HTTP::Post.new(#uri.request_uri)
request.basic_auth #uri.user, #uri.password
request.content_type = 'application/json'
request.body = post_body
http.request(request).body
rescue Errno::ECONNREFUSED => e
raise ConnectionRefusedError
end
def safe_getbalance
begin
getbalance
rescue
'N/A'
end
end
end
class ETH < self
def handle(name, *args)
post_body = {"jsonrpc" => "2.0", 'method' => name, 'params' => args, 'id' => '1' }.to_json
resp = JSON.parse( http_post_request(post_body) )
raise JSONRPCError, resp['error'] if resp['error']
result = resp['result']
result.symbolize_keys! if result.is_a? Hash
result
end
def http_post_request(post_body)
http = Net::HTTP.new(#uri.host, #uri.port)
request = Net::HTTP::Post.new(#uri.request_uri)
request.basic_auth #uri.user, #uri.password
request.content_type = 'application/json'
request.body = post_body
http.request(request).body
rescue Errno::ECONNREFUSED => e
raise ConnectionRefusedError
end
def safe_getbalance
begin
(open(#uri.host + '/cgi-bin/total.cgi').read.rstrip.to_f)
rescue
'N/A'
end
end
end
class BNB < self
def handle(name, *args)
post_body = {"jsonrpc" => "2.0", 'method' => name, 'params' => args, 'id' => '1' }.to_json
resp = JSON.parse( http_post_request(post_body) )
raise JSONRPCError, resp['error'] if resp['error']
result = resp['result']
result.symbolize_keys! if result.is_a? Hash
result
end
def http_post_request(post_body)
http = Net::HTTP.new(#uri.host, #uri.port)
request = Net::HTTP::Post.new(#uri.request_uri)
request.basic_auth #uri.user, #uri.password
request.content_type = 'application/json'
request.body = post_body
http.request(request).body
rescue Errno::ECONNREFUSED => e
raise ConnectionRefusedError
end
def safe_getbalance
begin
(open(#uri.host + '/cgi-bin/total.cgi').read.rstrip.to_f)
rescue
'N/A'
end
end
end
end
My code is parameterized for Binance currencies, I haven't tested the ETH network system, but I verified that the codes are similar.
It costs nothing to test ...
require 'net/http'
require 'uri'
require 'json'
class CoinRPC
class JSONRPCError < RuntimeError; end
class ConnectionRefusedError < StandardError; end
def initialize(coin)
#uri = URI.parse(coin.rpc)
#rest = coin.rest
#coin = coin
end
def self.[](currency)
c = Currency.find_by_code(currency.to_s)
if c && c.rpc
if c.proto == 'ETH'
name = 'ETH'
elsif c.proto == 'BTC'
name = 'BTC'
elsif c.proto == 'OLD_BTC'
name = 'OLD_BTC'
elsif c.proto == 'WOA_BTC'
name = 'WOA_BTC'
elsif c.proto == 'CNT'
name = 'CNT'
else
name = c[:handler]
end
Rails.logger.info "Making class " + name.to_s + "(" + currency.to_s + ")\n"
"::CoinRPC::#{name.to_s}".constantize.new(c)
end
end
def method_missing(name, *args)
handle name, *args
end
def handle
raise "Not implemented"
end
class BTC < self
def handle(name, *args)
post_body = { 'method' => name, 'params' => args, 'id' => 'jsonrpc' }.to_json
resp = JSON.parse( http_post_request(post_body) )
raise JSONRPCError, resp['error'] if resp['error']
result = resp['result']
result.symbolize_keys! if result.is_a? Hash
result
end
def http_post_request(post_body)
http = Net::HTTP.new(#uri.host, #uri.port)
request = Net::HTTP::Post.new(#uri.request_uri)
request.basic_auth #uri.user, #uri.password
request.content_type = 'application/json'
request.body = post_body
http.request(request).body
rescue Errno::ECONNREFUSED => e
raise ConnectionRefusedError
end
def http_post_request(post_body)
http = Net::HTTP.new(#uri.host, #uri.port)
request = Net::HTTP::Post.new(#uri.request_uri)
request.basic_auth #uri.user, #uri.password
request.content_type = 'application/json'
request.body = post_body
#reply = http.request(request).body
# Rails.logger.info #reply
return #reply
rescue Errno::ECONNREFUSED => e
raise ConnectionRefusedError
end
def getnewaddress(name, digest)
#newaddress = handle("getnewaddress", name)
end
def safe_getblockchaininfo
begin
getblockchaininfo
rescue
'N/A'
end
end
def safe_getbalance
begin
getbalance
rescue
'N/A'
end
end
end
class OLD_BTC < self
def handle(name, *args)
post_body = { 'method' => name, 'params' => args, 'id' => 'jsonrpc' }.to_json
resp = JSON.parse( http_post_request(post_body) )
raise JSONRPCError, resp['error'] if resp['error']
result = resp['result']
result.symbolize_keys! if result.is_a? Hash
result
end
def http_post_request(post_body)
http = Net::HTTP.new(#uri.host, #uri.port)
request = Net::HTTP::Post.new(#uri.request_uri)
request.basic_auth #uri.user, #uri.password
request.content_type = 'application/json'
request.body = post_body
http.request(request).body
rescue Errno::ECONNREFUSED => e
raise ConnectionRefusedError
end
def getnewaddress(name, digest)
#newaddress = handle("getnewaddress", name)
end
def getblockchaininfo
#getinfo = getinfo()
{
blocks: Integer(#getinfo[:blocks]),
headers: 0,
mediantime: 0
}
end
def safe_getbalance
begin
getbalance
rescue
'N/A'
end
end
end
class WOA_BTC < self
def handle(name, *args)
post_body = { 'method' => name, 'params' => args, 'id' => 'jsonrpc' }.to_json
Rails.logger.info "WOA_BTC " + post_body
resp = JSON.parse( http_post_request(post_body) )
Rails.logger.info resp
raise JSONRPCError, resp['error'] if resp['error']
result = resp['result']
result.symbolize_keys! if result.is_a? Hash
result
end
def http_post_request(post_body)
http = Net::HTTP.new(#uri.host, #uri.port)
request = Net::HTTP::Post.new(#uri.request_uri)
request.basic_auth #uri.user, #uri.password
request.content_type = 'application/json'
request.body = post_body
#Rails.logger.info post_body
#reply = http.request(request).body
#Rails.logger.info #reply
return #reply
rescue Errno::ECONNREFUSED => e
raise ConnectionRefusedError
end
def sendtoaddress(from, address, amount)
handle("sendtoaddress", address, amount)
end
def getnewaddress(name, digest)
#newaddress = handle("getnewaddress", "")
end
def getblockchaininfo
#getinfo = getinfo()
{
blocks: Integer(#getinfo[:blocks]),
headers: 0,
mediantime: 0
}
end
def safe_getbalance
begin
getbalance
rescue
'N/A'
end
end
end
class ETH < self
def handle(name, *args)
post_body = {"jsonrpc" => "2.0", 'method' => name, 'params' => args, 'id' => '1' }.to_json
resp = JSON.parse( http_post_request(post_body) )
raise JSONRPCError, resp['error'] if resp['error']
result = resp['result']
result.symbolize_keys! if result.is_a? Hash
result
end
def http_post_request(post_body)
http = Net::HTTP.new(#uri.host, #uri.port)
request = Net::HTTP::Post.new(#uri.request_uri)
request.basic_auth #uri.user, #uri.password
request.content_type = 'application/json'
request.body = post_body
http.request(request).body
rescue Errno::ECONNREFUSED => e
raise ConnectionRefusedError
end
def safe_getbalance
begin
(open(#uri.host + '/cgi-bin/total.cgi').read.rstrip.to_f)
rescue
'N/A'
end
end
def getblockchaininfo
#lastBlock = eth_getBlockByNumber("latest", true)
#Rails.logger.info #lastBlock
#Rails.logger.info "number = " + Integer(#lastBlock[:number]).to_s + ", timestamp = " + Integer(#lastBlock[:timestamp]).to_s
{
blocks: Integer(#lastBlock[:number]),
headers: 0,
mediantime: Integer(#lastBlock[:timestamp])
}
end
end
class LISK < self
def handle(name, *args)
post_body = {"jsonrpc" => "2.0", 'method' => name, 'params' => args, 'id' => '1' }.to_json
Rails.logger.info "LISK -> " + post_body
resp = JSON.parse( http_post_request(post_body) )
Rails.logger.info "LISK <- " + resp.to_json
raise JSONRPCError, resp['error'] if resp['error']
result = resp['result']
result.symbolize_keys! if result.is_a? Hash
result
end
def http_post_request(post_body)
http = Net::HTTP.new(#uri.host, #uri.port)
request = Net::HTTP::Post.new(#uri.request_uri)
request.basic_auth #uri.user, #uri.password
request.content_type = 'application/json'
request.body = post_body
#reply = http.request(request).body
return #reply
rescue Errno::ECONNREFUSED => e
raise ConnectionRefusedError
end
def http_post_request_body(post_url, post_body)
Rails.logger.info "LISK -> " + post_url + " / " + post_body
uri = URI.parse(post_url)
http = Net::HTTP.new(uri.host, uri.port)
request = Net::HTTP::Post.new(uri.request_uri)
request.basic_auth uri.user, uri.password
request.content_type = 'application/json'
request.body = post_body
reply = JSON.parse(http.request(request).body)
raise JSONRPCError, reply['error'] if reply['error']
Rails.logger.info "LISK <- " + reply.to_json
return reply
rescue Errno::ECONNREFUSED => e
raise ConnectionRefusedError
end
def http_get_request(get_url)
Rails.logger.info "LISK -> " + get_url
uri = URI.parse(get_url)
http = Net::HTTP.new(uri.host, uri.port)
request = Net::HTTP::Get.new(uri.request_uri)
request.basic_auth uri.user, uri.password
request.content_type = ""
request.body = ""
reply = http.request(request).body
result = JSON.parse(reply)
raise JSONRPCError, result['error'] if result['error']
Rails.logger.info "LISK <- " + result.to_json
return result
end
def http_put_request_body(post_url, post_body)
Rails.logger.info "LISK -> " + post_url + " / " + post_body
uri = URI.parse(post_url)
http = Net::HTTP.new(uri.host, uri.port)
request = Net::HTTP::Put.new(uri.request_uri)
request.basic_auth uri.user, uri.password
request.content_type = 'application/json'
request.body = post_body
reply = JSON.parse(http.request(request).body)
raise JSONRPCError, reply['error'] if reply['error']
Rails.logger.info "LISK <- " + reply.to_json
return reply
rescue Errno::ECONNREFUSED => e
raise ConnectionRefusedError
end
def safe_getbalance
begin
getbalance
rescue => ex
Rails.logger.info "[error]: " + ex.message + "\n" + ex.backtrace.join("\n") + "\n"
'N/A'
end
end
def getbalance
result = http_get_request("#{#rest}/api/accounts/getBalance?address=#{#coin.base_account}")
balance = result['balance'].to_f / 100000000.0
return balance
end
def gettransaction(txid)
transaction = http_get_request("#{#rest}/api/transactions/get?id=#{txid}")
{
confirmations: transaction['transaction']['confirmations'],
time: Time.now.to_i,
details:
[
address: transaction['transaction']['recipientId'],
amount: transaction['transaction']['amount'].to_f / 100000000.0,
category: "receive"
]
}
end
def settxfee
end
def sendtoaddress(from, address, amount)
parameters =
{
secret: from,
amount: Integer(amount * 100000000.0),
recipientId: address
}.to_json
result = http_put_request_body("#{#rest}/api/transactions", parameters)
return result['transactionId']
end
# digest - simple form usermail & number
def getnewaddress(base_account, digest)
parameters =
{
secret: digest
}.to_json
result = http_post_request_body("#{#rest}/api/accounts/open", parameters)
return result['account']['address']
end
def getfee(size)
return (12000000.0/100000000.0).to_f
end
def validateaddress(address)
end
def getblockchaininfo
result = http_get_request("#{#rest}/api/blocks/getStatus")
{
blocks: Integer(result['height']),
headers: 0,
mediantime: 0
}
end
end
class CNT < self
def handle(name, *args)
post_body = {"jsonrpc" => "2.0", 'method' => name, 'params' => args, 'id' => '1' }.to_json
Rails.logger.info "CNT -> " + post_body
resp = JSON.parse( http_post_request(post_body) )
Rails.logger.info "CNT <- " + resp.to_json
raise JSONRPCError, resp['error'] if resp['error']
result = resp['result']
#result.symbolize_keys! if result.is_a? Hash
result
end
def handle_one(name, arg)
post_body = {"jsonrpc" => "2.0", 'method' => name, 'params' => arg, 'id' => '1' }.to_json
Rails.logger.info "CNT -> " + post_body
resp = JSON.parse( http_post_request(post_body) )
Rails.logger.info "CNT <- " + resp.to_json
raise JSONRPCError, resp['error'] if resp['error']
result = resp['result']
#result.symbolize_keys! if result.is_a? Hash
result
end
def http_post_request(post_body)
http = Net::HTTP.new(#uri.host, #uri.port)
request = Net::HTTP::Post.new(#uri.request_uri)
#request.basic_auth #uri.user, #uri.password
request.content_type = 'application/json'
request.body = post_body
#reply = http.request(request).body
return #reply
rescue Errno::ECONNREFUSED => e
raise ConnectionRefusedError
end
def safe_getbalance
begin
getbalance
rescue => ex
Rails.logger.info "[error]: " + ex.message + "\n" + ex.backtrace.join("\n") + "\n"
'N/A'
end
end
def getbalance
result = handle("getbalance")
balance = result['balance'].to_f / 1000000000.0
return balance
end
def gettransaction(txid)
parameters =
{
txid: txid
}
transaction = handle_one("get_transfer_by_txid", parameters)
confirmations = Integer(transaction['transfer']['height'])
if confirmations > 0
result = handle("getheight", "")
confirmations = Integer(result['height']) - confirmations
end
result = {
confirmations: confirmations,
time: Time.now.to_i,
details:[]
}
if transaction['transfer']['destinations'] == nil
return result
end
transaction['transfer']['destinations'].each do |destination|
tx = {
address: destination['address'],
amount: destination['amount'].to_f / 1000000000.0,
category: "receive"
}
result[:details].push(tx)
end
return result
end
def settxfee
end
def sendtoaddress(from, address, amount)
parameters =
{
account_index: 0,
destinations:
[
{
amount: Integer(amount * 1000000000.0),
address: address
}
],
get_tx_key: true
}
result = handle_one("transfer", parameters)
return result['tx_hash']
end
def getnewaddress(name, digest)
parameters =
{
account_index: 0,
label: ""
}.to_json
result = handle_one("create_address", parameters)
return result['address']
end
def getfee(size)
return (30000000.0/1000000000.0).to_f
end
def validateaddress(address)
end
def getblockchaininfo
result = handle("getheight", "")
{
blocks: Integer(result['height']),
headers: 0,
mediantime: 0
}
end
end
end
I have controller.rb as follows
def lesson
params.require(:lesson_id)
begin
#result = #user.lesson_details(Integer(params[:lesson_id]),
params[:lesson_name]
head :ok
rescue ArgumentError => e
render_error(:bad_request, e.message)
end
end
I am testing using postman http://localhost:3001/DB/DB_id/users/user_id/books/lesson/lesson_id?lesson_name='test'
How do i wrap the conversion of the param lesson_id in rescue so i don't catch any underlying model's errors as well?
One option is to wrap it in an if:
def lesson
if params[:lesson_id] && params[:lesson_name]
#result = #user.lesson_details(params[:lesson_id]),
params[:lesson_name]
head :ok
else
render_error :bad_request, 'Your message here'
end
end
You can just rescue nil on #result.
def lesson
#result = #user.lesson_details(params[:lesson_id]), params[:lesson_name] rescue nil
if #result
head :ok
else
render_error :bad_request, 'Your message here'
end
end
Or you could use the rescue clause without ArgumentError
def lesson
params.require(:lesson_id)
begin
#result = #user.lesson_details(Integer(params[:lesson_id]),
params[:lesson_name]
head :ok
rescue => e
render_error(:bad_request, e.message)
end
end
So witness and observe the following code, my questions is why do i never make it to the on_connect after starting the cool.io loop in send_to_server, the l.run should fire off the request as per the documented example on the github, and how the code handles incoming connections in module Server #socket.attach(l)
l.run
which does work and accepts the incoming data and sends it to my parser, which does work and fires off all the way up until the aforementioned send_to_server. So what is going on here?
require 'cool.io'
require 'http/parser'
require 'uri'
class Hash
def downcase_key
keys.each do |k|
store(k.downcase, Array === (v = delete(k)) ? v.map(&:downcase_key) : v)
end
self
end
end
module ShadyProxy
extend self
module ClientParserCallbacks
extend self
def on_message_complete(conn)
lambda do
puts "on_message_complete"
PluginHooks.before_request_to_server(conn)
end
end
def on_headers_complete(conn)
lambda do |headers|
conn.headers = headers
end
end
def on_body(conn)
lambda do |chunk|
conn.body << chunk
end
end
end
module PluginHooks
extend self
def before_request_to_server(conn)
# modify request here
conn.parser.headers.delete "Proxy-Connection"
conn.parser.headers.downcase_key
send_to_server(conn)
end
def send_to_server(conn)
parser = conn.parser
uri = URI::parse(parser.request_url)
l = Coolio::Loop.default
puts uri.scheme + "://" + uri.host
c = ShadyHttpClient.connect(uri.scheme + "://" + uri.host,uri.port).attach(l)
c.connection_reference = conn
c.request(parser.http_method,uri.request_uri)
l.run
end
def before_reply_to_client(conn)
end
end
class ShadyHttpClient < Coolio::HttpClient
def connection_reference=(conn)
puts "haz conneciton ref"
#connection_reference = conn
end
def connection_reference
#connection_reference
end
def on_connect
super
#never gets here
#headers = nil
#body = ''
#buffer = ''
end
def on_connect_failed
super
# never gets here either
end
def on_response_header(header)
#headers = header
end
def on_body_data(data)
puts "on data?"
#body << data
STDOUT.write data
end
def on_request_complete
puts "Headers"
puts #headers
puts "Body"
puts #body
end
def on_error(reason)
STDERR.puts "Error: #{reason}"
end
end
class ShadyProxyConnection < Cool.io::TCPSocket
attr_accessor :headers, :body, :buffer, :parser
def on_connect
#headers = nil
#body = ''
#buffer = ''
#parser = Http::Parser.new
#parser.on_message_complete = ClientParserCallbacks.on_message_complete(self)
#parser.on_headers_complete = ClientParserCallbacks.on_headers_complete(self)
#parser.on_body = ClientParserCallbacks.on_body(self)
end
def on_close
puts "huh?"
end
def on_read(data)
#buffer << data
#parser << data
end
end
module Server
def run(opts)
begin
# Start our server to handle connections (will raise things on errors)
l = Coolio::Loop.new
#socket = Cool.io::TCPServer.new(opts[:host],opts[:port], ShadyProxy::ShadyProxyConnection)
#socket.attach(l)
l.run
# Handle every request in another thread
loop do
Thread.new s = #socket.accept
end
# CTRL-C
rescue Interrupt
puts 'Got Interrupt..'
# Ensure that we release the socket on errors
ensure
if #socket
#socket.close
puts 'Socked closed..'
end
puts 'Quitting.'
end
end
module_function :run
end
end
ShadyProxy::Server.run(:host => '0.0.0.0',:port => 1234)
What i bascially want is to extend the Numeric class so that it has one extra Attribute (currencie), which is set when of the undefined methods are invoked [yen(s), euro(s), etc.]
So, here is the class definition:
class Numeric
##currencies = {'yen' => 0.013, 'euro' => 1.292, 'rupee' => 0.019, 'dollar' => 1}
attr_accessor :currencie
def method_missing(method_id)
singular_currency = method_id.to_s.gsub( /s$/, '')
if ##currencies.has_key?(singular_currency)
self.currencie = singular_currency
self * ##currencies[singular_currency]
puts "method finished"
else
super
end
end
def in(convert_to)
end
end
Now, when i run the code
a = 5.rupees
puts "currencie is -> " + a.currencie
i've got:
method finished
/path_to_file/hw2.1.rb:33:in `<main>': undefined method `currencie' for nil:NilClass (NoMethodError)
Also the attribute currencie seems to be unset.
What am i doing wrong ?
In your case method_missing should return object i.e. self. Just add self to method_missing and it will work.
def method_missing(method_id)
singular_currency = method_id.to_s.gsub( /s$/, '')
if ##currencies.has_key?(singular_currency)
self.currencie = singular_currency
puts "method finished"
self * ##currencies[singular_currency] # just change the order of expressions
else
super
end
end
EDIT: Fixed as injekt said
I would like to upload data I generated at runtime in Ruby, something like feeding the upload from a block.
All examples I found only show how to stream a file that must be on disk prior to the request but I do not want to buffer the file.
What is the best solution besides rolling my own socket connection?
This a pseudocode example:
post_stream('127.0.0.1', '/stream/') do |body|
generate_xml do |segment|
body << segment
end
end
Code that works.
require 'thread'
require 'net/http'
require 'base64'
require 'openssl'
class Producer
def initialize
#mutex = Mutex.new
#body = ''
#eof = false
end
def eof!()
#eof = true
end
def eof?()
#eof
end
def read(size)
#mutex.synchronize {
#body.slice!(0,size)
}
end
def produce(str)
if #body.empty? && #eof
nil
else
#mutex.synchronize { #body.slice!(0,size) }
end
end
end
data = "--60079\r\nContent-Disposition: form-data; name=\"file\"; filename=\"test.file\"\r\nContent-Type: application/x-ruby\r\n\r\nthis is just a test\r\n--60079--\r\n"
req = Net::HTTP::Post.new('/')
producer = Producer.new
req.body_stream = producer
req.content_length = data.length
req.content_type = "multipart/form-data; boundary=60079"
t1 = Thread.new do
producer.produce(data)
producer.eof!
end
res = Net::HTTP.new('127.0.0.1', 9000).start {|http| http.request(req) }
puts res
There's a Net::HTTPGenericRequest#body_stream=( obj.should respond_to?(:read) )
You use it more or less like this:
class Producer
def initialize
#mutex = Mutex.new
#body = ''
end
def read(size)
#mutex.synchronize {
#body.slice!(0,size)
}
end
def produce(str)
#mutex.synchronize {
#body << str
}
end
end
# Create a producer thread
req = Net::HTTP::Post.new(url.path)
req.body_stream = producer
res = Net::HTTP.new(url.host, url.port).start {|http| http.request(req) }