glueby 1.1.2 → 1.2.0.beta.1
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/.github/workflows/ruby.yml +2 -2
- data/.ruby-version +1 -1
- data/README.md +1 -1
- data/glueby.gemspec +3 -3
- 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/glueby/block_syncer.rb +97 -97
- data/lib/glueby/contract/active_record/timestamp.rb +0 -3
- data/lib/glueby/contract/payment.rb +10 -15
- data/lib/glueby/contract/timestamp/tx_builder/simple.rb +19 -57
- data/lib/glueby/contract/timestamp/tx_builder/trackable.rb +6 -0
- data/lib/glueby/contract/timestamp/tx_builder/updating_trackable.rb +3 -2
- data/lib/glueby/contract/token.rb +163 -86
- data/lib/glueby/contract/tx_builder.rb +1 -0
- data/lib/glueby/internal/contract_builder.rb +462 -0
- data/lib/glueby/internal/wallet/abstract_wallet_adapter.rb +2 -0
- data/lib/glueby/internal/wallet/active_record/utxo.rb +3 -2
- data/lib/glueby/internal/wallet.rb +149 -12
- data/lib/glueby/internal.rb +1 -0
- data/lib/glueby/utxo_provider/tasks.rb +0 -2
- data/lib/glueby/utxo_provider.rb +15 -34
- data/lib/glueby/version.rb +1 -1
- data/lib/tasks/glueby/contract/timestamp.rake +0 -1
- metadata +14 -13
@@ -48,9 +48,6 @@ module Glueby
|
|
48
48
|
# token.metadata
|
49
49
|
# => "metadata"
|
50
50
|
class Token
|
51
|
-
include Glueby::Contract::TxBuilder
|
52
|
-
extend Glueby::Contract::TxBuilder
|
53
|
-
|
54
51
|
class << self
|
55
52
|
# Issue new token with specified amount and token type.
|
56
53
|
# REISSUABLE token can be reissued with #reissue! method, and
|
@@ -112,92 +109,132 @@ module Glueby
|
|
112
109
|
end
|
113
110
|
|
114
111
|
def issue_reissuable_token(issuer:, amount:, split: 1, fee_estimator:, metadata: nil)
|
115
|
-
|
112
|
+
txb = Internal::ContractBuilder.new(
|
113
|
+
sender_wallet: issuer.internal_wallet,
|
114
|
+
fee_estimator: fee_estimator,
|
115
|
+
use_auto_fulfill_inputs: true
|
116
|
+
)
|
117
|
+
|
118
|
+
if metadata
|
119
|
+
txb.add_p2c_utxo_to!(
|
120
|
+
metadata: metadata,
|
121
|
+
amount: FeeEstimator::Fixed.new.fixed_fee,
|
122
|
+
only_finalized: only_finalized?,
|
123
|
+
fee_estimator: Contract::FeeEstimator::Fixed.new
|
124
|
+
)
|
125
|
+
else
|
126
|
+
txb.add_utxo_to!(
|
127
|
+
address: issuer.internal_wallet.receive_address,
|
128
|
+
amount: FeeEstimator::Fixed.new.fixed_fee,
|
129
|
+
only_finalized: only_finalized?,
|
130
|
+
fee_estimator: Contract::FeeEstimator::Fixed.new
|
131
|
+
)
|
132
|
+
end
|
116
133
|
|
117
|
-
|
118
|
-
# To make it easier for API users to understand whether a transaction is a new issue or a reissue,
|
119
|
-
# when Token.issue! is executed, a new address is created and tpc is sent to it to ensure that it is a new issue,
|
120
|
-
# and a transaction is created using that UTXO as input to create a new color_id.
|
121
|
-
funding_tx = create_funding_tx(wallet: issuer, script: script, only_finalized: only_finalized?)
|
134
|
+
funding_tx = txb.prev_txs.first
|
122
135
|
script_pubkey = funding_tx.outputs.first.script_pubkey
|
123
136
|
color_id = Tapyrus::Color::ColorIdentifier.reissuable(script_pubkey)
|
124
137
|
|
125
|
-
ActiveRecord::Base.transaction(joinable: false, requires_new: true) do
|
126
|
-
funding_tx = issuer.internal_wallet.broadcast(funding_tx)
|
127
|
-
end
|
128
|
-
|
129
138
|
ActiveRecord::Base.transaction(joinable: false, requires_new: true) do
|
130
139
|
# Store the script_pubkey for reissue the token.
|
131
|
-
Glueby::Contract::AR::ReissuableToken.create!(
|
140
|
+
Glueby::Contract::AR::ReissuableToken.create!(
|
141
|
+
color_id: color_id.to_hex,
|
142
|
+
script_pubkey: script_pubkey.to_hex
|
143
|
+
)
|
132
144
|
|
133
|
-
tx = create_issue_tx_for_reissuable_token(funding_tx: funding_tx, issuer: issuer, amount: amount, split: split, fee_estimator: fee_estimator)
|
134
145
|
if metadata
|
146
|
+
p2c_utxo = txb.p2c_utxos.first
|
135
147
|
Glueby::Contract::AR::TokenMetadata.create!(
|
136
148
|
color_id: color_id.to_hex,
|
137
149
|
metadata: metadata,
|
138
|
-
p2c_address: p2c_address,
|
139
|
-
payment_base: payment_base
|
150
|
+
p2c_address: p2c_utxo[:p2c_address],
|
151
|
+
payment_base: p2c_utxo[:payment_base]
|
140
152
|
)
|
141
|
-
tx = sign_to_p2c_output(issuer, tx, funding_tx, payment_base, metadata)
|
142
153
|
end
|
154
|
+
|
155
|
+
tx = txb.reissuable_split(script_pubkey, issuer.internal_wallet.receive_address, amount, split)
|
156
|
+
.build
|
143
157
|
tx = issuer.internal_wallet.broadcast(tx)
|
144
158
|
[[funding_tx, tx], color_id]
|
145
159
|
end
|
146
160
|
end
|
147
161
|
|
148
162
|
def issue_non_reissuable_token(issuer:, amount:, split: 1, fee_estimator:, metadata: nil)
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
163
|
+
issue_token_from_out_point(
|
164
|
+
Tapyrus::Color::TokenTypes::NON_REISSUABLE,
|
165
|
+
issuer: issuer,
|
166
|
+
amount: amount,
|
167
|
+
split: split,
|
168
|
+
fee_estimator: fee_estimator,
|
169
|
+
metadata: metadata
|
170
|
+
)
|
171
|
+
end
|
156
172
|
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
)
|
168
|
-
tx = sign_to_p2c_output(issuer, tx, funding_tx, payment_base, metadata)
|
169
|
-
end
|
170
|
-
tx = issuer.internal_wallet.broadcast(tx)
|
173
|
+
def issue_nft_token(issuer:, metadata: nil)
|
174
|
+
issue_token_from_out_point(
|
175
|
+
Tapyrus::Color::TokenTypes::NFT,
|
176
|
+
issuer: issuer,
|
177
|
+
amount: 1,
|
178
|
+
split: 1,
|
179
|
+
fee_estimator: Contract::FeeEstimator::Fixed.new,
|
180
|
+
metadata: metadata
|
181
|
+
)
|
182
|
+
end
|
171
183
|
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
184
|
+
def issue_token_from_out_point(token_type, issuer:, amount:, split: 1, fee_estimator: , metadata: nil)
|
185
|
+
txb = Internal::ContractBuilder.new(
|
186
|
+
sender_wallet: issuer.internal_wallet,
|
187
|
+
fee_estimator: fee_estimator,
|
188
|
+
use_auto_fulfill_inputs: true
|
189
|
+
)
|
190
|
+
|
191
|
+
funding_tx = nil
|
192
|
+
|
193
|
+
if metadata
|
194
|
+
txb.add_p2c_utxo_to!(
|
195
|
+
metadata: metadata,
|
196
|
+
amount: FeeEstimator::Fixed.new.fixed_fee,
|
197
|
+
only_finalized: only_finalized?,
|
198
|
+
fee_estimator: Contract::FeeEstimator::Fixed.new
|
199
|
+
)
|
200
|
+
funding_tx = txb.prev_txs.first
|
201
|
+
elsif Glueby.configuration.use_utxo_provider?
|
202
|
+
txb.add_utxo_to!(
|
203
|
+
address: issuer.internal_wallet.receive_address,
|
204
|
+
amount: FeeEstimator::Fixed.new.fixed_fee,
|
205
|
+
only_finalized: only_finalized?,
|
206
|
+
fee_estimator: Contract::FeeEstimator::Fixed.new
|
207
|
+
)
|
208
|
+
funding_tx = txb.prev_txs.first
|
209
|
+
else
|
210
|
+
# Here need to add just one UTXO to derive color_id from the UTXO out-point.
|
211
|
+
_, outputs = issuer.internal_wallet.collect_uncolored_outputs(1, nil, true)
|
212
|
+
txb.add_utxo(outputs.first)
|
177
213
|
end
|
178
|
-
end
|
179
214
|
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
215
|
+
utxo = txb.utxos.first
|
216
|
+
out_point = Tapyrus::OutPoint.from_txid(utxo[:txid], utxo[:index])
|
217
|
+
|
218
|
+
case token_type
|
219
|
+
when Tapyrus::Color::TokenTypes::NON_REISSUABLE
|
220
|
+
color_id = Tapyrus::Color::ColorIdentifier.non_reissuable(out_point)
|
221
|
+
tx = txb.non_reissuable_split(out_point, issuer.internal_wallet.receive_address, amount, split)
|
222
|
+
.build
|
223
|
+
when Tapyrus::Color::TokenTypes::NFT
|
224
|
+
color_id = Tapyrus::Color::ColorIdentifier.nft(out_point)
|
225
|
+
tx = txb.nft(out_point, issuer.internal_wallet.receive_address)
|
226
|
+
.build
|
187
227
|
end
|
188
228
|
|
189
229
|
ActiveRecord::Base.transaction(joinable: false, requires_new: true) do
|
190
|
-
tx = create_issue_tx_for_nft_token(funding_tx: funding_tx, issuer: issuer)
|
191
|
-
out_point = tx.inputs.first.out_point
|
192
|
-
color_id = Tapyrus::Color::ColorIdentifier.nft(out_point)
|
193
230
|
if metadata
|
231
|
+
p2c_utxo = txb.p2c_utxos.first
|
194
232
|
Glueby::Contract::AR::TokenMetadata.create!(
|
195
233
|
color_id: color_id.to_hex,
|
196
234
|
metadata: metadata,
|
197
|
-
p2c_address: p2c_address,
|
198
|
-
payment_base: payment_base
|
235
|
+
p2c_address: p2c_utxo[:p2c_address],
|
236
|
+
payment_base: p2c_utxo[:payment_base]
|
199
237
|
)
|
200
|
-
tx = sign_to_p2c_output(issuer, tx, funding_tx, payment_base, metadata)
|
201
238
|
end
|
202
239
|
tx = issuer.internal_wallet.broadcast(tx)
|
203
240
|
|
@@ -208,6 +245,14 @@ module Glueby
|
|
208
245
|
end
|
209
246
|
end
|
210
247
|
end
|
248
|
+
|
249
|
+
# Add dummy inputs and outputs to tx for issue non-reissuable transaction and nft transaction
|
250
|
+
def dummy_issue_tx_from_out_point
|
251
|
+
tx = Tapyrus::Tx.new
|
252
|
+
receiver_colored_script = Tapyrus::Script.parse_from_payload('21c20000000000000000000000000000000000000000000000000000000000000000bc76a914000000000000000000000000000000000000000088ac'.htb)
|
253
|
+
tx.outputs << Tapyrus::TxOut.new(value: 0, script_pubkey: receiver_colored_script)
|
254
|
+
FeeEstimator.dummy_tx(tx)
|
255
|
+
end
|
211
256
|
end
|
212
257
|
|
213
258
|
attr_reader :color_id
|
@@ -230,12 +275,33 @@ module Glueby
|
|
230
275
|
token_metadata = Glueby::Contract::AR::TokenMetadata.find_by(color_id: color_id.to_hex)
|
231
276
|
raise Glueby::Contract::Errors::UnknownScriptPubkey unless valid_reissuer?(wallet: issuer, token_metadata: token_metadata)
|
232
277
|
|
233
|
-
|
234
|
-
|
235
|
-
|
278
|
+
txb = Internal::ContractBuilder.new(
|
279
|
+
sender_wallet: issuer.internal_wallet,
|
280
|
+
fee_estimator: fee_estimator,
|
281
|
+
use_auto_fulfill_inputs: true
|
282
|
+
)
|
283
|
+
|
236
284
|
if token_metadata
|
237
|
-
|
285
|
+
txb.add_p2c_utxo_to!(
|
286
|
+
metadata: metadata,
|
287
|
+
amount: FeeEstimator::Fixed.new.fixed_fee,
|
288
|
+
p2c_address: token_metadata.p2c_address,
|
289
|
+
payment_base: token_metadata.payment_base,
|
290
|
+
only_finalized: only_finalized?,
|
291
|
+
fee_estimator: Contract::FeeEstimator::Fixed.new
|
292
|
+
)
|
293
|
+
else
|
294
|
+
txb.add_utxo_to!(
|
295
|
+
address: @script_pubkey.to_addr,
|
296
|
+
amount: FeeEstimator::Fixed.new.fixed_fee,
|
297
|
+
only_finalized: only_finalized?,
|
298
|
+
fee_estimator: Contract::FeeEstimator::Fixed.new
|
299
|
+
)
|
238
300
|
end
|
301
|
+
|
302
|
+
tx = txb.reissuable_split(@script_pubkey, issuer.internal_wallet.receive_address, amount, split)
|
303
|
+
.build
|
304
|
+
|
239
305
|
tx = issuer.internal_wallet.broadcast(tx)
|
240
306
|
|
241
307
|
[color_id, tx]
|
@@ -252,18 +318,13 @@ module Glueby
|
|
252
318
|
# @raise [InsufficientTokens] if wallet does not have enough token to send.
|
253
319
|
# @raise [InvalidAmount] if amount is not positive integer.
|
254
320
|
def transfer!(sender:, receiver_address:, amount: 1, fee_estimator: FeeEstimator::Fixed.new)
|
255
|
-
|
256
|
-
|
257
|
-
tx = create_transfer_tx(
|
258
|
-
color_id: color_id,
|
321
|
+
multi_transfer!(
|
259
322
|
sender: sender,
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
sender.internal_wallet.broadcast(tx)
|
266
|
-
[color_id, tx]
|
323
|
+
receivers: [{
|
324
|
+
address: receiver_address,
|
325
|
+
amount: amount
|
326
|
+
}],
|
327
|
+
fee_estimator: fee_estimator)
|
267
328
|
end
|
268
329
|
|
269
330
|
# Send the tokens to multiple wallets
|
@@ -280,14 +341,20 @@ module Glueby
|
|
280
341
|
raise Glueby::Contract::Errors::InvalidAmount unless r[:amount].positive?
|
281
342
|
end
|
282
343
|
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
344
|
+
txb = Internal::ContractBuilder
|
345
|
+
.new(
|
346
|
+
sender_wallet: sender.internal_wallet,
|
347
|
+
fee_estimator: fee_estimator,
|
348
|
+
use_unfinalized_utxo: !only_finalized?,
|
349
|
+
use_auto_fulfill_inputs: true
|
350
|
+
)
|
351
|
+
.change_address(sender.internal_wallet.receive_address, color_id)
|
352
|
+
|
353
|
+
receivers.each do |r|
|
354
|
+
txb.pay(r[:address], r[:amount].to_i, color_id)
|
355
|
+
end
|
356
|
+
|
357
|
+
tx = sender.internal_wallet.broadcast(txb.build)
|
291
358
|
[color_id, tx]
|
292
359
|
end
|
293
360
|
|
@@ -306,7 +373,17 @@ module Glueby
|
|
306
373
|
raise Glueby::Contract::Errors::InsufficientTokens unless balance
|
307
374
|
raise Glueby::Contract::Errors::InsufficientTokens if balance < amount
|
308
375
|
|
309
|
-
tx =
|
376
|
+
tx = Internal::ContractBuilder
|
377
|
+
.new(
|
378
|
+
sender_wallet: sender.internal_wallet,
|
379
|
+
fee_estimator: fee_estimator,
|
380
|
+
use_unfinalized_utxo: !only_finalized?,
|
381
|
+
use_auto_fulfill_inputs: true
|
382
|
+
)
|
383
|
+
.burn(amount, color_id)
|
384
|
+
.change_address(sender.internal_wallet.receive_address, color_id)
|
385
|
+
.build
|
386
|
+
|
310
387
|
sender.internal_wallet.broadcast(tx)
|
311
388
|
end
|
312
389
|
|
@@ -314,10 +391,10 @@ module Glueby
|
|
314
391
|
# @param wallet [Glueby::Wallet]
|
315
392
|
# @return [Integer] amount of utxo value associated with this token.
|
316
393
|
def amount(wallet:)
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
394
|
+
amount, _utxos = wallet
|
395
|
+
.internal_wallet
|
396
|
+
.collect_colored_outputs(color_id, nil, nil, only_finalized?)
|
397
|
+
amount
|
321
398
|
end
|
322
399
|
|
323
400
|
# Return metadata for this token
|