glueby 0.4.4 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +463 -387
- data/glueby.gemspec +33 -33
- 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/utxo_table.rb.erb +16 -16
- data/lib/glueby/block_syncer.rb +97 -97
- data/lib/glueby/configuration.rb +26 -2
- data/lib/glueby/contract/timestamp/syncer.rb +13 -13
- data/lib/glueby/contract/timestamp.rb +108 -102
- data/lib/glueby/contract/token.rb +270 -244
- data/lib/glueby/contract/tx_builder.rb +97 -30
- data/lib/glueby/fee_provider/tasks.rb +140 -140
- data/lib/glueby/fee_provider.rb +11 -0
- data/lib/glueby/internal/wallet/abstract_wallet_adapter.rb +151 -151
- data/lib/glueby/internal/wallet/active_record/utxo.rb +51 -51
- data/lib/glueby/internal/wallet/active_record_wallet_adapter/syncer.rb +13 -13
- data/lib/glueby/internal/wallet/active_record_wallet_adapter.rb +151 -151
- data/lib/glueby/internal/wallet/tapyrus_core_wallet_adapter.rb +186 -186
- data/lib/glueby/internal/wallet.rb +163 -162
- data/lib/glueby/railtie.rb +10 -9
- data/lib/glueby/utxo_provider/tasks.rb +135 -0
- data/lib/glueby/utxo_provider.rb +85 -0
- data/lib/glueby/version.rb +3 -3
- data/lib/glueby.rb +40 -39
- data/lib/tasks/glueby/block_syncer.rake +28 -28
- data/lib/tasks/glueby/contract/timestamp.rake +46 -39
- data/lib/tasks/glueby/fee_provider.rake +18 -18
- data/lib/tasks/glueby/utxo_provider.rake +18 -0
- metadata +5 -2
@@ -11,18 +11,32 @@ module Glueby
|
|
11
11
|
end
|
12
12
|
|
13
13
|
# Create new public key, and new transaction that sends TPC to it
|
14
|
-
def create_funding_tx(wallet:, script: nil, fee_estimator: FixedFeeEstimator.new)
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
14
|
+
def create_funding_tx(wallet:, script: nil, fee_estimator: FixedFeeEstimator.new, utxo_provider: nil)
|
15
|
+
if utxo_provider
|
16
|
+
script_pubkey = script ? script : Tapyrus::Script.parse_from_addr(wallet.internal_wallet.receive_address)
|
17
|
+
funding_tx, _index = utxo_provider.get_utxo(script_pubkey, FUNDING_TX_AMOUNT)
|
18
|
+
utxo_provider.wallet.sign_tx(funding_tx)
|
19
|
+
else
|
20
|
+
txb = Tapyrus::TxBuilder.new
|
21
|
+
fee = fee_estimator.fee(dummy_tx(txb.build))
|
22
|
+
|
23
|
+
sum, outputs = wallet.internal_wallet.collect_uncolored_outputs(fee + FUNDING_TX_AMOUNT)
|
24
|
+
outputs.each do |utxo|
|
25
|
+
txb.add_utxo({
|
26
|
+
script_pubkey: Tapyrus::Script.parse_from_payload(utxo[:script_pubkey].htb),
|
27
|
+
txid: utxo[:txid],
|
28
|
+
index: utxo[:vout],
|
29
|
+
value: utxo[:amount]
|
30
|
+
})
|
31
|
+
end
|
32
|
+
|
33
|
+
receiver_address = script ? script.addresses.first : wallet.internal_wallet.receive_address
|
34
|
+
tx = txb.pay(receiver_address, FUNDING_TX_AMOUNT)
|
35
|
+
.change_address(wallet.internal_wallet.change_address)
|
36
|
+
.fee(fee)
|
37
|
+
.build
|
38
|
+
wallet.internal_wallet.sign_tx(tx)
|
39
|
+
end
|
26
40
|
end
|
27
41
|
|
28
42
|
def create_issue_tx_for_reissuable_token(funding_tx:, issuer:, amount:, fee_estimator: FixedFeeEstimator.new)
|
@@ -48,21 +62,27 @@ module Glueby
|
|
48
62
|
issuer.internal_wallet.sign_tx(tx, prev_txs)
|
49
63
|
end
|
50
64
|
|
51
|
-
def create_issue_tx_for_non_reissuable_token(issuer:, amount:, fee_estimator: FixedFeeEstimator.new)
|
52
|
-
create_issue_tx_from_out_point(token_type: Tapyrus::Color::TokenTypes::NON_REISSUABLE, issuer: issuer, amount: amount, fee_estimator: fee_estimator)
|
65
|
+
def create_issue_tx_for_non_reissuable_token(funding_tx: nil, issuer:, amount:, fee_estimator: FixedFeeEstimator.new)
|
66
|
+
create_issue_tx_from_out_point(funding_tx: funding_tx, token_type: Tapyrus::Color::TokenTypes::NON_REISSUABLE, issuer: issuer, amount: amount, fee_estimator: fee_estimator)
|
53
67
|
end
|
54
68
|
|
55
|
-
def create_issue_tx_for_nft_token(issuer:, fee_estimator: FixedFeeEstimator.new)
|
56
|
-
create_issue_tx_from_out_point(token_type: Tapyrus::Color::TokenTypes::NFT, issuer: issuer, amount: 1, fee_estimator: fee_estimator)
|
69
|
+
def create_issue_tx_for_nft_token(funding_tx: nil, issuer:, fee_estimator: FixedFeeEstimator.new)
|
70
|
+
create_issue_tx_from_out_point(funding_tx: funding_tx, token_type: Tapyrus::Color::TokenTypes::NFT, issuer: issuer, amount: 1, fee_estimator: fee_estimator)
|
57
71
|
end
|
58
72
|
|
59
|
-
def create_issue_tx_from_out_point(token_type:, issuer:, amount:, fee_estimator: FixedFeeEstimator.new)
|
73
|
+
def create_issue_tx_from_out_point(funding_tx: nil, token_type:, issuer:, amount:, fee_estimator: FixedFeeEstimator.new)
|
60
74
|
tx = Tapyrus::Tx.new
|
61
75
|
|
62
76
|
fee = fee_estimator.fee(dummy_issue_tx_from_out_point)
|
63
|
-
sum
|
64
|
-
|
65
|
-
|
77
|
+
sum = if funding_tx
|
78
|
+
out_point = Tapyrus::OutPoint.from_txid(funding_tx.txid, 0)
|
79
|
+
tx.inputs << Tapyrus::TxIn.new(out_point: out_point)
|
80
|
+
funding_tx.outputs.first.value
|
81
|
+
else
|
82
|
+
sum, outputs = issuer.internal_wallet.collect_uncolored_outputs(fee)
|
83
|
+
fill_input(tx, outputs)
|
84
|
+
sum
|
85
|
+
end
|
66
86
|
out_point = tx.inputs.first.out_point
|
67
87
|
color_id = case token_type
|
68
88
|
when Tapyrus::Color::TokenTypes::NON_REISSUABLE
|
@@ -78,7 +98,18 @@ module Glueby
|
|
78
98
|
tx.outputs << Tapyrus::TxOut.new(value: amount, script_pubkey: receiver_colored_script)
|
79
99
|
|
80
100
|
fill_change_tpc(tx, issuer, sum - fee)
|
81
|
-
|
101
|
+
prev_txs = if funding_tx
|
102
|
+
output = funding_tx.outputs.first
|
103
|
+
[{
|
104
|
+
txid: funding_tx.txid,
|
105
|
+
vout: 0,
|
106
|
+
scriptPubKey: output.script_pubkey.to_hex,
|
107
|
+
amount: output.value
|
108
|
+
}]
|
109
|
+
else
|
110
|
+
[]
|
111
|
+
end
|
112
|
+
issuer.internal_wallet.sign_tx(tx, prev_txs)
|
82
113
|
end
|
83
114
|
|
84
115
|
def create_reissue_tx(funding_tx:, issuer:, amount:, color_id:, fee_estimator: FixedFeeEstimator.new)
|
@@ -103,7 +134,7 @@ module Glueby
|
|
103
134
|
issuer.internal_wallet.sign_tx(tx, prev_txs)
|
104
135
|
end
|
105
136
|
|
106
|
-
def create_transfer_tx(color_id:, sender:, receiver_address:, amount:, fee_estimator: FixedFeeEstimator.new)
|
137
|
+
def create_transfer_tx(funding_tx:nil, color_id:, sender:, receiver_address:, amount:, fee_estimator: FixedFeeEstimator.new)
|
107
138
|
tx = Tapyrus::Tx.new
|
108
139
|
|
109
140
|
utxos = sender.internal_wallet.list_unspent
|
@@ -117,14 +148,32 @@ module Glueby
|
|
117
148
|
fill_change_token(tx, sender, sum_token - amount, color_id)
|
118
149
|
|
119
150
|
fee = fee_estimator.fee(dummy_tx(tx))
|
120
|
-
sum_tpc
|
121
|
-
|
151
|
+
sum_tpc = if funding_tx
|
152
|
+
out_point = Tapyrus::OutPoint.from_txid(funding_tx.txid, 0)
|
153
|
+
tx.inputs << Tapyrus::TxIn.new(out_point: out_point)
|
154
|
+
funding_tx.outputs.first.value
|
155
|
+
else
|
156
|
+
sum_tpc, outputs = sender.internal_wallet.collect_uncolored_outputs(fee)
|
157
|
+
fill_input(tx, outputs)
|
158
|
+
sum_tpc
|
159
|
+
end
|
122
160
|
|
123
161
|
fill_change_tpc(tx, sender, sum_tpc - fee)
|
124
|
-
|
162
|
+
prev_txs = if funding_tx
|
163
|
+
output = funding_tx.outputs.first
|
164
|
+
[{
|
165
|
+
txid: funding_tx.txid,
|
166
|
+
vout: 0,
|
167
|
+
scriptPubKey: output.script_pubkey.to_hex,
|
168
|
+
amount: output.value
|
169
|
+
}]
|
170
|
+
else
|
171
|
+
[]
|
172
|
+
end
|
173
|
+
sender.internal_wallet.sign_tx(tx, prev_txs)
|
125
174
|
end
|
126
175
|
|
127
|
-
def create_burn_tx(color_id:, sender:, amount: 0, fee_estimator: FixedFeeEstimator.new)
|
176
|
+
def create_burn_tx(funding_tx:nil, color_id:, sender:, amount: 0, fee_estimator: FixedFeeEstimator.new)
|
128
177
|
tx = Tapyrus::Tx.new
|
129
178
|
|
130
179
|
utxos = sender.internal_wallet.list_unspent
|
@@ -135,12 +184,30 @@ module Glueby
|
|
135
184
|
|
136
185
|
fee = fee_estimator.fee(dummy_tx(tx))
|
137
186
|
|
138
|
-
|
139
|
-
|
140
|
-
|
187
|
+
sum_tpc = if funding_tx
|
188
|
+
out_point = Tapyrus::OutPoint.from_txid(funding_tx.txid, 0)
|
189
|
+
tx.inputs << Tapyrus::TxIn.new(out_point: out_point)
|
190
|
+
funding_tx.outputs.first.value
|
191
|
+
else
|
192
|
+
dust = 600 # in case that the wallet has output which has just fee amount.
|
193
|
+
sum_tpc, outputs = sender.internal_wallet.collect_uncolored_outputs(fee + dust)
|
194
|
+
fill_input(tx, outputs)
|
195
|
+
sum_tpc
|
196
|
+
end
|
141
197
|
|
142
198
|
fill_change_tpc(tx, sender, sum_tpc - fee)
|
143
|
-
|
199
|
+
prev_txs = if funding_tx
|
200
|
+
output = funding_tx.outputs.first
|
201
|
+
[{
|
202
|
+
txid: funding_tx.txid,
|
203
|
+
vout: 0,
|
204
|
+
scriptPubKey: output.script_pubkey.to_hex,
|
205
|
+
amount: output.value
|
206
|
+
}]
|
207
|
+
else
|
208
|
+
[]
|
209
|
+
end
|
210
|
+
sender.internal_wallet.sign_tx(tx, prev_txs)
|
144
211
|
end
|
145
212
|
|
146
213
|
def fill_input(tx, outputs)
|
@@ -1,141 +1,141 @@
|
|
1
|
-
module Glueby
|
2
|
-
class FeeProvider
|
3
|
-
class Tasks
|
4
|
-
attr_reader :fee_provider
|
5
|
-
|
6
|
-
STATUS = {
|
7
|
-
# FeeProvider is ready to pay fees.
|
8
|
-
ready: 'Ready',
|
9
|
-
# FeeProvider is ready to pay fees, but it doesn't have enough amount to fill the UTXO pool by UTXOs which is for paying fees.
|
10
|
-
insufficient_amount: 'Insufficient Amount',
|
11
|
-
# FeeProvider is not ready to pay fees. It has no UTXOs for paying fee and amounts.
|
12
|
-
not_ready: 'Not Ready'
|
13
|
-
}
|
14
|
-
|
15
|
-
def initialize
|
16
|
-
@fee_provider = Glueby::FeeProvider.new
|
17
|
-
end
|
18
|
-
|
19
|
-
# Create UTXOs for paying fee from TPC amount of the wallet FeeProvider has. Then show the status.
|
20
|
-
#
|
21
|
-
# About the UTXO Pool
|
22
|
-
# FeeProvider have the UTXO pool. the pool is manged to keep some number of UTXOs that have fixed fee value. The
|
23
|
-
# value is configurable by :fixed_fee. This method do the management to the pool.
|
24
|
-
def manage_utxo_pool
|
25
|
-
txb = Tapyrus::TxBuilder.new
|
26
|
-
|
27
|
-
sum, utxos = collect_outputs
|
28
|
-
return if utxos.empty?
|
29
|
-
|
30
|
-
utxos.each { |utxo| txb.add_utxo(utxo) }
|
31
|
-
address = wallet.receive_address
|
32
|
-
|
33
|
-
shortage = [fee_provider.utxo_pool_size - current_utxo_pool_size, 0].max
|
34
|
-
can_create = (sum - fee_provider.fixed_fee) / fee_provider.fixed_fee
|
35
|
-
fee_outputs_count_to_be_created = [shortage, can_create].min
|
36
|
-
|
37
|
-
return if fee_outputs_count_to_be_created == 0
|
38
|
-
|
39
|
-
fee_outputs_count_to_be_created.times do
|
40
|
-
txb.pay(address, fee_provider.fixed_fee)
|
41
|
-
end
|
42
|
-
|
43
|
-
tx = txb.change_address(address)
|
44
|
-
.fee(fee_provider.fixed_fee)
|
45
|
-
.build
|
46
|
-
tx = wallet.sign_tx(tx)
|
47
|
-
wallet.broadcast(tx, without_fee_provider: true)
|
48
|
-
ensure
|
49
|
-
status
|
50
|
-
end
|
51
|
-
|
52
|
-
# Show the status of the UTXO pool
|
53
|
-
def status
|
54
|
-
status = :ready
|
55
|
-
|
56
|
-
if current_utxo_pool_size < fee_provider.utxo_pool_size
|
57
|
-
if tpc_amount < value_to_fill_utxo_pool
|
58
|
-
status = :insufficient_amount
|
59
|
-
message = <<~MESSAGE
|
60
|
-
1. Please replenishment TPC which is for paying fee to FeeProvider.
|
61
|
-
FeeProvider needs #{value_to_fill_utxo_pool} tapyrus at least for paying 20 transaction fees.
|
62
|
-
FeeProvider wallet's address is '#{wallet.receive_address}'
|
63
|
-
2. Then create UTXOs for paying in UTXO pool with 'rake glueby:fee_provider:manage_utxo_pool'
|
64
|
-
MESSAGE
|
65
|
-
else
|
66
|
-
message = "Please create UTXOs for paying in UTXO pool with 'rake glueby:fee_provider:manage_utxo_pool'\n"
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
status = :not_ready if current_utxo_pool_size == 0
|
71
|
-
|
72
|
-
puts <<~EOS
|
73
|
-
Status: #{STATUS[status]}
|
74
|
-
TPC amount: #{delimit(tpc_amount)}
|
75
|
-
UTXO pool size: #{delimit(current_utxo_pool_size)}
|
76
|
-
#{"\n" if message}#{message}
|
77
|
-
Configuration:
|
78
|
-
fixed_fee = #{delimit(fee_provider.fixed_fee)}
|
79
|
-
utxo_pool_size = #{delimit(fee_provider.utxo_pool_size)}
|
80
|
-
EOS
|
81
|
-
end
|
82
|
-
|
83
|
-
# Show the address of Fee Provider
|
84
|
-
def
|
85
|
-
puts wallet.receive_address
|
86
|
-
end
|
87
|
-
|
88
|
-
private
|
89
|
-
|
90
|
-
def check_wallet_amount!
|
91
|
-
if tpc_amount < fee_provider.fixed_fee
|
92
|
-
raise InsufficientTPC, <<~MESSAGE
|
93
|
-
FeeProvider has insufficient TPC to create fee outputs to fill the UTXO pool.
|
94
|
-
1. Please replenishment TPC which is for paying fee to FeeProvider. FeeProvider needs #{fee_provider.utxo_pool_size * fee_provider.fixed_fee} tapyrus at least. FeeProvider wallet's address is '#{wallet.receive_address}'
|
95
|
-
2. Then create UTXOs for paying in UTXO pool with 'rake glueby:fee_provider:manage_utxo_pool'
|
96
|
-
MESSAGE
|
97
|
-
end
|
98
|
-
end
|
99
|
-
|
100
|
-
def tpc_amount
|
101
|
-
wallet.balance(false)
|
102
|
-
end
|
103
|
-
|
104
|
-
def collect_outputs
|
105
|
-
wallet.list_unspent.inject([0, []]) do |sum, output|
|
106
|
-
next sum if output[:color_id] || output[:amount] == fee_provider.fixed_fee
|
107
|
-
|
108
|
-
new_sum = sum[0] + output[:amount]
|
109
|
-
new_outputs = sum[1] << {
|
110
|
-
txid: output[:txid],
|
111
|
-
script_pubkey: output[:script_pubkey],
|
112
|
-
value: output[:amount],
|
113
|
-
index: output[:vout] ,
|
114
|
-
finalized: output[:finalized]
|
115
|
-
}
|
116
|
-
return [new_sum, new_outputs] if new_sum >= value_to_fill_utxo_pool
|
117
|
-
|
118
|
-
[new_sum, new_outputs]
|
119
|
-
end
|
120
|
-
end
|
121
|
-
|
122
|
-
def current_utxo_pool_size
|
123
|
-
wallet
|
124
|
-
.list_unspent(false)
|
125
|
-
.count { |o| !o[:color_id] && o[:amount] == fee_provider.fixed_fee }
|
126
|
-
end
|
127
|
-
|
128
|
-
def value_to_fill_utxo_pool
|
129
|
-
fee_provider.fixed_fee * (fee_provider.utxo_pool_size + 1) # +1 is for paying fee
|
130
|
-
end
|
131
|
-
|
132
|
-
def wallet
|
133
|
-
fee_provider.wallet
|
134
|
-
end
|
135
|
-
|
136
|
-
def delimit(num)
|
137
|
-
num.to_s.reverse.scan(/.{1,3}/).join('_').reverse
|
138
|
-
end
|
139
|
-
end
|
140
|
-
end
|
1
|
+
module Glueby
|
2
|
+
class FeeProvider
|
3
|
+
class Tasks
|
4
|
+
attr_reader :fee_provider
|
5
|
+
|
6
|
+
STATUS = {
|
7
|
+
# FeeProvider is ready to pay fees.
|
8
|
+
ready: 'Ready',
|
9
|
+
# FeeProvider is ready to pay fees, but it doesn't have enough amount to fill the UTXO pool by UTXOs which is for paying fees.
|
10
|
+
insufficient_amount: 'Insufficient Amount',
|
11
|
+
# FeeProvider is not ready to pay fees. It has no UTXOs for paying fee and amounts.
|
12
|
+
not_ready: 'Not Ready'
|
13
|
+
}
|
14
|
+
|
15
|
+
def initialize
|
16
|
+
@fee_provider = Glueby::FeeProvider.new
|
17
|
+
end
|
18
|
+
|
19
|
+
# Create UTXOs for paying fee from TPC amount of the wallet FeeProvider has. Then show the status.
|
20
|
+
#
|
21
|
+
# About the UTXO Pool
|
22
|
+
# FeeProvider have the UTXO pool. the pool is manged to keep some number of UTXOs that have fixed fee value. The
|
23
|
+
# value is configurable by :fixed_fee. This method do the management to the pool.
|
24
|
+
def manage_utxo_pool
|
25
|
+
txb = Tapyrus::TxBuilder.new
|
26
|
+
|
27
|
+
sum, utxos = collect_outputs
|
28
|
+
return if utxos.empty?
|
29
|
+
|
30
|
+
utxos.each { |utxo| txb.add_utxo(utxo) }
|
31
|
+
address = wallet.receive_address
|
32
|
+
|
33
|
+
shortage = [fee_provider.utxo_pool_size - current_utxo_pool_size, 0].max
|
34
|
+
can_create = (sum - fee_provider.fixed_fee) / fee_provider.fixed_fee
|
35
|
+
fee_outputs_count_to_be_created = [shortage, can_create].min
|
36
|
+
|
37
|
+
return if fee_outputs_count_to_be_created == 0
|
38
|
+
|
39
|
+
fee_outputs_count_to_be_created.times do
|
40
|
+
txb.pay(address, fee_provider.fixed_fee)
|
41
|
+
end
|
42
|
+
|
43
|
+
tx = txb.change_address(address)
|
44
|
+
.fee(fee_provider.fixed_fee)
|
45
|
+
.build
|
46
|
+
tx = wallet.sign_tx(tx)
|
47
|
+
wallet.broadcast(tx, without_fee_provider: true)
|
48
|
+
ensure
|
49
|
+
status
|
50
|
+
end
|
51
|
+
|
52
|
+
# Show the status of the UTXO pool
|
53
|
+
def status
|
54
|
+
status = :ready
|
55
|
+
|
56
|
+
if current_utxo_pool_size < fee_provider.utxo_pool_size
|
57
|
+
if tpc_amount < value_to_fill_utxo_pool
|
58
|
+
status = :insufficient_amount
|
59
|
+
message = <<~MESSAGE
|
60
|
+
1. Please replenishment TPC which is for paying fee to FeeProvider.
|
61
|
+
FeeProvider needs #{value_to_fill_utxo_pool} tapyrus at least for paying 20 transaction fees.
|
62
|
+
FeeProvider wallet's address is '#{wallet.receive_address}'
|
63
|
+
2. Then create UTXOs for paying in UTXO pool with 'rake glueby:fee_provider:manage_utxo_pool'
|
64
|
+
MESSAGE
|
65
|
+
else
|
66
|
+
message = "Please create UTXOs for paying in UTXO pool with 'rake glueby:fee_provider:manage_utxo_pool'\n"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
status = :not_ready if current_utxo_pool_size == 0
|
71
|
+
|
72
|
+
puts <<~EOS
|
73
|
+
Status: #{STATUS[status]}
|
74
|
+
TPC amount: #{delimit(tpc_amount)}
|
75
|
+
UTXO pool size: #{delimit(current_utxo_pool_size)}
|
76
|
+
#{"\n" if message}#{message}
|
77
|
+
Configuration:
|
78
|
+
fixed_fee = #{delimit(fee_provider.fixed_fee)}
|
79
|
+
utxo_pool_size = #{delimit(fee_provider.utxo_pool_size)}
|
80
|
+
EOS
|
81
|
+
end
|
82
|
+
|
83
|
+
# Show the address of Fee Provider
|
84
|
+
def print_address
|
85
|
+
puts wallet.receive_address
|
86
|
+
end
|
87
|
+
|
88
|
+
private
|
89
|
+
|
90
|
+
def check_wallet_amount!
|
91
|
+
if tpc_amount < fee_provider.fixed_fee
|
92
|
+
raise InsufficientTPC, <<~MESSAGE
|
93
|
+
FeeProvider has insufficient TPC to create fee outputs to fill the UTXO pool.
|
94
|
+
1. Please replenishment TPC which is for paying fee to FeeProvider. FeeProvider needs #{fee_provider.utxo_pool_size * fee_provider.fixed_fee} tapyrus at least. FeeProvider wallet's address is '#{wallet.receive_address}'
|
95
|
+
2. Then create UTXOs for paying in UTXO pool with 'rake glueby:fee_provider:manage_utxo_pool'
|
96
|
+
MESSAGE
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def tpc_amount
|
101
|
+
wallet.balance(false)
|
102
|
+
end
|
103
|
+
|
104
|
+
def collect_outputs
|
105
|
+
wallet.list_unspent.inject([0, []]) do |sum, output|
|
106
|
+
next sum if output[:color_id] || output[:amount] == fee_provider.fixed_fee
|
107
|
+
|
108
|
+
new_sum = sum[0] + output[:amount]
|
109
|
+
new_outputs = sum[1] << {
|
110
|
+
txid: output[:txid],
|
111
|
+
script_pubkey: output[:script_pubkey],
|
112
|
+
value: output[:amount],
|
113
|
+
index: output[:vout] ,
|
114
|
+
finalized: output[:finalized]
|
115
|
+
}
|
116
|
+
return [new_sum, new_outputs] if new_sum >= value_to_fill_utxo_pool
|
117
|
+
|
118
|
+
[new_sum, new_outputs]
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def current_utxo_pool_size
|
123
|
+
wallet
|
124
|
+
.list_unspent(false)
|
125
|
+
.count { |o| !o[:color_id] && o[:amount] == fee_provider.fixed_fee }
|
126
|
+
end
|
127
|
+
|
128
|
+
def value_to_fill_utxo_pool
|
129
|
+
fee_provider.fixed_fee * (fee_provider.utxo_pool_size + 1) # +1 is for paying fee
|
130
|
+
end
|
131
|
+
|
132
|
+
def wallet
|
133
|
+
fee_provider.wallet
|
134
|
+
end
|
135
|
+
|
136
|
+
def delimit(num)
|
137
|
+
num.to_s.reverse.scan(/.{1,3}/).join('_').reverse
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
141
|
end
|
data/lib/glueby/fee_provider.rb
CHANGED
@@ -8,6 +8,7 @@ module Glueby
|
|
8
8
|
WALLET_ID = 'FEE_PROVIDER_WALLET'
|
9
9
|
DEFAULT_FIXED_FEE = 1000
|
10
10
|
DEFAULT_UTXO_POOL_SIZE = 20
|
11
|
+
MAX_UTXO_POOL_SIZE = 2_000
|
11
12
|
|
12
13
|
attr_reader :fixed_fee, :utxo_pool_size, :wallet,
|
13
14
|
|
@@ -33,6 +34,7 @@ module Glueby
|
|
33
34
|
Internal::Wallet.create(WALLET_ID)
|
34
35
|
end
|
35
36
|
|
37
|
+
validate_config!
|
36
38
|
@fixed_fee = (FeeProvider.config && FeeProvider.config[:fixed_fee]) || DEFAULT_FIXED_FEE
|
37
39
|
@utxo_pool_size = (FeeProvider.config && FeeProvider.config[:utxo_pool_size]) || DEFAULT_UTXO_POOL_SIZE
|
38
40
|
end
|
@@ -69,5 +71,14 @@ module Glueby
|
|
69
71
|
def get_signature(script_sig)
|
70
72
|
script_sig.chunks.first.pushed_data
|
71
73
|
end
|
74
|
+
|
75
|
+
def validate_config!
|
76
|
+
if FeeProvider.config
|
77
|
+
utxo_pool_size = FeeProvider.config[:utxo_pool_size]
|
78
|
+
if utxo_pool_size && (!utxo_pool_size.is_a?(Integer) || utxo_pool_size > MAX_UTXO_POOL_SIZE)
|
79
|
+
raise Glueby::Configuration::Errors::InvalidConfiguration, "utxo_pool_size(#{utxo_pool_size}) should not be greater than #{MAX_UTXO_POOL_SIZE}"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
72
83
|
end
|
73
84
|
end
|