Advertisement
Guest User

CoinRPC

a guest
Nov 18th, 2017
276
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Ruby 7.77 KB | None | 0 0
  1. require 'net/http'
  2. require 'uri'
  3. require 'json'
  4.  
  5. class CoinRPC
  6.  
  7.   class JSONRPCError < RuntimeError; end
  8.   class ConnectionRefusedError < StandardError; end
  9.  
  10.   def initialize(uri)
  11.     @uri = URI.parse(uri)
  12.   end
  13.  
  14.   def self.[](currency)
  15.     c = Currency.find_by_code(currency.to_s)
  16.     case c && c.rpc
  17.     when c.code.upcase = 'ETH' then "::CoinRPC::ETH".constantize.new(c.rpc)
  18.     when c.code.upcase = 'XRP' then "::CoinRPC::XRP".constantize.new(c.rpc)
  19.     else "::CoinRPC::BTC".constantize.new(c.rpc)
  20.     end
  21.   end
  22.  
  23.   def method_missing(name, *args)
  24.     handle name, *args
  25.   end
  26.  
  27.   def handle
  28.     raise "Not implemented"
  29.   end
  30.  
  31.   class BTC < self
  32.     def handle(name, *args)
  33.       post_body = { 'method' => name, 'params' => args, 'id' => 'jsonrpc' }.to_json
  34.       resp = JSON.parse( http_post_request(post_body) )
  35.       raise JSONRPCError, resp['error'] if resp['error']
  36.       result = resp['result']
  37.       result.symbolize_keys! if result.is_a? Hash
  38.       result
  39.     end
  40.     def http_post_request(post_body)
  41.       http    = Net::HTTP.new(@uri.host, @uri.port)
  42.       request = Net::HTTP::Post.new(@uri.request_uri)
  43.       request.basic_auth @uri.user, @uri.password
  44.       request.content_type = 'application/json'
  45.       request.body = post_body
  46.       http.request(request).body
  47.     rescue Errno::ECONNREFUSED => e
  48.       raise ConnectionRefusedError
  49.     end
  50.     def safe_getbalance
  51.       begin
  52.         getbalance
  53.       rescue
  54.         'N/A'
  55.       end
  56.     end
  57.   end
  58.  
  59.   class ETH < self
  60.     def handle(name, *args)
  61.       post_body = {"jsonrpc" => "2.0", 'method' => name, 'params' => args, 'id' => '1' }.to_json
  62.       resp = JSON.parse( http_post_request(post_body) )
  63.       raise JSONRPCError, resp['error'] if resp['error']
  64.       result = resp['result']
  65.       result.symbolize_keys! if result.is_a? Hash
  66.       result
  67.     end
  68.     def http_post_request(post_body)
  69.       http    = Net::HTTP.new(@uri.host, @uri.port)
  70.       request = Net::HTTP::Post.new(@uri.request_uri)
  71.       request.basic_auth @uri.user, @uri.password
  72.       request.content_type = 'application/json'
  73.       request.body = post_body
  74.       http.request(request).body
  75.     rescue Errno::ECONNREFUSED => e
  76.       raise ConnectionRefusedError
  77.     end
  78.     def safe_getbalance
  79.       begin
  80.         (open('http://your_server_ip/cgi-bin/total.cgi').read.rstrip.to_f)
  81.       rescue
  82.         'N/A'
  83.       end
  84.     end
  85.     def getnewaddress(account)
  86.       call 'getnewaddress', account
  87.     end
  88.     def settxfee(fee)
  89.       call 'settxfee', fee
  90.     end
  91.     def getbalance
  92.       call 'getbalance'
  93.     end
  94.     def validateaddress(fund_uid)
  95.       call 'validateaddress', fund_uid
  96.     end
  97.     def listtransactions(account, number)
  98.       call 'listtransactions', account, number
  99.     end
  100.     def gettransaction(txid)
  101.       call 'gettransaction', txid
  102.     end
  103.     def sendtoaddress(fund_uid, amount)
  104.       call 'sendtoaddress', fund_uid, amount
  105.     end
  106.    
  107.   end
  108.  
  109.   class XRP < self
  110.     R_B58_DICT = 'rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz'
  111.  
  112.     def handle(name, *args)
  113.       post_body = {:method => name, :params => args} .to_json
  114.       resp = JSON.parse( http_post_request(post_body) )
  115.       raise JSONRPCError, resp['error'] if resp['error']
  116.       result = resp['result']
  117.       result.symbolize_keys! if result.is_a? Hash
  118.       result
  119.     end
  120.     def http_post_request(post_body)
  121.       http    = Net::HTTP.new(@uri.host, @uri.port)
  122.       request = Net::HTTP::Post.new(@uri.request_uri)
  123.       request.basic_auth @uri.user, @uri.password
  124.       request.content_type = 'application/json'
  125.       request.body = post_body
  126.       http.request(request).body
  127.     rescue Errno::ECONNREFUSED
  128.       raise ConnectionRefusedError
  129.     end
  130.     def getnewaddress(args = nil)
  131.       secret = SecureRandom.hex
  132.       pubkey = Digest::SHA512.new.update(secret).hexdigest[0...33]
  133.  
  134.       pubkey_inner_hash = Digest::SHA256.new.update(pubkey)
  135.       pubkey_outer_hash = Digest::RMD160.new
  136.       pubkey_outer_hash.update(pubkey_inner_hash.digest)
  137.  
  138.       account_id = pubkey_outer_hash.digest
  139.  
  140.       address_type_prefix = "\x00"
  141.       payload = address_type_prefix + account_id
  142.  
  143.       chksum_hash1 = Digest::SHA256.new.update(payload).digest
  144.       chksum_hash2 = Digest::SHA256.new.update(chksum_hash1).digest
  145.  
  146.       checksum = chksum_hash2[0...4]
  147.  
  148.       data_to_encode = payload << checksum
  149.  
  150.       int = data_to_encode.each_byte.reduce(0) { |i, byte| i * 256 + byte }
  151.  
  152.       address = ''
  153.  
  154.       while int > 0
  155.         char = R_B58_DICT[int % 58]
  156.         address << char
  157.         int /= 58
  158.       end
  159.  
  160.       {
  161.         address: (address << R_B58_DICT[0]).reverse,
  162.         secret: secret
  163.       }
  164.     end
  165.     def listtransactions(account, number = 100)
  166.       post_body = {
  167.         method: 'account_tx',
  168.         params: [{
  169.           account: account,
  170.           ledger_index_max: -1,
  171.           ledger_index_min: -1,
  172.           limit: number
  173.         }]
  174.       }.to_json
  175.  
  176.       resp = JSON.parse(http_post_request(post_body))
  177.       raise JSONRPCError, resp['error'] if resp['error']
  178.       resp['result']['transactions'].map { |t| t['tx'] }
  179.     end
  180.     def gettransaction(txid)
  181.       post_body = {
  182.         method: 'tx',
  183.         params: [
  184.           transaction: txid,
  185.           binary: false
  186.         ]
  187.       }.to_json
  188.  
  189.       resp = JSON.parse(http_post_request(post_body))
  190.       raise JSONRPCError, resp['error'] if resp['error']
  191.  
  192.       {
  193.         amount: resp['result']['Amount'].to_d / 1_000_000,
  194.         confirmations: resp['result']['meta']['AffectedNodes'].size,
  195.         timereceived: resp['result']['date'] + 946684800,
  196.         txid: txid,
  197.         details: [{
  198.            account:  'payment',
  199.            address:  resp['result']['Destination'],
  200.            amount:   resp['result']['Amount'].to_d / 1_000_000,
  201.            category: 'receive'
  202.         }]
  203.       }
  204.     end
  205.     def validateaddress(address = nil)
  206.       p address
  207.       post_body = {
  208.         method: 'ledger_entry',
  209.         params: [
  210.           {
  211.             account_root: address,
  212.             ledger_index: 'validated',
  213.             type: 'account_root'
  214.           }
  215.         ]
  216.       }.to_json
  217.  
  218.       resp = JSON.parse(http_post_request(post_body))
  219.       raise JSONRPCError, resp['error'] if resp['error']
  220.  
  221.       {
  222.         isvalid: resp['result']['status'] == 'success',
  223.         ismine: false,
  224.         address: address
  225.       }
  226.     end
  227.     def sendtoaddress(address, amount)
  228.       issuer = FundSource.find_by(uid: Withdraw.last.fund_uid)
  229.                          .member.payment_addresses
  230.                          .find_by(currency: currency)
  231.  
  232.       post_body = {
  233.         method: 'sign',
  234.         params: [{
  235.           offline: false,
  236.           secret: issuer['secret'],
  237.           tx_json: {
  238.             Account: issuer['address'],
  239.             Amount: {
  240.               currency: 'XRP',
  241.               issuer: issuer['address'],
  242.               value: amount.to_s
  243.             },
  244.             Destination: address,
  245.             TransactionType: 'Payment'
  246.           },
  247.           fee_mult_max: @tx_fee
  248.         }]
  249.       }.to_json
  250.  
  251.       resp = JSON.parse(http_post_request(post_body))
  252.       raise JSONRPCError, resp['error'] if resp['error']
  253.       p resp
  254.     end
  255.     def getbalance(account = nil)
  256.       post_body = {
  257.         method: 'account_info',
  258.         params: [
  259.           account: account || Currency.find_by_code('xrp').assets['accounts'].sample['address'],
  260.           strict: true,
  261.           ledger_index: 'validated'
  262.         ]
  263.       }.to_json
  264.  
  265.       resp = JSON.parse(http_post_request(post_body))
  266.       raise JSONRPCError, resp['error'] if resp['error']
  267.       result = resp['result']['account_data']['Balance'].to_f / 1_000_000
  268.       result
  269.     end
  270.     def safe_getbalance
  271.       getbalance || 'N/A'
  272.     end
  273.   end
  274. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement