bitcoin-ruby 0.0.6 → 0.0.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +0 -1
- data/.travis.yml +2 -7
- data/COPYING +1 -1
- data/Gemfile +2 -6
- data/Gemfile.lock +34 -0
- data/README.rdoc +16 -68
- data/Rakefile +3 -6
- data/bin/bitcoin_shell +0 -1
- data/{concept-examples/blockchain-pow.rb → examples/concept-blockchain-pow.rb} +0 -0
- data/lib/bitcoin.rb +350 -296
- data/lib/bitcoin/builder.rb +3 -1
- data/lib/bitcoin/connection.rb +2 -1
- data/lib/bitcoin/contracthash.rb +76 -0
- data/lib/bitcoin/dogecoin.rb +97 -0
- data/lib/bitcoin/ffi/bitcoinconsensus.rb +74 -0
- data/lib/bitcoin/ffi/openssl.rb +98 -2
- data/lib/bitcoin/ffi/secp256k1.rb +144 -0
- data/lib/bitcoin/key.rb +12 -2
- data/lib/bitcoin/logger.rb +3 -12
- data/lib/bitcoin/protocol/block.rb +3 -9
- data/lib/bitcoin/protocol/parser.rb +6 -2
- data/lib/bitcoin/protocol/tx.rb +44 -13
- data/lib/bitcoin/protocol/txin.rb +4 -2
- data/lib/bitcoin/protocol/txout.rb +2 -2
- data/lib/bitcoin/script.rb +212 -37
- data/lib/bitcoin/trezor/mnemonic.rb +130 -0
- data/lib/bitcoin/version.rb +1 -1
- data/spec/bitcoin/bitcoin_spec.rb +32 -3
- data/spec/bitcoin/builder_spec.rb +18 -0
- data/spec/bitcoin/contracthash_spec.rb +45 -0
- data/spec/bitcoin/dogecoin_spec.rb +176 -0
- data/spec/bitcoin/ffi_openssl.rb +45 -0
- data/spec/bitcoin/fixtures/156e6e1b84c5c3bd3a0927b25e4119fadce6e6d5186f363317511d1d680fae9a.json +24 -0
- data/spec/bitcoin/fixtures/8d0b238a06b5a70be75d543902d02d7a514d68d3252a949a513865ac3538874c.json +24 -0
- data/spec/bitcoin/fixtures/coinbase-toshi.json +33 -0
- data/spec/bitcoin/fixtures/coinbase.json +24 -0
- data/spec/bitcoin/fixtures/dogecoin-block-60323982f9c5ff1b5a954eac9dc1269352835f47c2c5222691d80f0d50dcf053.bin +0 -0
- data/spec/bitcoin/fixtures/rawtx-01-toshi.json +46 -0
- data/spec/bitcoin/fixtures/rawtx-02-toshi.json +46 -0
- data/spec/bitcoin/fixtures/rawtx-03-toshi.json +73 -0
- data/spec/bitcoin/fixtures/rawtx-testnet-04fdc38d6722ab4b12d79113fc4b2896bdcc5169710690ee4e78541b98e467b4.bin +0 -0
- data/spec/bitcoin/fixtures/rawtx-testnet-0b294c7d11dd21bcccb8393e6744fed7d4d1981a08c00e3e88838cc421f33c9f.bin +0 -0
- data/spec/bitcoin/fixtures/rawtx-testnet-3bc52ac063291ad92d95ddda5fd776a342083b95607ad32ed8bc6f8f7d30449e.bin +0 -0
- data/spec/bitcoin/fixtures/rawtx-testnet-6f0bbdd4e71a8af4305018d738184df32dbb6f27284fdebd5b56d16947f7c181.bin +0 -0
- data/spec/bitcoin/fixtures/rawtx-testnet-a7c9b06e275e8674cc19a5f7d3e557c72c6d93576e635b33212dbe08ab7cdb60.bin +0 -0
- data/spec/bitcoin/fixtures/rawtx-testnet-f80acbd2f594d04ddb0e1cacba662132104909157dff526935a3c88abe9201a5.bin +0 -0
- data/spec/bitcoin/protocol/block_spec.rb +0 -22
- data/spec/bitcoin/protocol/tx_spec.rb +145 -2
- data/spec/bitcoin/script/script_spec.rb +282 -0
- data/spec/bitcoin/secp256k1_spec.rb +48 -0
- data/spec/bitcoin/spec_helper.rb +0 -51
- data/spec/bitcoin/trezor/mnemonic_spec.rb +161 -0
- metadata +48 -98
- data/bin/bitcoin_dns_seed +0 -130
- data/bin/bitcoin_gui +0 -80
- data/bin/bitcoin_node +0 -153
- data/bin/bitcoin_node_cli +0 -81
- data/bin/bitcoin_wallet +0 -402
- data/doc/CONFIG.rdoc +0 -66
- data/doc/EXAMPLES.rdoc +0 -13
- data/doc/NAMECOIN.rdoc +0 -34
- data/doc/NODE.rdoc +0 -225
- data/doc/STORAGE.rdoc +0 -33
- data/doc/WALLET.rdoc +0 -102
- data/examples/balance.rb +0 -66
- data/examples/forwarder.rb +0 -73
- data/examples/index_nhash.rb +0 -24
- data/examples/reindex_p2sh_addrs.rb +0 -44
- data/examples/relay_tx.rb +0 -22
- data/examples/verify_tx.rb +0 -57
- data/lib/bitcoin/config.rb +0 -58
- data/lib/bitcoin/gui/addr_view.rb +0 -44
- data/lib/bitcoin/gui/bitcoin-ruby.png +0 -0
- data/lib/bitcoin/gui/bitcoin-ruby.svg +0 -80
- data/lib/bitcoin/gui/conn_view.rb +0 -38
- data/lib/bitcoin/gui/connection.rb +0 -70
- data/lib/bitcoin/gui/em_gtk.rb +0 -30
- data/lib/bitcoin/gui/gui.builder +0 -1643
- data/lib/bitcoin/gui/gui.rb +0 -292
- data/lib/bitcoin/gui/helpers.rb +0 -115
- data/lib/bitcoin/gui/tree_view.rb +0 -84
- data/lib/bitcoin/gui/tx_view.rb +0 -69
- data/lib/bitcoin/namecoin.rb +0 -280
- data/lib/bitcoin/network/command_client.rb +0 -104
- data/lib/bitcoin/network/command_handler.rb +0 -570
- data/lib/bitcoin/network/connection_handler.rb +0 -387
- data/lib/bitcoin/network/node.rb +0 -565
- data/lib/bitcoin/storage/dummy/dummy_store.rb +0 -179
- data/lib/bitcoin/storage/models.rb +0 -171
- data/lib/bitcoin/storage/sequel/migrations.rb +0 -99
- data/lib/bitcoin/storage/sequel/migrations/001_base_schema.rb +0 -52
- data/lib/bitcoin/storage/sequel/migrations/002_tx.rb +0 -45
- data/lib/bitcoin/storage/sequel/migrations/003_change_txin_script_sig_to_blob.rb +0 -18
- data/lib/bitcoin/storage/sequel/migrations/004_change_txin_prev_out_to_blob.rb +0 -18
- data/lib/bitcoin/storage/sequel/migrations/005_change_tx_hash_to_bytea.rb +0 -14
- data/lib/bitcoin/storage/sequel/migrations/006_add_tx_nhash.rb +0 -31
- data/lib/bitcoin/storage/sequel/migrations/007_add_prev_out_index_index.rb +0 -16
- data/lib/bitcoin/storage/sequel/migrations/008_add_txin_p2sh_type.rb +0 -31
- data/lib/bitcoin/storage/sequel/migrations/009_add_addrs_type.rb +0 -56
- data/lib/bitcoin/storage/sequel/sequel_store.rb +0 -551
- data/lib/bitcoin/storage/storage.rb +0 -517
- data/lib/bitcoin/storage/utxo/migrations/001_base_schema.rb +0 -52
- data/lib/bitcoin/storage/utxo/migrations/002_utxo.rb +0 -18
- data/lib/bitcoin/storage/utxo/migrations/003_update_indices.rb +0 -14
- data/lib/bitcoin/storage/utxo/migrations/004_add_addrs_type.rb +0 -14
- data/lib/bitcoin/storage/utxo/utxo_store.rb +0 -374
- data/lib/bitcoin/validation.rb +0 -400
- data/lib/bitcoin/wallet/coinselector.rb +0 -33
- data/lib/bitcoin/wallet/keygenerator.rb +0 -77
- data/lib/bitcoin/wallet/keystore.rb +0 -207
- data/lib/bitcoin/wallet/txdp.rb +0 -118
- data/lib/bitcoin/wallet/wallet.rb +0 -281
- data/spec/bitcoin/fixtures/freicoin-block-000000005d231b285e63af83edae2d8f5e50e70d396468643092b9239fd3be3c.bin +0 -0
- data/spec/bitcoin/fixtures/freicoin-block-000000005d231b285e63af83edae2d8f5e50e70d396468643092b9239fd3be3c.json +0 -43
- data/spec/bitcoin/fixtures/freicoin-genesis-block-000000005b1e3d23ecfd2dd4a6e1a35238aa0392c0a8528c40df52376d7efe2c.bin +0 -0
- data/spec/bitcoin/fixtures/freicoin-genesis-block-000000005b1e3d23ecfd2dd4a6e1a35238aa0392c0a8528c40df52376d7efe2c.json +0 -67
- data/spec/bitcoin/namecoin_spec.rb +0 -182
- data/spec/bitcoin/node/command_api_spec.rb +0 -663
- data/spec/bitcoin/storage/models_spec.rb +0 -104
- data/spec/bitcoin/storage/reorg_spec.rb +0 -236
- data/spec/bitcoin/storage/storage_spec.rb +0 -387
- data/spec/bitcoin/storage/validation_spec.rb +0 -300
- data/spec/bitcoin/wallet/coinselector_spec.rb +0 -38
- data/spec/bitcoin/wallet/keygenerator_spec.rb +0 -69
- data/spec/bitcoin/wallet/keystore_spec.rb +0 -190
- data/spec/bitcoin/wallet/txdp_spec.rb +0 -76
- data/spec/bitcoin/wallet/wallet_spec.rb +0 -238
data/lib/bitcoin/gui/gui.rb
DELETED
@@ -1,292 +0,0 @@
|
|
1
|
-
# encoding: ascii-8bit
|
2
|
-
|
3
|
-
require_relative "em_gtk.rb"
|
4
|
-
require_relative "helpers.rb"
|
5
|
-
require_relative "tree_view.rb"
|
6
|
-
require_relative "addr_view.rb"
|
7
|
-
require_relative "tx_view.rb"
|
8
|
-
require_relative "conn_view.rb"
|
9
|
-
|
10
|
-
Gtk.init
|
11
|
-
|
12
|
-
module Bitcoin::Gui
|
13
|
-
|
14
|
-
class Gui
|
15
|
-
|
16
|
-
include Helpers
|
17
|
-
|
18
|
-
attr_reader :builder, :wallet, :storage
|
19
|
-
attr_accessor :node, :addr_view, :conn_view
|
20
|
-
|
21
|
-
def initialize storage, wallet_file = nil
|
22
|
-
@storage = storage
|
23
|
-
@node = nil
|
24
|
-
build
|
25
|
-
@addr_view = AddrView.new(self)
|
26
|
-
@tx_view = TxView.new(self, :tx_view)
|
27
|
-
@conn_view = ConnView.new(self)
|
28
|
-
open_wallet(wallet_file) if wallet_file
|
29
|
-
main_window.show_all
|
30
|
-
# notebook.next_page
|
31
|
-
statusicon.tooltip_text = "Bitcoin-Ruby GUI"
|
32
|
-
GObject.signal_connect(statusicon, "activate") do
|
33
|
-
main_window.visible ? main_window.hide : main_window.show
|
34
|
-
end
|
35
|
-
GObject.signal_connect(statusicon, "popup-menu") do
|
36
|
-
popup_menu.popup_for_device(nil, nil, nil, ->(*a) {}, nil, nil, 0, 0)
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
def log
|
41
|
-
@log ||= Bitcoin::Logger.create(:gui)
|
42
|
-
end
|
43
|
-
|
44
|
-
def build
|
45
|
-
@builder = Gtk::Builder.new
|
46
|
-
@builder.add_from_file(File.join(File.dirname(__FILE__), "gui.builder"))
|
47
|
-
@builder.connect_signals_full(->(builder, widget, signal, handler, _, _, gui) do
|
48
|
-
GObject.signal_connect(widget, signal) { gui.send(handler) }
|
49
|
-
end, self)
|
50
|
-
|
51
|
-
{
|
52
|
-
"<Control>n" => :file_new,
|
53
|
-
"<Control>o" => :file_open,
|
54
|
-
"<Control>q" => :file_quit,
|
55
|
-
"<Control>c" => :edit_copy,
|
56
|
-
"<Control>v" => :edit_paste,
|
57
|
-
"<Control>p" => :edit_preferences,
|
58
|
-
"<Control>h" => :help_about,
|
59
|
-
}.each do |binding, action|
|
60
|
-
send("menu_#{action}").add_accelerator("activate", accelgroup1,
|
61
|
-
*Gtk.accelerator_parse(binding), 0)
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
def update_wallet_views
|
66
|
-
return unless @wallet
|
67
|
-
EM.defer do
|
68
|
-
@addr_view.update(@wallet.keystore.keys)#.select{|k| k[:mine] == true})
|
69
|
-
@tx_view.update(@wallet.get_txouts(true))
|
70
|
-
unconfirmed = check_unconfirmed.active
|
71
|
-
wallet_text = "wallet: #{@wallet.keystore.config[:file]} | " +
|
72
|
-
"addresses: #{@wallet.addrs.size} | " +
|
73
|
-
"balance: #{"%.8f" % (@wallet.get_balance(unconfirmed) / 1e8)}"
|
74
|
-
status_wallet.push 0, wallet_text
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
def on_check_unconfirmed_toggled
|
79
|
-
update_wallet_views
|
80
|
-
end
|
81
|
-
|
82
|
-
def on_preferences
|
83
|
-
dialog(:preferences, :setup => ->(d) {
|
84
|
-
config = Bitcoin::Config.load({}, :wallet)
|
85
|
-
model = preferences_box_network.get_model
|
86
|
-
row = model.append
|
87
|
-
model.set_value(row, 0, "foo")
|
88
|
-
preferences_box_network.set_model model
|
89
|
-
# preferences_entry_network.text = config[:network]
|
90
|
-
}) do |*a|
|
91
|
-
p a
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
def on_copy_addr
|
96
|
-
addrs = []
|
97
|
-
valid, i = @addr_view.model.get_iter_first
|
98
|
-
while valid
|
99
|
-
if @addr_view.view.selection.iter_is_selected(i)
|
100
|
-
a = @addr_view.model.get_value(i, 0).get_string
|
101
|
-
addrs << a
|
102
|
-
end
|
103
|
-
valid = @addr_view.model.iter_next(i.to_ptr)
|
104
|
-
end
|
105
|
-
|
106
|
-
return unless addrs.any?
|
107
|
-
text = addrs.join(", ")
|
108
|
-
c = Gtk::Clipboard.get(Gdk::Atom.intern("PRIMARY", false))
|
109
|
-
c.set_text text, text.size
|
110
|
-
c = Gtk::Clipboard.get(Gdk::Atom.intern("CLIPBOARD", false))
|
111
|
-
c.set_text text, text.size
|
112
|
-
end
|
113
|
-
|
114
|
-
def on_paste_addr
|
115
|
-
c = Gtk::Clipboard.get(Gdk::Atom.intern("PRIMARY", false))
|
116
|
-
c.request_text ->(clip, text, data) {
|
117
|
-
on_new_addr(text) if Bitcoin.valid_address?(text)
|
118
|
-
}, self
|
119
|
-
c = Gtk::Clipboard.get(Gdk::Atom.intern("CLIPBOARD", false))
|
120
|
-
c.request_text ->(clip, text, data) {
|
121
|
-
on_new_addr(text) if Bitcoin.valid_address?(text)
|
122
|
-
}, self
|
123
|
-
end
|
124
|
-
|
125
|
-
def on_new_addr addr = nil
|
126
|
-
dialog(:new_addr, setup: ->(d) {
|
127
|
-
new_addr_check_addr.active = addr ? true : false
|
128
|
-
new_addr_check_pubkey.active = false
|
129
|
-
new_addr_check_mine.active = addr ? false : true
|
130
|
-
new_addr_entry_label.text = ""
|
131
|
-
new_addr_entry_addr.text = addr ? addr : ""
|
132
|
-
new_addr_entry_pubkey.text = ""
|
133
|
-
new_addr_entry_addr.hide unless addr
|
134
|
-
new_addr_entry_pubkey.hide
|
135
|
-
GObject.signal_connect(new_addr_check_addr, "toggled") do
|
136
|
-
new_addr_check_addr.active ? new_addr_entry_addr.show :
|
137
|
-
new_addr_entry_addr.hide
|
138
|
-
end
|
139
|
-
GObject.signal_connect(new_addr_check_pubkey, "toggled") do
|
140
|
-
new_addr_check_pubkey.active ? new_addr_entry_pubkey.show :
|
141
|
-
new_addr_entry_pubkey.hide
|
142
|
-
end
|
143
|
-
}) do |*a|
|
144
|
-
begin
|
145
|
-
label = new_addr_entry_label.text
|
146
|
-
set_address = new_addr_check_addr.active
|
147
|
-
set_pubkey = new_addr_check_pubkey.active
|
148
|
-
is_mine = new_addr_check_mine.active
|
149
|
-
key = {:label => label}
|
150
|
-
if set_address
|
151
|
-
addr = new_addr_entry_addr.text
|
152
|
-
raise "Address #{addr} invalid" unless Bitcoin.valid_address?(addr)
|
153
|
-
key[:addr] = addr
|
154
|
-
end
|
155
|
-
if set_pubkey
|
156
|
-
k = Bitcoin::Key.new(nil, new_addr_entry_pubkey.text)
|
157
|
-
key[:key] = k
|
158
|
-
key[:addr] = k.addr
|
159
|
-
end
|
160
|
-
if !set_address && !set_pubkey
|
161
|
-
key[:key] = Bitcoin::Key.generate
|
162
|
-
key[:addr] = key[:key].addr
|
163
|
-
end
|
164
|
-
key[:mine] = is_mine
|
165
|
-
@wallet.add_key(key)
|
166
|
-
update_wallet_views
|
167
|
-
rescue
|
168
|
-
message(:error, "Error adding key", $!.message, [:ok]) do
|
169
|
-
new_addr_dialog.show
|
170
|
-
end
|
171
|
-
end
|
172
|
-
update_addr_store
|
173
|
-
end
|
174
|
-
end
|
175
|
-
|
176
|
-
def on_new_tx
|
177
|
-
dialog(:new_tx, :setup => ->(d) {
|
178
|
-
new_tx_entry_address.text = ""
|
179
|
-
new_tx_entry_amount.text = ""
|
180
|
-
model = Gtk::ListStore.new([GObject::TYPE_STRING, GObject::TYPE_STRING])
|
181
|
-
@wallet.keystore.keys.each do |key|
|
182
|
-
row = model.append
|
183
|
-
model.set_value(row, 0, key[:label] || "")
|
184
|
-
model.set_value(row, 1, key[:addr])
|
185
|
-
end
|
186
|
-
renderer = Gtk::CellRendererText.new
|
187
|
-
comp = Gtk::EntryCompletion.new_with_area(area)
|
188
|
-
comp.text_column = 1
|
189
|
-
comp.minimum_key_length = 1
|
190
|
-
comp.set_match_func(->(comp, text, iter, _) {
|
191
|
-
label = comp.get_model.value(iter, 0).get_string
|
192
|
-
addr = comp.get_model.value(iter, 1).get_string
|
193
|
-
!!(label =~ /#{text}/ || addr =~ /#{text}/)
|
194
|
-
}, nil, nil)
|
195
|
-
comp.area.pack_start renderer, false, false, false
|
196
|
-
comp.area.orientation = :vertical
|
197
|
-
comp.set_model model
|
198
|
-
renderer.set_padding 10, 0
|
199
|
-
renderer.foreground = "blue"
|
200
|
-
comp.set_cell_data_func(renderer, ->(layout, renderer, model, iter, data) {
|
201
|
-
renderer.text = model.get_value(iter, 0).get_string
|
202
|
-
}, nil, nil)
|
203
|
-
new_tx_entry_address.set_completion comp
|
204
|
-
# GObject.signal_connect(comp, "match-selected") do |comp, _, iter, _|
|
205
|
-
# addr = comp.get_model.get_value(iter, 1).get_string
|
206
|
-
# new_tx_entry_address.text = addr
|
207
|
-
# true
|
208
|
-
# end
|
209
|
-
}) do |dialog|
|
210
|
-
|
211
|
-
address = new_tx_entry_address.text
|
212
|
-
amount = new_tx_entry_amount.text
|
213
|
-
unless Bitcoin.valid_address?(address)
|
214
|
-
message(:error, "Invalid Address",
|
215
|
-
"Address #{address} is not a valid bitcoin address.", [:ok]) do
|
216
|
-
new_tx_dialog.show
|
217
|
-
end
|
218
|
-
next
|
219
|
-
end
|
220
|
-
unless amount =~ /[0-9]*\.[0-9]*/
|
221
|
-
message(:error, "Invalid Amount",
|
222
|
-
"Amount #{amount} can not be parsed. Please use \"0.0\" form.", [:ok]) do
|
223
|
-
new_tx_dialog.show
|
224
|
-
end
|
225
|
-
next
|
226
|
-
end
|
227
|
-
value = (amount.to_f * 1e8).to_i
|
228
|
-
unless value <= @wallet.get_balance
|
229
|
-
message(:error, "Insufficient Balance",
|
230
|
-
"Balance #{@wallet.get_balance} is not sufficient to spend #{value}.", [:ok]) do
|
231
|
-
dialog.show
|
232
|
-
end
|
233
|
-
next
|
234
|
-
end
|
235
|
-
message(:question, "Really send transaction?",
|
236
|
-
"Do you really want to send #{format_value value} to #{address}?", [:no, :yes]) do
|
237
|
-
tx = @wallet.new_tx([[:address, *[address], value]], 0.00)
|
238
|
-
# puts tx.to_json
|
239
|
-
if @node.request(:relay_tx, tx)
|
240
|
-
puts "Transaction #{tx} relayed."
|
241
|
-
end
|
242
|
-
end
|
243
|
-
end
|
244
|
-
end
|
245
|
-
|
246
|
-
def on_new_wallet
|
247
|
-
dialog(:wallet_save, :filters => :wallet, :callbacks => {
|
248
|
-
"update-preview" => method(:wallet_preview)}) do
|
249
|
-
file = wallet_save_dialog.filename.read_string
|
250
|
-
open_wallet(file) unless File.file?(file)
|
251
|
-
end
|
252
|
-
end
|
253
|
-
|
254
|
-
def on_open_wallet
|
255
|
-
dialog(:wallet_open, :filters => :wallet, :callbacks => {
|
256
|
-
"update-preview" => method(:wallet_preview)}) do
|
257
|
-
open_wallet(wallet_open_dialog.filename.read_string)
|
258
|
-
end
|
259
|
-
end
|
260
|
-
|
261
|
-
def on_about
|
262
|
-
dialog(:about)
|
263
|
-
end
|
264
|
-
|
265
|
-
def on_exit
|
266
|
-
puts "bye"
|
267
|
-
Gtk.main_quit
|
268
|
-
EM.stop
|
269
|
-
end
|
270
|
-
|
271
|
-
def open_wallet(file)
|
272
|
-
keystore = Bitcoin::Wallet::SimpleKeyStore.new(:file => file)
|
273
|
-
@wallet = Bitcoin::Wallet::Wallet.new(@storage, keystore,
|
274
|
-
Bitcoin::Wallet::SimpleCoinSelector)
|
275
|
-
@wallet.on_tx do |type, tx|
|
276
|
-
puts "#{type} transaction: #{tx.hash}"
|
277
|
-
update_wallet_views
|
278
|
-
value = tx.out.select {|out| (@wallet.addrs & out.get_addresses).any? }
|
279
|
-
.map(&:value).inject(:+)
|
280
|
-
title = "#{type.to_s.capitalize} transaction"
|
281
|
-
message = "#{tx.hash}\nValue: #{format_value(value)}"
|
282
|
-
Notify.notify title, message
|
283
|
-
end
|
284
|
-
update_wallet_views
|
285
|
-
rescue
|
286
|
-
message(:error, "Error loading wallet", $!.message, [:ok])
|
287
|
-
p $!
|
288
|
-
puts *$@
|
289
|
-
end
|
290
|
-
|
291
|
-
end
|
292
|
-
end
|
data/lib/bitcoin/gui/helpers.rb
DELETED
@@ -1,115 +0,0 @@
|
|
1
|
-
# encoding: ascii-8bit
|
2
|
-
|
3
|
-
module Bitcoin::Gui::Helpers
|
4
|
-
|
5
|
-
def display_tx tx_hash
|
6
|
-
tx = @storage.get_tx(tx_hash)
|
7
|
-
dialog(:tx, setup: ->(d) {
|
8
|
-
tx_label_hash.text = tx.hash
|
9
|
-
tx_label_value.text = format_value(tx.out.map(&:value).inject(:+))
|
10
|
-
tx_label_confirmations.text = tx.confirmations.to_s
|
11
|
-
txin_view = Bitcoin::Gui::TxInView.new(self, :tx_txin_view)
|
12
|
-
# txin_view.update(tx.in)
|
13
|
-
})
|
14
|
-
end
|
15
|
-
|
16
|
-
def wallet_preview(dialog, *args)
|
17
|
-
filename = dialog.preview_filename
|
18
|
-
file = filename.read_string rescue nil
|
19
|
-
if file && File.file?(file)
|
20
|
-
keystore = Bitcoin::Wallet::SimpleKeyStore.new(:file => file)
|
21
|
-
wallet = Bitcoin::Wallet::Wallet.new(@storage, keystore,
|
22
|
-
Bitcoin::Wallet::SimpleCoinSelector)
|
23
|
-
preview = Gtk::Label.new "Keys: #{wallet.addrs.size}\n" +
|
24
|
-
"Balance:\n%.8f" % (wallet.get_balance / 1e8)
|
25
|
-
end
|
26
|
-
dialog.preview_widget = preview
|
27
|
-
end
|
28
|
-
|
29
|
-
def add_wallet_filters dialog
|
30
|
-
filter = Gtk::FileFilter.new
|
31
|
-
filter.name = "Wallet Files"
|
32
|
-
filter.add_pattern("*.json")
|
33
|
-
dialog.add_filter filter
|
34
|
-
|
35
|
-
filter = Gtk::FileFilter.new
|
36
|
-
filter.name = "All Files"
|
37
|
-
filter.add_pattern("*")
|
38
|
-
dialog.add_filter filter
|
39
|
-
end
|
40
|
-
|
41
|
-
def dialog name, opts = {}
|
42
|
-
@dialog_cb_ids ||= {}
|
43
|
-
ids = @dialog_cb_ids[name] || []
|
44
|
-
dialog = send("#{name}_dialog")
|
45
|
-
send("add_#{opts[:filters]}_filters", dialog) if opts[:filters]
|
46
|
-
opts[:setup].call(dialog) if opts[:setup]
|
47
|
-
while id = ids.shift
|
48
|
-
GObject.signal_handler_disconnect(dialog, id)
|
49
|
-
end
|
50
|
-
ids << GObject.signal_connect(dialog, "response") do |dialog, response, *data|
|
51
|
-
yield(dialog, *data) if response > 0
|
52
|
-
dialog.hide
|
53
|
-
end
|
54
|
-
if dialog.is_a?(Gtk::FileChooserDialog)
|
55
|
-
ids << GObject.signal_connect(dialog, "file-activated") do |dialog, *data|
|
56
|
-
yield(dialog, *data)
|
57
|
-
dialog.hide
|
58
|
-
end
|
59
|
-
end
|
60
|
-
(opts[:callbacks] || {}).each do |name, block|
|
61
|
-
ids << GObject.signal_connect(dialog, name) {|*a| block.call(*a) }
|
62
|
-
end
|
63
|
-
dialog.show
|
64
|
-
@dialog_cb_ids[name] = ids
|
65
|
-
rescue
|
66
|
-
p $!
|
67
|
-
puts *$@
|
68
|
-
end
|
69
|
-
|
70
|
-
def message(type, title, text, buttons)
|
71
|
-
dialog(:message, :setup => ->(dialog){
|
72
|
-
dialog.message_type = Gtk::MessageType.find(type.to_sym)
|
73
|
-
dialog.text = title
|
74
|
-
dialog.secondary_text = text
|
75
|
-
[:yes, :no, :ok].each do |n|
|
76
|
-
b = send("message_dialog_button_#{n}")
|
77
|
-
buttons.include?(n) ? b.show : b.hide
|
78
|
-
end
|
79
|
-
}) do |dialog|
|
80
|
-
yield(dialog) if block_given?
|
81
|
-
dialog.show_all
|
82
|
-
dialog.hide
|
83
|
-
end
|
84
|
-
rescue
|
85
|
-
p $!
|
86
|
-
end
|
87
|
-
|
88
|
-
def method_missing name, *args
|
89
|
-
@builder.get_object(name.to_s) rescue super(name, *args)
|
90
|
-
end
|
91
|
-
|
92
|
-
def format_value val
|
93
|
-
"%.8f" % (val / 1e8)
|
94
|
-
end
|
95
|
-
|
96
|
-
def format_address address, label = nil
|
97
|
-
"#{label} (#{address})"
|
98
|
-
end
|
99
|
-
|
100
|
-
def format_version ver
|
101
|
-
ver.insert(-3, '.') if ver.size > 2
|
102
|
-
ver.insert(-6, '.') if ver.size > 5
|
103
|
-
ver.insert(0, "0.") if ver.size <= 7
|
104
|
-
ver
|
105
|
-
end
|
106
|
-
|
107
|
-
def format_uptime started
|
108
|
-
uptime = Time.now.to_i - started
|
109
|
-
mm, ss = uptime.divmod(60) #=> [4515, 21]
|
110
|
-
hh, mm = mm.divmod(60) #=> [75, 15]
|
111
|
-
dd, hh = hh.divmod(24) #=> [3, 3]
|
112
|
-
"%02d:%02d:%02d:%02d" % [dd, hh, mm, ss]
|
113
|
-
end
|
114
|
-
|
115
|
-
end
|
@@ -1,84 +0,0 @@
|
|
1
|
-
# encoding: ascii-8bit
|
2
|
-
|
3
|
-
module Bitcoin::Gui
|
4
|
-
class TreeView
|
5
|
-
|
6
|
-
include Helpers
|
7
|
-
|
8
|
-
attr_accessor :model, :view
|
9
|
-
|
10
|
-
def initialize gui, view_name, columns
|
11
|
-
@gui = gui
|
12
|
-
@view = @gui.builder.get_object(view_name.to_s)
|
13
|
-
@model = Gtk::TreeStore.new(columns.map{|c| c[0] })
|
14
|
-
@view.set_model @model
|
15
|
-
|
16
|
-
columns.each_with_index do |cdef, i|
|
17
|
-
type, label, cb = *cdef
|
18
|
-
next unless label
|
19
|
-
case type
|
20
|
-
when GObject::TYPE_BOOLEAN
|
21
|
-
renderer = Gtk::CellRendererToggle.new
|
22
|
-
col = tree_view_col(renderer, label, "active", i) do |*args|
|
23
|
-
method(cb).call(@model, i, args[1], args[3]) if cb
|
24
|
-
end
|
25
|
-
when GObject::TYPE_STRING, GObject::TYPE_INT
|
26
|
-
renderer = Gtk::CellRendererText.new
|
27
|
-
col = tree_view_col(renderer, label, "text", i) do |*args|
|
28
|
-
method(cb).call(@model, i, args[1], args[3]) if cb
|
29
|
-
end
|
30
|
-
end
|
31
|
-
@view.append_column(col)
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
def embed name
|
36
|
-
parent = @gui.builder.get_object(name.to_s).parent
|
37
|
-
parent.remove(parent.get_child)
|
38
|
-
parent.add(@view)
|
39
|
-
end
|
40
|
-
|
41
|
-
def tree_view_col renderer, title, key, val, &block
|
42
|
-
col = Gtk::TreeViewColumn.new
|
43
|
-
col.pack_start renderer, true
|
44
|
-
col.add_attribute renderer, key, val
|
45
|
-
col.set_title title
|
46
|
-
col.set_cell_data_func(renderer, block, nil, nil)
|
47
|
-
col
|
48
|
-
end
|
49
|
-
|
50
|
-
def format_address_col model, i, renderer, iter
|
51
|
-
address = model.get_value(iter, i).get_string
|
52
|
-
label = model.get_value(iter, i+1).get_string
|
53
|
-
renderer.text = format_address(address, label)
|
54
|
-
end
|
55
|
-
|
56
|
-
def format_value_col model, i, renderer, iter
|
57
|
-
val = model.get_value(iter, i).get_string.to_i
|
58
|
-
renderer.text = format_value(val)
|
59
|
-
if val > 0
|
60
|
-
renderer.foreground = "darkgreen"
|
61
|
-
elsif val < 0
|
62
|
-
renderer.foreground = "red"
|
63
|
-
else
|
64
|
-
renderer.foreground = "black"
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
def format_version_col model, i, renderer, iter
|
69
|
-
ver = model.get_value(iter, i).get_int.to_s
|
70
|
-
renderer.text = format_version(ver)
|
71
|
-
end
|
72
|
-
|
73
|
-
def format_uptime_col model, i, renderer, iter
|
74
|
-
started = model.get_value(iter, i).get_int
|
75
|
-
renderer.text = format_uptime(started)
|
76
|
-
end
|
77
|
-
|
78
|
-
def format_bool_col model, i, renderer, iter
|
79
|
-
active = model.get_value(iter, i).get_boolean
|
80
|
-
renderer.set_active active
|
81
|
-
end
|
82
|
-
|
83
|
-
end
|
84
|
-
end
|