glueby 0.12.0 → 1.1.0
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 +3 -4
- data/README.md +3 -3
- data/glueby.gemspec +2 -1
- data/lib/generators/glueby/contract/templates/initializer.rb.erb +8 -8
- data/lib/generators/glueby/contract/templates/key_table.rb.erb +16 -16
- data/lib/generators/glueby/contract/templates/timestamp_table.rb.erb +2 -0
- data/lib/generators/glueby/contract/templates/token_metadata_table.rb.erb +13 -0
- data/lib/generators/glueby/contract/templates/utxo_table.rb.erb +1 -0
- data/lib/generators/glueby/contract/{reissuable_token_generator.rb → token_generator.rb} +12 -1
- data/lib/glueby/block_syncer.rb +97 -97
- data/lib/glueby/configuration.rb +2 -0
- data/lib/glueby/contract/active_record/timestamp.rb +9 -2
- data/lib/glueby/contract/active_record/token_metadata.rb +8 -0
- data/lib/glueby/contract/active_record.rb +1 -0
- data/lib/glueby/contract/fee_estimator/auto.rb +9 -1
- data/lib/glueby/contract/fee_estimator.rb +12 -5
- data/lib/glueby/contract/timestamp/syncer.rb +1 -1
- data/lib/glueby/contract/timestamp/tx_builder/simple.rb +5 -1
- data/lib/glueby/contract/timestamp.rb +2 -2
- data/lib/glueby/contract/token.rb +161 -80
- data/lib/glueby/contract/tx_builder.rb +104 -67
- data/lib/glueby/fee_provider/tasks.rb +4 -1
- data/lib/glueby/internal/wallet/abstract_wallet_adapter.rb +26 -0
- data/lib/glueby/internal/wallet/active_record/key.rb +2 -2
- data/lib/glueby/internal/wallet/active_record/utxo.rb +9 -0
- data/lib/glueby/internal/wallet/active_record_wallet_adapter.rb +22 -9
- data/lib/glueby/internal/wallet/errors.rb +1 -0
- data/lib/glueby/internal/wallet/mysql_wallet_adapter.rb +17 -0
- data/lib/glueby/internal/wallet/tapyrus_core_wallet_adapter.rb +1 -1
- data/lib/glueby/internal/wallet.rb +16 -0
- data/lib/glueby/util/digest.rb +23 -0
- data/lib/glueby/utxo_provider/tasks.rb +3 -1
- data/lib/glueby/utxo_provider.rb +56 -9
- data/lib/glueby/version.rb +1 -1
- data/lib/tasks/glueby/block_syncer.rake +7 -0
- metadata +23 -5
@@ -38,10 +38,13 @@ module Glueby
|
|
38
38
|
|
39
39
|
fee_outputs_count_to_be_created.times do
|
40
40
|
txb.pay(address, fee_provider.fixed_fee)
|
41
|
+
sum -= fee_provider.fixed_fee
|
41
42
|
end
|
43
|
+
fee = fee_provider.fixed_fee
|
44
|
+
fee += (sum - fee) if sum - fee < DUST_LIMIT
|
42
45
|
|
43
46
|
tx = txb.change_address(address)
|
44
|
-
.fee(
|
47
|
+
.fee(fee)
|
45
48
|
.build
|
46
49
|
tx = wallet.sign_tx(tx)
|
47
50
|
wallet.broadcast(tx, without_fee_provider: true)
|
@@ -86,6 +86,14 @@ module Glueby
|
|
86
86
|
raise NotImplementedError, "You must implement #{self.class}##{__method__}"
|
87
87
|
end
|
88
88
|
|
89
|
+
# Attempt to lock a specified utxo and update lock_at field
|
90
|
+
#
|
91
|
+
# @param wallet_id [String] The wallet id that is offered by `create_wallet()` method.
|
92
|
+
# @param utxo [Hash] The utxo hash object
|
93
|
+
def lock_unspent(wallet_id, utxo)
|
94
|
+
true
|
95
|
+
end
|
96
|
+
|
89
97
|
# Sign to the transaction with a key in the wallet.
|
90
98
|
#
|
91
99
|
# @param [String] wallet_id - The wallet id that is offered by `create_wallet()` method.
|
@@ -157,6 +165,15 @@ module Glueby
|
|
157
165
|
raise NotImplementedError, "You must implement #{self.class}##{__method__}"
|
158
166
|
end
|
159
167
|
|
168
|
+
# Create pay to contract key
|
169
|
+
# @param [String] wallet_id - The wallet id that is offered by `create_wallet()` method.
|
170
|
+
# @param [Tapyrus::Key] payment_base - The public key used to generate pay to contract public key
|
171
|
+
# @param [String] contents - The data to be used for generating pay-to-contract address
|
172
|
+
# @return [Tapyrus::Key] Key for pay to contract
|
173
|
+
def pay_to_contract_key(wallet_id, payment_base, contents)
|
174
|
+
raise NotImplementedError, "You must implement #{self.class}##{__method__}"
|
175
|
+
end
|
176
|
+
|
160
177
|
# Sign to the pay to contract input
|
161
178
|
# @param [String] wallet_id - The wallet id that is offered by `create_wallet()` method.
|
162
179
|
# @param [Tapyrus::Tx] tx - The tx that has pay to contract input in the inputs list
|
@@ -170,9 +187,18 @@ module Glueby
|
|
170
187
|
# @param [Integer] sighashtype - The sighash flag for each signature that would be produced here.
|
171
188
|
# @return [Tapyrus::Tx]
|
172
189
|
# @raise [Glueby::Internal::Wallet::Errors::InvalidSighashType] when the specified sighashtype is invalid
|
190
|
+
# @raise [Glueby::Internal::Wallet::Errors::InvalidSigner] when the wallet don't have any private key of the specified payment_base
|
173
191
|
def sign_to_pay_to_contract_address(wallet_id, tx, utxo, payment_base, contents, sighashtype: Tapyrus::SIGHASH_TYPE[:all])
|
174
192
|
raise NotImplementedError, "You must implement #{self.class}##{__method__}"
|
175
193
|
end
|
194
|
+
|
195
|
+
# Return if wallet has the address
|
196
|
+
# @param wallet_id [String] The wallet id that is offered by `create_wallet()` method.
|
197
|
+
# @param address [String] address
|
198
|
+
# @return [Boolean] true if the wallet has an address, false otherwise
|
199
|
+
def has_address?(wallet_id, address)
|
200
|
+
raise NotImplementedError, "You must implement #{self.class}##{__method__}"
|
201
|
+
end
|
176
202
|
end
|
177
203
|
end
|
178
204
|
end
|
@@ -20,7 +20,7 @@ module Glueby
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def sign(data)
|
23
|
-
Tapyrus::Key.new(priv_key: self.private_key).sign(data, algo: :schnorr)
|
23
|
+
Tapyrus::Key.new(priv_key: self.private_key, key_type: Tapyrus::Key::TYPES[:compressed]).sign(data, algo: :schnorr)
|
24
24
|
end
|
25
25
|
|
26
26
|
def address
|
@@ -54,7 +54,7 @@ module Glueby
|
|
54
54
|
|
55
55
|
def generate_key
|
56
56
|
key = if private_key
|
57
|
-
Tapyrus::Key.new(priv_key: private_key)
|
57
|
+
Tapyrus::Key.new(priv_key: private_key, key_type: Tapyrus::Key::TYPES[:compressed])
|
58
58
|
else
|
59
59
|
Tapyrus::Key.generate
|
60
60
|
end
|
@@ -8,6 +8,7 @@ module Glueby
|
|
8
8
|
belongs_to :key
|
9
9
|
|
10
10
|
validates :txid, uniqueness: { scope: :index, case_sensitive: false }
|
11
|
+
validate :check_dust_output
|
11
12
|
|
12
13
|
enum status: { init: 0, broadcasted: 1, finalized: 2 }
|
13
14
|
|
@@ -44,6 +45,14 @@ module Glueby
|
|
44
45
|
)
|
45
46
|
end
|
46
47
|
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def check_dust_output
|
52
|
+
if !color_id && value < DUST_LIMIT
|
53
|
+
errors.add(:value, "is less than dust limit(#{DUST_LIMIT})")
|
54
|
+
end
|
55
|
+
end
|
47
56
|
end
|
48
57
|
end
|
49
58
|
end
|
@@ -84,16 +84,15 @@ module Glueby
|
|
84
84
|
|
85
85
|
def balance(wallet_id, only_finalized = true)
|
86
86
|
wallet = AR::Wallet.find_by(wallet_id: wallet_id)
|
87
|
-
utxos = wallet.utxos
|
87
|
+
utxos = wallet.utxos.where(locked_at: nil)
|
88
88
|
utxos = utxos.where(status: :finalized) if only_finalized
|
89
89
|
utxos.sum(&:value)
|
90
90
|
end
|
91
91
|
|
92
92
|
def list_unspent(wallet_id, only_finalized = true, label = nil)
|
93
93
|
wallet = AR::Wallet.find_by(wallet_id: wallet_id)
|
94
|
-
utxos = wallet.utxos
|
94
|
+
utxos = wallet.utxos.where(locked_at: nil)
|
95
95
|
utxos = utxos.where(status: :finalized) if only_finalized
|
96
|
-
|
97
96
|
if [:unlabeled, nil].include?(label)
|
98
97
|
utxos = utxos.where(label: nil)
|
99
98
|
elsif label && (label != :all)
|
@@ -144,7 +143,7 @@ module Glueby
|
|
144
143
|
def create_pubkey(wallet_id)
|
145
144
|
wallet = AR::Wallet.find_by(wallet_id: wallet_id)
|
146
145
|
key = wallet.keys.create(purpose: :receive)
|
147
|
-
Tapyrus::Key.new(pubkey: key.public_key)
|
146
|
+
Tapyrus::Key.new(pubkey: key.public_key, key_type: Tapyrus::Key::TYPES[:compressed])
|
148
147
|
end
|
149
148
|
|
150
149
|
def get_addresses(wallet_id, label = nil)
|
@@ -155,13 +154,17 @@ module Glueby
|
|
155
154
|
end
|
156
155
|
|
157
156
|
def create_pay_to_contract_address(wallet_id, contents)
|
157
|
+
pubkey = create_pubkey(wallet_id)
|
158
|
+
[pay_to_contract_key(wallet_id, pubkey, contents).to_p2pkh, pubkey.pubkey]
|
159
|
+
end
|
160
|
+
|
161
|
+
def pay_to_contract_key(wallet_id, pubkey, contents)
|
158
162
|
# Calculate P + H(P || contents)G
|
159
163
|
group = ECDSA::Group::Secp256k1
|
160
|
-
pubkey = create_pubkey(wallet_id)
|
161
164
|
p = pubkey.to_point # P
|
162
165
|
commitment = create_pay_to_contract_commitment(pubkey, contents)
|
163
166
|
point = p + group.generator.multiply_by_scalar(commitment) # P + H(P || contents)G
|
164
|
-
|
167
|
+
Tapyrus::Key.new(pubkey: point.to_hex(true), key_type: Tapyrus::Key::TYPES[:compressed])
|
165
168
|
end
|
166
169
|
|
167
170
|
def sign_to_pay_to_contract_address(wallet_id, tx, utxo, payment_base, contents)
|
@@ -174,6 +177,12 @@ module Glueby
|
|
174
177
|
tx
|
175
178
|
end
|
176
179
|
|
180
|
+
def has_address?(wallet_id, address)
|
181
|
+
script_pubkey = Tapyrus::Script.parse_from_addr(address)
|
182
|
+
wallet = AR::Wallet.find_by(wallet_id: wallet_id)
|
183
|
+
wallet.keys.exists?(script_pubkey: script_pubkey.to_hex)
|
184
|
+
end
|
185
|
+
|
177
186
|
private
|
178
187
|
|
179
188
|
# Calculate commitment = H(P || contents)
|
@@ -181,22 +190,26 @@ module Glueby
|
|
181
190
|
# @param [String] contents
|
182
191
|
# @return Integer
|
183
192
|
def create_pay_to_contract_commitment(pubkey, contents)
|
193
|
+
contents = (+contents).force_encoding('binary')
|
184
194
|
group = ECDSA::Group::Secp256k1
|
185
195
|
p = pubkey.to_point # P
|
186
|
-
Tapyrus.sha256(p.to_hex(true).htb + contents).bth.to_i(16) % group.order # H(P || contents)
|
196
|
+
Tapyrus.sha256(p.to_hex(true).htb + contents).bth.to_i(16) % group.order # H(P || contents)
|
187
197
|
end
|
188
198
|
|
189
199
|
# @param [String] wallet_id
|
190
200
|
# @param [String] payment_base The public key hex string
|
191
201
|
# @param [String] contents
|
192
202
|
# @return [Tapyrus::Key] pay to contract private key
|
203
|
+
# @raise [Errors::InvalidSigner] raises when the wallet don't have any private key of the specified payment_base
|
193
204
|
def create_pay_to_contract_private_key(wallet_id, payment_base, contents)
|
194
205
|
group = ECDSA::Group::Secp256k1
|
195
206
|
wallet = AR::Wallet.find_by(wallet_id: wallet_id)
|
196
207
|
ar_key = wallet.keys.where(public_key: payment_base).first
|
197
|
-
key
|
208
|
+
raise Errors::InvalidSigner, "The wallet don't have any private key of the specified payment_base" unless ar_key
|
209
|
+
|
210
|
+
key = Tapyrus::Key.new(pubkey: payment_base, key_type: Tapyrus::Key::TYPES[:compressed])
|
198
211
|
commitment = create_pay_to_contract_commitment(key, contents)
|
199
|
-
Tapyrus::Key.new(priv_key: ((ar_key.private_key.to_i(16) + commitment) % group.order).to_even_length_hex) # K + commitment
|
212
|
+
Tapyrus::Key.new(priv_key: ((ar_key.private_key.to_i(16) + commitment) % group.order).to_even_length_hex, key_type: Tapyrus::Key::TYPES[:compressed]) # K + commitment
|
200
213
|
end
|
201
214
|
end
|
202
215
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Glueby
|
4
|
+
module Internal
|
5
|
+
class Wallet
|
6
|
+
class MySQLWalletAdapter < ActiveRecordWalletAdapter
|
7
|
+
def lock_unspent(wallet_id, utxo)
|
8
|
+
ActiveRecord::Base.transaction(joinable: false, requires_new: true) do
|
9
|
+
record = AR::Utxo.lock("FOR UPDATE SKIP LOCKED").find_by(txid: utxo[:txid], index: utxo[:vout], locked_at: nil)
|
10
|
+
record&.update!(locked_at: Time.now)
|
11
|
+
record
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -149,7 +149,7 @@ module Glueby
|
|
149
149
|
perform_as(wallet_id) do |client|
|
150
150
|
address = client.getnewaddress('')
|
151
151
|
info = client.getaddressinfo(address)
|
152
|
-
Tapyrus::Key.new(pubkey: info['pubkey'])
|
152
|
+
Tapyrus::Key.new(pubkey: info['pubkey'], key_type: Tapyrus::Key::TYPES[:compressed])
|
153
153
|
end
|
154
154
|
end
|
155
155
|
|
@@ -31,8 +31,11 @@ module Glueby
|
|
31
31
|
autoload :AR, 'glueby/internal/wallet/active_record'
|
32
32
|
autoload :TapyrusCoreWalletAdapter, 'glueby/internal/wallet/tapyrus_core_wallet_adapter'
|
33
33
|
autoload :ActiveRecordWalletAdapter, 'glueby/internal/wallet/active_record_wallet_adapter'
|
34
|
+
autoload :MySQLWalletAdapter, 'glueby/internal/wallet/mysql_wallet_adapter'
|
34
35
|
autoload :Errors, 'glueby/internal/wallet/errors'
|
35
36
|
|
37
|
+
include GluebyLogger
|
38
|
+
|
36
39
|
class << self
|
37
40
|
def create(wallet_id = nil)
|
38
41
|
begin
|
@@ -91,6 +94,10 @@ module Glueby
|
|
91
94
|
wallet_adapter.list_unspent(id, only_finalized, label)
|
92
95
|
end
|
93
96
|
|
97
|
+
def lock_unspent(utxo)
|
98
|
+
wallet_adapter.lock_unspent(id, utxo)
|
99
|
+
end
|
100
|
+
|
94
101
|
def delete
|
95
102
|
wallet_adapter.delete_wallet(id)
|
96
103
|
end
|
@@ -118,6 +125,7 @@ module Glueby
|
|
118
125
|
# @param [Proc] block The block that is called before broadcasting. It can be used to handle tx that is modified by FeeProvider.
|
119
126
|
def broadcast(tx, without_fee_provider: false, &block)
|
120
127
|
tx = FeeProvider.provide(tx) if !without_fee_provider && Glueby.configuration.fee_provider_bears?
|
128
|
+
logger.info("Try to broadcast a tx (tx payload: #{tx.to_hex} )")
|
121
129
|
wallet_adapter.broadcast(id, tx, &block)
|
122
130
|
tx
|
123
131
|
end
|
@@ -158,10 +166,18 @@ module Glueby
|
|
158
166
|
wallet_adapter.create_pay_to_contract_address(id, contents)
|
159
167
|
end
|
160
168
|
|
169
|
+
def pay_to_contract_key(payment_base, contents)
|
170
|
+
wallet_adapter.pay_to_contract_key(id, payment_base, contents)
|
171
|
+
end
|
172
|
+
|
161
173
|
def sign_to_pay_to_contract_address(tx, utxo, payment_base, contents)
|
162
174
|
wallet_adapter.sign_to_pay_to_contract_address(id, tx, utxo, payment_base, contents)
|
163
175
|
end
|
164
176
|
|
177
|
+
def has_address?(address)
|
178
|
+
wallet_adapter.has_address?(id, address)
|
179
|
+
end
|
180
|
+
|
165
181
|
private
|
166
182
|
|
167
183
|
def wallet_adapter
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Glueby
|
2
|
+
module Util
|
3
|
+
module Digest
|
4
|
+
# Hash content with specified digest algorithm
|
5
|
+
#
|
6
|
+
# @param content [String] content to be hashed
|
7
|
+
# @param digest [Symbol] The symbol represents algorithm used for hashing. :sha256, :double_sha256, :none are available
|
8
|
+
# @return [String] hex string hashed from content
|
9
|
+
def digest_content(content, digest)
|
10
|
+
case digest&.downcase
|
11
|
+
when :sha256
|
12
|
+
Tapyrus.sha256(content).bth
|
13
|
+
when :double_sha256
|
14
|
+
Tapyrus.double_sha256(content).bth
|
15
|
+
when :none
|
16
|
+
content
|
17
|
+
else
|
18
|
+
raise Glueby::Contract::Errors::UnsupportedDigestType
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -15,7 +15,7 @@ module Glueby
|
|
15
15
|
}
|
16
16
|
|
17
17
|
def initialize
|
18
|
-
@utxo_provider = Glueby::UtxoProvider.
|
18
|
+
@utxo_provider = Glueby::UtxoProvider.instance
|
19
19
|
end
|
20
20
|
|
21
21
|
# Create UTXOs for paying tpc
|
@@ -46,6 +46,8 @@ module Glueby
|
|
46
46
|
return if added_outputs == 0
|
47
47
|
|
48
48
|
fee = fee_estimator.fee(Contract::FeeEstimator.dummy_tx(txb.build))
|
49
|
+
fee += (sum - fee) if sum - fee < DUST_LIMIT
|
50
|
+
|
49
51
|
tx = txb.change_address(utxo_provider.address)
|
50
52
|
.fee(fee)
|
51
53
|
.build
|
data/lib/glueby/utxo_provider.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
module Glueby
|
2
2
|
class UtxoProvider
|
3
3
|
include Glueby::Contract::TxBuilder
|
4
|
+
include Singleton
|
4
5
|
|
5
6
|
autoload :Tasks, 'glueby/utxo_provider/tasks'
|
6
7
|
|
@@ -63,6 +64,41 @@ module Glueby
|
|
63
64
|
[signed_tx, 0]
|
64
65
|
end
|
65
66
|
|
67
|
+
# Fill inputs in the tx up to target_amount of TPC from UTXO pool
|
68
|
+
# This method should be called before adding change output and script_sig in outputs.
|
69
|
+
# FeeEstimator.dummy_tx returns fee amount to the TX that will be added one TPC input, a change TPC output and
|
70
|
+
# script sigs in outputs.
|
71
|
+
# @param [Tapyrus::Tx] tx The tx that will be filled the inputs
|
72
|
+
# @param [Integer] target_amount The tapyrus amount the tx is expected to be added in this method
|
73
|
+
# @param [Integer] current_amount The tapyrus amount the tx already has in its inputs
|
74
|
+
# @param [Glueby::Contract::FeeEstimator] fee_estimator
|
75
|
+
# @return [Tapyrus::Tx] tx The tx that is added inputs
|
76
|
+
# @return [Integer] fee The final fee after the inputs are filled
|
77
|
+
# @return [Integer] current_amount The final amount of the tx inputs
|
78
|
+
# @return [Array<Hash>] provided_utxos The utxos that are added to the tx inputs
|
79
|
+
def fill_inputs(tx, target_amount: , current_amount: 0, fee_estimator: Contract::FeeEstimator::Fixed.new)
|
80
|
+
fee = fee_estimator.fee(Contract::FeeEstimator.dummy_tx(tx, dummy_input_count: 0))
|
81
|
+
provided_utxos = []
|
82
|
+
|
83
|
+
# If the change output value is less than DUST_LIMIT, tapyrus core returns "dust" error while broadcasting.
|
84
|
+
target_amount += DUST_LIMIT if target_amount < DUST_LIMIT
|
85
|
+
|
86
|
+
while current_amount - fee < target_amount
|
87
|
+
sum, utxos = collect_uncolored_outputs(wallet, fee + target_amount - current_amount, provided_utxos)
|
88
|
+
|
89
|
+
utxos.each do |utxo|
|
90
|
+
tx.inputs << Tapyrus::TxIn.new(out_point: Tapyrus::OutPoint.from_txid(utxo[:txid], utxo[:vout]))
|
91
|
+
provided_utxos << utxo
|
92
|
+
end
|
93
|
+
current_amount += sum
|
94
|
+
|
95
|
+
new_fee = fee_estimator.fee(Contract::FeeEstimator.dummy_tx(tx, dummy_input_count: 0))
|
96
|
+
fee = new_fee
|
97
|
+
end
|
98
|
+
|
99
|
+
[tx, fee, current_amount, provided_utxos]
|
100
|
+
end
|
101
|
+
|
66
102
|
def default_value
|
67
103
|
@default_value ||=
|
68
104
|
(
|
@@ -110,16 +146,27 @@ module Glueby
|
|
110
146
|
end
|
111
147
|
end
|
112
148
|
|
113
|
-
|
114
|
-
|
149
|
+
# Collects and returns TPC UTXOs.
|
150
|
+
# @param [Glueby::Internal::Wallet] wallet The wallet that funds the caller
|
151
|
+
# @param [Integer] amount The target amount which to be collected
|
152
|
+
# @param [Array<Hash>] excludes The exclusion UTXO list. It excludes this UTXOs from the targets that will be collected TPC UTXOs.
|
153
|
+
# @return [Integer] sum The sum amount of the funds
|
154
|
+
# @return [Array<Hash>] outputs The UTXO set of the funds
|
155
|
+
def collect_uncolored_outputs(wallet, amount, excludes = [])
|
156
|
+
utxos = wallet.list_unspent.select do |o|
|
157
|
+
!o[:color_id] &&
|
158
|
+
o[:amount] == default_value &&
|
159
|
+
!excludes.find { |i| i[:txid] == o[:txid] && i[:vout] == o[:vout] }
|
160
|
+
end
|
115
161
|
utxos.shuffle!
|
116
|
-
|
117
|
-
utxos.inject([0, []]) do |sum, output|
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
162
|
+
|
163
|
+
utxos.inject([0, []]) do |(sum, outputs), output|
|
164
|
+
if wallet.lock_unspent(output)
|
165
|
+
sum += output[:amount]
|
166
|
+
outputs << output
|
167
|
+
return [sum, outputs] if sum >= amount
|
168
|
+
end
|
169
|
+
[sum, outputs]
|
123
170
|
end
|
124
171
|
raise Glueby::Contract::Errors::InsufficientFunds
|
125
172
|
end
|
data/lib/glueby/version.rb
CHANGED
@@ -25,5 +25,12 @@ namespace :glueby do
|
|
25
25
|
puts "success in synchronization (block height=#{height})"
|
26
26
|
end
|
27
27
|
end
|
28
|
+
|
29
|
+
desc 'Update the block height in Glueby::AR::SystemInformation and do not run Glueby::BlockSyncer. This task is intended to skip the synchronization process until the latest block height.'
|
30
|
+
task :update_height, [] => [:environment] do |_, _|
|
31
|
+
new_height = Glueby::Internal::RPC.client.getblockcount
|
32
|
+
synced_block = Glueby::AR::SystemInformation.synced_block_height
|
33
|
+
synced_block.update(info_value: new_height.to_s)
|
34
|
+
end
|
28
35
|
end
|
29
36
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: glueby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- azuchi
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-11-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: tapyrus
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.
|
19
|
+
version: 0.3.1
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 0.
|
26
|
+
version: 0.3.1
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: activerecord
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -52,6 +52,20 @@ dependencies:
|
|
52
52
|
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: mysql2
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
70
|
name: rails
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -88,15 +102,16 @@ files:
|
|
88
102
|
- glueby.gemspec
|
89
103
|
- lib/generators/glueby/contract/block_syncer_generator.rb
|
90
104
|
- lib/generators/glueby/contract/initializer_generator.rb
|
91
|
-
- lib/generators/glueby/contract/reissuable_token_generator.rb
|
92
105
|
- lib/generators/glueby/contract/templates/initializer.rb.erb
|
93
106
|
- lib/generators/glueby/contract/templates/key_table.rb.erb
|
94
107
|
- lib/generators/glueby/contract/templates/reissuable_token_table.rb.erb
|
95
108
|
- lib/generators/glueby/contract/templates/system_information_table.rb.erb
|
96
109
|
- lib/generators/glueby/contract/templates/timestamp_table.rb.erb
|
110
|
+
- lib/generators/glueby/contract/templates/token_metadata_table.rb.erb
|
97
111
|
- lib/generators/glueby/contract/templates/utxo_table.rb.erb
|
98
112
|
- lib/generators/glueby/contract/templates/wallet_table.rb.erb
|
99
113
|
- lib/generators/glueby/contract/timestamp_generator.rb
|
114
|
+
- lib/generators/glueby/contract/token_generator.rb
|
100
115
|
- lib/generators/glueby/contract/wallet_adapter_generator.rb
|
101
116
|
- lib/glueby.rb
|
102
117
|
- lib/glueby/active_record.rb
|
@@ -108,6 +123,7 @@ files:
|
|
108
123
|
- lib/glueby/contract/active_record.rb
|
109
124
|
- lib/glueby/contract/active_record/reissuable_token.rb
|
110
125
|
- lib/glueby/contract/active_record/timestamp.rb
|
126
|
+
- lib/glueby/contract/active_record/token_metadata.rb
|
111
127
|
- lib/glueby/contract/errors.rb
|
112
128
|
- lib/glueby/contract/fee_estimator.rb
|
113
129
|
- lib/glueby/contract/fee_estimator/auto.rb
|
@@ -136,8 +152,10 @@ files:
|
|
136
152
|
- lib/glueby/internal/wallet/active_record_wallet_adapter.rb
|
137
153
|
- lib/glueby/internal/wallet/active_record_wallet_adapter/syncer.rb
|
138
154
|
- lib/glueby/internal/wallet/errors.rb
|
155
|
+
- lib/glueby/internal/wallet/mysql_wallet_adapter.rb
|
139
156
|
- lib/glueby/internal/wallet/tapyrus_core_wallet_adapter.rb
|
140
157
|
- lib/glueby/railtie.rb
|
158
|
+
- lib/glueby/util/digest.rb
|
141
159
|
- lib/glueby/utxo_provider.rb
|
142
160
|
- lib/glueby/utxo_provider/tasks.rb
|
143
161
|
- lib/glueby/version.rb
|