Last active
October 5, 2020 15:58
-
-
Save fuyuton/87b5f4d2d9cd9e8801b3cc265c1ed925 to your computer and use it in GitHub Desktop.
bitcoin-rubyでmonapartyのトークンを送れるようにするコード
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# frozen_string_literal: true | |
source "https://rubygems.org" | |
gem 'bitcoin-ruby', git: 'https://github.com/fuyuton/bitcoin-ruby', branch: 'master', require: 'bitcoin' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'json' | |
require "uri" | |
require "net/http" | |
require 'bitcoin' | |
class Http_Client | |
def initialize(url) | |
@url = url | |
@https = Net::HTTP.new(@url.host, @url.port); | |
@https.use_ssl = true | |
@request = Net::HTTP::Post.new(@url) | |
@request["Content-Type"] = "application/json" | |
end | |
def post(json) | |
@request.body = json | |
response = @https.request(@request) | |
JSON.parse(response.read_body) | |
end | |
end | |
class Monaparty | |
def initialize(network, url, is_testnet) | |
@api = Http_Client.new(url) | |
#ネットワークの指定 | |
#多分これであってるだろう(元にしたコードにあったコメント) | |
Bitcoin.network = is_testnet ? "#{network}_testnet".to_sym : network.to_sym | |
end | |
def valid_address?(address) | |
Bitcoin.valid_address?(address) | |
end | |
#MONAの残高を見る | |
def get_balance_basecoin(address) | |
json = create_json("get_chain_address_info", {"addresses":["#{address}"],"with_uxtos":"True","with_last_txn_hashes":"4"}) | |
@api.post(json) | |
balance = '' | |
res['result'].each {|elem| | |
info = elem['info'] | |
balance = info['balance'] if info['addrStr'] == address | |
} | |
balance | |
end | |
#アセット(トークン)の残高を見る | |
def get_balance_token(address) | |
json = create_json("get_normalized_balances", {"addresses":["#{address}"]}) | |
@api.post(json) | |
balance = '' | |
if !res['result'].empty? | |
res['result'].each {|elem| | |
balance = elem['normalized_quantity'] if elem['address'] == address | |
} | |
end | |
balance | |
end | |
def get_raw_transaction(tx_hash, verbose=false, skip_missing=false) | |
json = create_proxy_json("getrawtransaction", {"tx_hash": "#{tx_hash}", "verbose": verbose, "skip_missing": skip_missing }) | |
res = @api.post(json) | |
verbose ? res['result']['hex'] : res['result'] | |
end | |
def create_unsigned_tx(src, dest, asset, qty, fee, is_enhanced_send=true, mona_qty=54600) | |
json = create_proxy_json( | |
"create_send", | |
{ | |
"source": src, | |
"destination": dest, | |
"asset": asset, | |
"quantity": qty*100000000, | |
"fee_per_kb": fee * 1024, | |
"use_enhanced_send": is_enhanced_send, | |
"allow_unconfirmed_inputs": false, | |
"disable_utxo_locks": true, | |
"encoding": "auto", | |
"extended_tx_info": true, | |
"regular_dust_size": mona_qty, | |
} | |
) | |
res = @api.post(json) | |
if res.has_key?('result') && res['result'].has_key?('tx_hex') | |
unsigned_tx = res['result']['tx_hex'] | |
puts "\nunsigned_tx: #{unsigned_tx}" | |
else | |
puts "#{__method__} Error:\n" | |
puts "#{res}\n" | |
exit | |
end | |
unsigned_tx | |
end | |
def sign(unsigned_tx, secret) | |
#鍵の準備 | |
key = Bitcoin::Key.from_base58 secret | |
pubkey = [key.pub].pack('H*') | |
#トランザクションを作る | |
#成功バージョン(ただしdust monaも送られる) | |
tx = Bitcoin::Protocol::Tx.new([unsigned_tx].pack("H*")) | |
prev_hash = tx.in[0].prev_out.reverse_hth | |
prev_tx_hex = [get_raw_transaction(prev_hash)].pack('H*') | |
prev_tx = Bitcoin::Protocol::Tx.new prev_tx_hex | |
subscript = tx.signature_hash_for_input 0, prev_tx | |
#署名する | |
signed_tx = Bitcoin.sign_data(Bitcoin.open_key(key.priv), subscript) | |
tx.in[0].script_sig = Bitcoin::Script.to_signature_pubkey_script signed_tx, pubkey | |
signed_tx_hex = tx.to_payload.unpack('H*')[0] | |
end | |
def broadcast(signed_tx_hex) | |
json = create_json("broadcast_tx", {signed_tx_hex: signed_tx_hex}) | |
res = @api.post(json) | |
if res.has_key?('result') | |
txid = res['result'] | |
else | |
puts "#{__method__} Error:\n" | |
puts "#{res}\n" | |
exit | |
end | |
txid | |
end | |
private | |
def create_json(method, params) | |
%Q{{ | |
"jsonrpc": "2.0", | |
"id": 0, | |
"method": "#{method}", | |
"params": #{params.to_json} | |
}} | |
end | |
def create_proxy_json(method, params) | |
%Q{{ | |
"jsonrpc": "2.0", | |
"id": 0, | |
"method": | |
"proxy_to_counterpartyd", | |
"params": | |
{ | |
"method": "#{method}", | |
"params": #{params.to_json} | |
} | |
}} | |
end | |
end | |
if __FILE__ == $0 | |
network = "monacoin" | |
is_testnet = true | |
if !is_testnet | |
#url = URI("https://wallet.monaparty.me/_api") | |
url = URI("https://monapa.electrum-mona.org/_api") | |
src_address = "" | |
dest_address = "" | |
secret = "" | |
else | |
#テストネットにつなぐときは、endpointを /_t_api にする | |
url = URI("https://testnet-monapa.electrum-mona.org/_t_api") | |
#url = URI("https://wallet-testnet.monaparty.me/_t_api") | |
src_address = "" | |
dest_address = "" | |
secret = "" | |
end | |
mp = Monaparty.new(network, url, is_testnet) | |
avs = mp.valid_address?(src_address) | |
avd = mp.valid_address?(dest_address) | |
if !avs || !avd | |
puts "source_address valid? #{avs}" if !avs | |
puts "destination_address valid? #{avd}" if !avd | |
exit | |
end | |
asset = "XMP" | |
token_qty = 1 | |
fee_satoshi = 110 | |
#未署名トランザクションを作る | |
unsigned_tx = mp.create_unsigned_tx(src_address, dest_address, asset, token_qty, fee_satoshi) | |
#monaを送るときの書き方 | |
#qty_watanabe = 100000000 | |
#unsigned_tx = mp.create_unsigned_tx(src_address, dest_address, asset, token_qty, fee_satoshi, false, qty_watanabe) | |
#未署名トランザクションに署名する | |
signed_tx_hex = mp.sign(unsigned_tx, secret) | |
puts "signed_tx_hex: #{signed_tx_hex}" | |
#署名されたトランザクションを送信する | |
txid = mp.broadcast(signed_tx_hex) | |
puts "txid: #{txid}" | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment