glueby 0.3.0 → 0.4.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +35 -0
- data/Gemfile +1 -0
- data/README.md +227 -16
- data/glueby.gemspec +3 -2
- data/lib/generators/glueby/contract/reissuable_token_generator.rb +26 -0
- data/lib/generators/glueby/contract/templates/initializer.rb.erb +7 -2
- data/lib/generators/glueby/contract/templates/key_table.rb.erb +4 -3
- data/lib/generators/glueby/contract/templates/reissuable_token_table.rb.erb +10 -0
- data/lib/generators/glueby/contract/templates/system_information_table.rb.erb +2 -2
- data/lib/generators/glueby/contract/templates/timestamp_table.rb.erb +1 -1
- data/lib/generators/glueby/contract/templates/utxo_table.rb.erb +3 -2
- data/lib/generators/glueby/contract/templates/wallet_table.rb.erb +2 -2
- data/lib/glueby/block_syncer.rb +98 -0
- data/lib/glueby/configuration.rb +62 -0
- data/lib/glueby/contract/active_record/reissuable_token.rb +26 -0
- data/lib/glueby/contract/active_record.rb +1 -0
- data/lib/glueby/contract/fee_estimator.rb +38 -0
- data/lib/glueby/contract/payment.rb +4 -4
- data/lib/glueby/contract/timestamp/syncer.rb +13 -0
- data/lib/glueby/contract/timestamp.rb +8 -6
- data/lib/glueby/contract/token.rb +70 -22
- data/lib/glueby/contract/tx_builder.rb +22 -19
- data/lib/glueby/contract.rb +2 -2
- data/lib/glueby/fee_provider/tasks.rb +141 -0
- data/lib/glueby/fee_provider.rb +73 -0
- data/lib/glueby/generator/migrate_generator.rb +1 -1
- data/lib/glueby/internal/wallet/abstract_wallet_adapter.rb +25 -6
- data/lib/glueby/internal/wallet/active_record/utxo.rb +1 -0
- data/lib/glueby/internal/wallet/active_record/wallet.rb +15 -5
- data/lib/glueby/internal/wallet/active_record_wallet_adapter/syncer.rb +14 -0
- data/lib/glueby/internal/wallet/active_record_wallet_adapter.rb +25 -8
- data/lib/glueby/internal/wallet/errors.rb +3 -0
- data/lib/glueby/internal/wallet/tapyrus_core_wallet_adapter.rb +42 -14
- data/lib/glueby/internal/wallet.rb +56 -13
- data/lib/glueby/railtie.rb +10 -0
- data/lib/glueby/version.rb +1 -1
- data/lib/glueby/wallet.rb +3 -2
- data/lib/glueby.rb +27 -12
- data/lib/tasks/glueby/block_syncer.rake +29 -0
- data/lib/tasks/glueby/contract/timestamp.rake +4 -26
- data/lib/tasks/glueby/fee_provider.rake +18 -0
- metadata +40 -16
- data/.travis.yml +0 -7
- data/lib/glueby/contract/fee_provider.rb +0 -21
- data/lib/tasks/glueby/contract/block_syncer.rake +0 -36
- data/lib/tasks/glueby/contract/wallet_adapter.rake +0 -42
@@ -13,13 +13,16 @@ module Glueby
|
|
13
13
|
|
14
14
|
# @param [Tapyrus::Tx] tx
|
15
15
|
# @param [Array] prevtxs array of outputs
|
16
|
-
|
16
|
+
# @param [Integer] sighashtype
|
17
|
+
def sign(tx, prevtxs = [], sighashtype: Tapyrus::SIGHASH_TYPE[:all])
|
18
|
+
validate_sighashtype!(sighashtype)
|
19
|
+
|
17
20
|
tx.inputs.each.with_index do |input, index|
|
18
21
|
script_pubkey = script_for_input(input, prevtxs)
|
19
22
|
next unless script_pubkey
|
20
23
|
key = Key.key_for_script(script_pubkey)
|
21
24
|
next unless key
|
22
|
-
sign_tx_for_p2pkh(tx, index, key, script_pubkey)
|
25
|
+
sign_tx_for_p2pkh(tx, index, key, script_pubkey, sighashtype)
|
23
26
|
end
|
24
27
|
tx
|
25
28
|
end
|
@@ -30,9 +33,9 @@ module Glueby
|
|
30
33
|
|
31
34
|
private
|
32
35
|
|
33
|
-
def sign_tx_for_p2pkh(tx, index, key, script_pubkey)
|
34
|
-
sighash = tx.sighash_for_input(index, script_pubkey)
|
35
|
-
sig = key.sign(sighash) + [
|
36
|
+
def sign_tx_for_p2pkh(tx, index, key, script_pubkey, sighashtype)
|
37
|
+
sighash = tx.sighash_for_input(index, script_pubkey, hash_type: sighashtype)
|
38
|
+
sig = key.sign(sighash) + [sighashtype].pack('C')
|
36
39
|
script_sig = Tapyrus::Script.parse_from_payload(Tapyrus::Script.pack_pushdata(sig) + Tapyrus::Script.pack_pushdata(key.public_key.htb))
|
37
40
|
tx.inputs[index].script_sig = script_sig
|
38
41
|
end
|
@@ -47,6 +50,13 @@ module Glueby
|
|
47
50
|
Tapyrus::Script.parse_from_payload(output[:scriptPubKey].htb) if output
|
48
51
|
end
|
49
52
|
end
|
53
|
+
|
54
|
+
def validate_sighashtype!(sighashtype)
|
55
|
+
hash_type = sighashtype & (~(Tapyrus::SIGHASH_TYPE[:anyonecanpay]))
|
56
|
+
if hash_type < Tapyrus::SIGHASH_TYPE[:all] || hash_type > Tapyrus::SIGHASH_TYPE[:single]
|
57
|
+
raise Errors::InvalidSighashType, "Invalid sighash type '#{sighashtype}'"
|
58
|
+
end
|
59
|
+
end
|
50
60
|
end
|
51
61
|
end
|
52
62
|
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Glueby
|
2
|
+
module Internal
|
3
|
+
class Wallet
|
4
|
+
class ActiveRecordWalletAdapter
|
5
|
+
class Syncer
|
6
|
+
def tx_sync(tx)
|
7
|
+
Glueby::Internal::Wallet::AR::Utxo.destroy_for_inputs(tx)
|
8
|
+
Glueby::Internal::Wallet::AR::Utxo.create_or_update_for_outputs(tx)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -54,9 +54,16 @@ module Glueby
|
|
54
54
|
# alice_wallet.balances
|
55
55
|
# ```
|
56
56
|
class ActiveRecordWalletAdapter < AbstractWalletAdapter
|
57
|
-
|
58
|
-
|
59
|
-
|
57
|
+
|
58
|
+
autoload :Syncer, 'glueby/internal/wallet/active_record_wallet_adapter/syncer'
|
59
|
+
|
60
|
+
def create_wallet(wallet_id = nil)
|
61
|
+
wallet_id = SecureRandom.hex(16) unless wallet_id
|
62
|
+
begin
|
63
|
+
AR::Wallet.create!(wallet_id: wallet_id)
|
64
|
+
rescue ActiveRecord::RecordInvalid => _
|
65
|
+
raise Errors::WalletAlreadyCreated, "wallet_id '#{wallet_id}' is already exists"
|
66
|
+
end
|
60
67
|
wallet_id
|
61
68
|
end
|
62
69
|
|
@@ -65,6 +72,7 @@ module Glueby
|
|
65
72
|
end
|
66
73
|
|
67
74
|
def load_wallet(wallet_id)
|
75
|
+
raise Errors::WalletNotFound, "Wallet #{wallet_id} does not found" unless AR::Wallet.where(wallet_id: wallet_id).exists?
|
68
76
|
end
|
69
77
|
|
70
78
|
def unload_wallet(wallet_id)
|
@@ -81,10 +89,12 @@ module Glueby
|
|
81
89
|
utxos.sum(&:value)
|
82
90
|
end
|
83
91
|
|
84
|
-
def list_unspent(wallet_id, only_finalized = true)
|
92
|
+
def list_unspent(wallet_id, only_finalized = true, label = nil)
|
85
93
|
wallet = AR::Wallet.find_by(wallet_id: wallet_id)
|
86
94
|
utxos = wallet.utxos
|
87
95
|
utxos = utxos.where(status: :finalized) if only_finalized
|
96
|
+
utxos = utxos.where(label: label) if label && (label != :unlabeled)
|
97
|
+
utxos = utxos.where(label: nil) if label == :unlabeled
|
88
98
|
utxos.map do |utxo|
|
89
99
|
{
|
90
100
|
txid: utxo.txid,
|
@@ -97,9 +107,9 @@ module Glueby
|
|
97
107
|
end
|
98
108
|
end
|
99
109
|
|
100
|
-
def sign_tx(wallet_id, tx, prevtxs = [])
|
110
|
+
def sign_tx(wallet_id, tx, prevtxs = [], sighashtype: Tapyrus::SIGHASH_TYPE[:all])
|
101
111
|
wallet = AR::Wallet.find_by(wallet_id: wallet_id)
|
102
|
-
wallet.sign(tx, prevtxs)
|
112
|
+
wallet.sign(tx, prevtxs, sighashtype: sighashtype)
|
103
113
|
end
|
104
114
|
|
105
115
|
def broadcast(wallet_id, tx)
|
@@ -110,9 +120,9 @@ module Glueby
|
|
110
120
|
end
|
111
121
|
end
|
112
122
|
|
113
|
-
def receive_address(wallet_id)
|
123
|
+
def receive_address(wallet_id, label = nil)
|
114
124
|
wallet = AR::Wallet.find_by(wallet_id: wallet_id)
|
115
|
-
key = wallet.keys.create(purpose: :receive)
|
125
|
+
key = wallet.keys.create(purpose: :receive, label: label)
|
116
126
|
key.address
|
117
127
|
end
|
118
128
|
|
@@ -127,6 +137,13 @@ module Glueby
|
|
127
137
|
key = wallet.keys.create(purpose: :receive)
|
128
138
|
Tapyrus::Key.new(pubkey: key.public_key)
|
129
139
|
end
|
140
|
+
|
141
|
+
def get_addresses(wallet_id, label = nil)
|
142
|
+
wallet = AR::Wallet.find_by(wallet_id: wallet_id)
|
143
|
+
keys = wallet.keys
|
144
|
+
keys = keys.where(label: label) if label
|
145
|
+
keys.map(&:address)
|
146
|
+
end
|
130
147
|
end
|
131
148
|
end
|
132
149
|
end
|
@@ -5,6 +5,9 @@ module Glueby
|
|
5
5
|
class ShouldInitializeWalletAdapter < StandardError; end
|
6
6
|
class WalletUnloaded < StandardError; end
|
7
7
|
class WalletAlreadyLoaded < StandardError; end
|
8
|
+
class WalletAlreadyCreated < StandardError; end
|
9
|
+
class WalletNotFound < StandardError; end
|
10
|
+
class InvalidSighashType < StandardError; end
|
8
11
|
end
|
9
12
|
end
|
10
13
|
end
|
@@ -28,9 +28,18 @@ module Glueby
|
|
28
28
|
RPC_WALLET_ERROR_ERROR_CODE = -4 # Unspecified problem with wallet (key not found etc.)
|
29
29
|
RPC_WALLET_NOT_FOUND_ERROR_CODE = -18 # Invalid wallet specified
|
30
30
|
|
31
|
-
def create_wallet
|
32
|
-
wallet_id = SecureRandom.hex(16)
|
33
|
-
|
31
|
+
def create_wallet(wallet_id = nil)
|
32
|
+
wallet_id = SecureRandom.hex(16) unless wallet_id
|
33
|
+
begin
|
34
|
+
RPC.client.createwallet(wallet_name(wallet_id))
|
35
|
+
rescue Tapyrus::RPC::Error => ex
|
36
|
+
if ex.rpc_error && ex.rpc_error['code'] == RPC_WALLET_ERROR_ERROR_CODE && /Wallet wallet-#{wallet_id} already exists\./ =~ ex.rpc_error['message']
|
37
|
+
raise Errors::WalletAlreadyCreated, "Wallet #{wallet_id} has been already created."
|
38
|
+
else
|
39
|
+
raise ex
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
34
43
|
wallet_id
|
35
44
|
end
|
36
45
|
|
@@ -42,10 +51,11 @@ module Glueby
|
|
42
51
|
|
43
52
|
def load_wallet(wallet_id)
|
44
53
|
RPC.client.loadwallet(wallet_name(wallet_id))
|
45
|
-
rescue
|
46
|
-
|
47
|
-
if json.is_a?(Hash) && json['code'] == RPC_WALLET_ERROR_ERROR_CODE && /Duplicate -wallet filename specified/ =~ ex.message
|
54
|
+
rescue Tapyrus::RPC::Error => ex
|
55
|
+
if ex.rpc_error && ex.rpc_error['code'] == RPC_WALLET_ERROR_ERROR_CODE && /Duplicate -wallet filename specified/ =~ ex.rpc_error['message']
|
48
56
|
raise Errors::WalletAlreadyLoaded, "Wallet #{wallet_id} has been already loaded."
|
57
|
+
elsif ex.rpc_error && ex.rpc_error['code'] == RPC_WALLET_NOT_FOUND_ERROR_CODE
|
58
|
+
raise Errors::WalletNotFound, "Wallet #{wallet_id} does not found"
|
49
59
|
else
|
50
60
|
raise ex
|
51
61
|
end
|
@@ -73,11 +83,14 @@ module Glueby
|
|
73
83
|
end
|
74
84
|
end
|
75
85
|
|
76
|
-
def list_unspent(wallet_id, only_finalized = true)
|
86
|
+
def list_unspent(wallet_id, only_finalized = true, label = nil)
|
77
87
|
perform_as(wallet_id) do |client|
|
78
88
|
min_conf = only_finalized ? 1 : 0
|
79
89
|
res = client.listunspent(min_conf)
|
80
90
|
|
91
|
+
res = res.filter { |i| i['label'] == label } if label && (label != :unlabeled)
|
92
|
+
res = res.filter { |i| i['label'] == "" } if label == :unlabeled
|
93
|
+
|
81
94
|
res.map do |i|
|
82
95
|
script = Tapyrus::Script.parse_from_payload(i['scriptPubKey'].htb)
|
83
96
|
color_id = if script.cp2pkh? || script.cp2sh?
|
@@ -95,9 +108,9 @@ module Glueby
|
|
95
108
|
end
|
96
109
|
end
|
97
110
|
|
98
|
-
def sign_tx(wallet_id, tx, prevtxs = [])
|
111
|
+
def sign_tx(wallet_id, tx, prevtxs = [], sighashtype: Tapyrus::SIGHASH_TYPE[:all])
|
99
112
|
perform_as(wallet_id) do |client|
|
100
|
-
res = client.signrawtransactionwithwallet(tx.to_hex, prevtxs)
|
113
|
+
res = client.signrawtransactionwithwallet(tx.to_hex, prevtxs, encode_sighashtype(sighashtype))
|
101
114
|
if res['complete']
|
102
115
|
Tapyrus::Tx.parse_from_payload(res['hex'].htb)
|
103
116
|
else
|
@@ -112,9 +125,9 @@ module Glueby
|
|
112
125
|
end
|
113
126
|
end
|
114
127
|
|
115
|
-
def receive_address(wallet_id)
|
128
|
+
def receive_address(wallet_id, label = nil)
|
116
129
|
perform_as(wallet_id) do |client|
|
117
|
-
client.getnewaddress('', ADDRESS_TYPE)
|
130
|
+
client.getnewaddress(label || '', ADDRESS_TYPE)
|
118
131
|
end
|
119
132
|
end
|
120
133
|
|
@@ -138,9 +151,8 @@ module Glueby
|
|
138
151
|
RPC.perform_as(wallet_name(wallet_id)) do |client|
|
139
152
|
begin
|
140
153
|
yield(client)
|
141
|
-
rescue
|
142
|
-
|
143
|
-
if json.is_a?(Hash) && json['code'] == RPC_WALLET_NOT_FOUND_ERROR_CODE
|
154
|
+
rescue Tapyrus::RPC::Error => ex
|
155
|
+
if ex.rpc_error && ex.rpc_error['code'] == RPC_WALLET_NOT_FOUND_ERROR_CODE
|
144
156
|
raise Errors::WalletUnloaded, "The wallet #{wallet_id} is unloaded. You should load before use it."
|
145
157
|
else
|
146
158
|
raise ex
|
@@ -152,6 +164,22 @@ module Glueby
|
|
152
164
|
def wallet_name(wallet_id)
|
153
165
|
"#{WALLET_PREFIX}#{wallet_id}"
|
154
166
|
end
|
167
|
+
|
168
|
+
def encode_sighashtype(sighashtype)
|
169
|
+
type = case sighashtype & (~(Tapyrus::SIGHASH_TYPE[:anyonecanpay]))
|
170
|
+
when Tapyrus::SIGHASH_TYPE[:all] then 'ALL'
|
171
|
+
when Tapyrus::SIGHASH_TYPE[:none] then 'NONE'
|
172
|
+
when Tapyrus::SIGHASH_TYPE[:single] then 'SIGNLE'
|
173
|
+
else
|
174
|
+
raise Errors::InvalidSighashType, "Invalid sighash type '#{sighashtype}'"
|
175
|
+
end
|
176
|
+
|
177
|
+
if sighashtype & Tapyrus::SIGHASH_TYPE[:anyonecanpay] == 0x80
|
178
|
+
type += '|ANYONECANPAY'
|
179
|
+
end
|
180
|
+
|
181
|
+
type
|
182
|
+
end
|
155
183
|
end
|
156
184
|
end
|
157
185
|
end
|
@@ -34,10 +34,13 @@ module Glueby
|
|
34
34
|
autoload :Errors, 'glueby/internal/wallet/errors'
|
35
35
|
|
36
36
|
class << self
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
37
|
+
def create(wallet_id = nil)
|
38
|
+
begin
|
39
|
+
wallet_id = wallet_adapter.create_wallet(wallet_id)
|
40
|
+
rescue Errors::WalletAlreadyCreated => _
|
41
|
+
# Ignore when wallet is already created.
|
42
|
+
end
|
43
|
+
new(wallet_id)
|
41
44
|
end
|
42
45
|
|
43
46
|
def load(wallet_id)
|
@@ -53,6 +56,16 @@ module Glueby
|
|
53
56
|
wallet_adapter.wallets.map { |id| new(id) }
|
54
57
|
end
|
55
58
|
|
59
|
+
def wallet_adapter=(adapter)
|
60
|
+
if adapter.is_a?(ActiveRecordWalletAdapter)
|
61
|
+
BlockSyncer.register_syncer(ActiveRecordWalletAdapter::Syncer)
|
62
|
+
else
|
63
|
+
BlockSyncer.unregister_syncer(ActiveRecordWalletAdapter::Syncer)
|
64
|
+
end
|
65
|
+
|
66
|
+
@wallet_adapter = adapter
|
67
|
+
end
|
68
|
+
|
56
69
|
def wallet_adapter
|
57
70
|
@wallet_adapter or
|
58
71
|
raise Errors::ShouldInitializeWalletAdapter, 'You should initialize wallet adapter using `Glueby::Internal::Wallet.wallet_adapter = some wallet adapter instance`.'
|
@@ -69,24 +82,50 @@ module Glueby
|
|
69
82
|
wallet_adapter.balance(id, only_finalized)
|
70
83
|
end
|
71
84
|
|
72
|
-
|
73
|
-
|
85
|
+
# @param only_finalized [Boolean] The flag to get a UTXO with status only finalized
|
86
|
+
# @param label [String] This label is used to filtered the UTXOs with labeled if a key or Utxo is labeled.
|
87
|
+
# - If label is not specified (label=nil), all UTXOs will be returned.
|
88
|
+
# - If label=:unlabeled, only unlabeled UTXOs will be returned.
|
89
|
+
def list_unspent(only_finalized = true, label = nil)
|
90
|
+
wallet_adapter.list_unspent(id, only_finalized, label)
|
74
91
|
end
|
75
92
|
|
76
93
|
def delete
|
77
94
|
wallet_adapter.delete_wallet(id)
|
78
95
|
end
|
79
96
|
|
80
|
-
|
81
|
-
|
97
|
+
# @param [Tapyrus::Tx] tx The tx that is signed
|
98
|
+
# @param [Array<Hash>] prev_txs An array of hash that represents unbroadcasted transaction outputs used by signing tx
|
99
|
+
# @option prev_txs [String] :txid
|
100
|
+
# @option prev_txs [Integer] :vout
|
101
|
+
# @option prev_txs [String] :scriptPubkey
|
102
|
+
# @option prev_txs [Integer] :amount
|
103
|
+
# @param [Boolean] for_fee_provider_input The flag to notify whether the caller is FeeProvider and called for signing a input that is by FeeProvider.
|
104
|
+
def sign_tx(tx, prev_txs = [], for_fee_provider_input: false)
|
105
|
+
sighashtype = Tapyrus::SIGHASH_TYPE[:all]
|
106
|
+
|
107
|
+
if !for_fee_provider_input && Glueby.configuration.fee_provider_bears?
|
108
|
+
sighashtype |= Tapyrus::SIGHASH_TYPE[:anyonecanpay]
|
109
|
+
end
|
110
|
+
|
111
|
+
wallet_adapter.sign_tx(id, tx, prev_txs, sighashtype: sighashtype)
|
82
112
|
end
|
83
113
|
|
84
|
-
|
114
|
+
# Broadcast a transaction via Tapyrus Core RPC
|
115
|
+
# @param [Tapyrus::Tx] tx The tx that would be broadcasted
|
116
|
+
# @option [Boolean] without_fee_provider The flag to avoid to use FeeProvider temporary.
|
117
|
+
# @param [Proc] block The block that is called before broadcasting. It can be used to handle tx that is modified by FeeProvider.
|
118
|
+
def broadcast(tx, without_fee_provider: false, &block)
|
119
|
+
tx = FeeProvider.provide(tx) if !without_fee_provider && Glueby.configuration.fee_provider_bears?
|
120
|
+
|
121
|
+
block.call(tx) if block
|
122
|
+
|
85
123
|
wallet_adapter.broadcast(id, tx)
|
124
|
+
tx
|
86
125
|
end
|
87
126
|
|
88
|
-
def receive_address
|
89
|
-
wallet_adapter.receive_address(id)
|
127
|
+
def receive_address(label = nil)
|
128
|
+
wallet_adapter.receive_address(id, label)
|
90
129
|
end
|
91
130
|
|
92
131
|
def change_address
|
@@ -97,8 +136,8 @@ module Glueby
|
|
97
136
|
wallet_adapter.create_pubkey(id)
|
98
137
|
end
|
99
138
|
|
100
|
-
def collect_uncolored_outputs(amount)
|
101
|
-
utxos = list_unspent
|
139
|
+
def collect_uncolored_outputs(amount, label = nil, only_finalized = true)
|
140
|
+
utxos = list_unspent(only_finalized, label)
|
102
141
|
|
103
142
|
utxos.inject([0, []]) do |sum, output|
|
104
143
|
next sum if output[:color_id]
|
@@ -112,6 +151,10 @@ module Glueby
|
|
112
151
|
raise Glueby::Contract::Errors::InsufficientFunds
|
113
152
|
end
|
114
153
|
|
154
|
+
def get_addresses(label = nil)
|
155
|
+
wallet_adapter.get_addresses(id, label)
|
156
|
+
end
|
157
|
+
|
115
158
|
private
|
116
159
|
|
117
160
|
def wallet_adapter
|
data/lib/glueby/version.rb
CHANGED
data/lib/glueby/wallet.rb
CHANGED
@@ -13,6 +13,7 @@ module Glueby
|
|
13
13
|
new(Glueby::Internal::Wallet.load(wallet_id))
|
14
14
|
end
|
15
15
|
|
16
|
+
# @deprecated - Use Glueby.configure instead
|
16
17
|
def configure(config)
|
17
18
|
case config[:adapter]
|
18
19
|
when 'core'
|
@@ -32,8 +33,8 @@ module Glueby
|
|
32
33
|
end
|
33
34
|
|
34
35
|
# @return [HashMap] hash of balances which key is color_id or empty string, and value is amount
|
35
|
-
def balances
|
36
|
-
utxos = @internal_wallet.list_unspent
|
36
|
+
def balances(only_finalized = true)
|
37
|
+
utxos = @internal_wallet.list_unspent(only_finalized)
|
37
38
|
utxos.inject({}) do |balances, output|
|
38
39
|
key = output[:color_id] || ''
|
39
40
|
balances[key] ||= 0
|
data/lib/glueby.rb
CHANGED
@@ -7,18 +7,33 @@ module Glueby
|
|
7
7
|
autoload :Wallet, 'glueby/wallet'
|
8
8
|
autoload :Internal, 'glueby/internal'
|
9
9
|
autoload :AR, 'glueby/active_record'
|
10
|
+
autoload :FeeProvider, 'glueby/fee_provider'
|
11
|
+
autoload :Configuration, 'glueby/configuration'
|
12
|
+
autoload :BlockSyncer, 'glueby/block_syncer'
|
10
13
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
14
|
+
if defined? ::Rails::Railtie
|
15
|
+
require 'glueby/railtie'
|
16
|
+
end
|
17
|
+
|
18
|
+
# Add prefix to activerecord table names
|
19
|
+
def self.table_name_prefix
|
20
|
+
'glueby_'
|
21
|
+
end
|
22
|
+
|
23
|
+
# Returns the global [Configuration](RSpec/Core/Configuration) object.
|
24
|
+
def self.configuration
|
25
|
+
@configuration ||= Glueby::Configuration.new
|
26
|
+
end
|
27
|
+
|
28
|
+
# Yields the global configuration to a block.
|
29
|
+
# @yield [Configuration] global configuration
|
30
|
+
#
|
31
|
+
# @example
|
32
|
+
# Glueby.configure do |config|
|
33
|
+
# config.wallet_adapter = :activerecord
|
34
|
+
# config.rpc_config = { schema: 'http', host: '127.0.0.1', port: 12381, user: 'user', password: 'pass' }
|
35
|
+
# end
|
36
|
+
def self.configure
|
37
|
+
yield configuration if block_given?
|
23
38
|
end
|
24
39
|
end
|