glueby 1.2.3 → 1.3.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/.github/workflows/ruby.yml +4 -8
- data/.ruby-version +1 -1
- data/Gemfile +2 -0
- data/glueby.gemspec +2 -1
- data/lib/generators/glueby/contract/templates/timestamp_table.rb.erb +1 -1
- data/lib/generators/glueby/contract/templates/utxo_table.rb.erb +1 -0
- data/lib/glueby/configuration.rb +1 -1
- data/lib/glueby/contract/active_record/timestamp.rb +25 -6
- data/lib/glueby/contract/errors.rb +1 -0
- data/lib/glueby/contract/timestamp.rb +53 -4
- data/lib/glueby/contract/token.rb +0 -27
- data/lib/glueby/contract/tx_builder.rb +5 -8
- data/lib/glueby/fee_provider/tasks.rb +0 -10
- data/lib/glueby/internal/contract_builder.rb +1 -1
- data/lib/glueby/internal/wallet/abstract_wallet_adapter.rb +20 -2
- data/lib/glueby/internal/wallet/active_record/utxo.rb +1 -0
- data/lib/glueby/internal/wallet/active_record_wallet_adapter.rb +43 -22
- data/lib/glueby/internal/wallet/tapyrus_core_wallet_adapter.rb +9 -2
- data/lib/glueby/internal/wallet.rb +24 -9
- data/lib/glueby/version.rb +1 -1
- data/lib/glueby/wallet.rb +4 -0
- data/lib/glueby.rb +1 -1
- metadata +21 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 41286c658b45bd9914f4c46f27e8e0f8696b61a8d763b5fcc2b0117d0e91668d
|
4
|
+
data.tar.gz: 3237815c98b14f3fc126e5531c8ff229d468fe77832bcca4b22828ffd386c7bd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dad03d9f436a2720b854450fb95e8fab7fedde3d721f5db3bf0c69c1aa7b818ebfc359cda0c1057f4d98075295459f55f5261c69a4cc99a49f752bba3683e95c
|
7
|
+
data.tar.gz: eb8f0724b6b7b849a343b14e5630480584df5b6f408509dcdeebcca711055f8bcd3a62c188130b75118a7f93e18e015aeb2afd60784d4382cd27741b010f2c06
|
data/.github/workflows/ruby.yml
CHANGED
@@ -7,19 +7,15 @@
|
|
7
7
|
|
8
8
|
name: Ruby
|
9
9
|
|
10
|
-
on:
|
11
|
-
push:
|
12
|
-
branches: [master, v1.1, v1.2]
|
13
|
-
pull_request:
|
14
|
-
branches: [master, v1.1, v1.2]
|
10
|
+
on: [push,pull_request]
|
15
11
|
|
16
12
|
jobs:
|
17
13
|
test:
|
18
14
|
runs-on: ubuntu-latest
|
19
15
|
strategy:
|
20
16
|
matrix:
|
21
|
-
ruby-version: ["
|
22
|
-
|
17
|
+
ruby-version: ["3.0", "3.1", "3.2", "3.3"]
|
18
|
+
permissions: write-all
|
23
19
|
steps:
|
24
20
|
- run: docker pull tapyrus/tapyrusd:v0.5.2
|
25
21
|
- uses: actions/checkout@v2
|
@@ -31,4 +27,4 @@ jobs:
|
|
31
27
|
ruby-version: ${{ matrix.ruby-version }}
|
32
28
|
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
|
33
29
|
- name: Run tests
|
34
|
-
run: bundle exec rake
|
30
|
+
run: bundle exec rake
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
ruby-3.
|
1
|
+
ruby-3.3.0
|
data/Gemfile
CHANGED
data/glueby.gemspec
CHANGED
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
|
|
10
10
|
spec.description = %q{A Ruby library of smart contracts that can be used on Tapyrus.}
|
11
11
|
spec.homepage = "https://github.com/chaintope/glueby"
|
12
12
|
spec.license = "MIT"
|
13
|
-
spec.required_ruby_version = Gem::Requirement.new(">=
|
13
|
+
spec.required_ruby_version = Gem::Requirement.new(">= 3.0.0")
|
14
14
|
|
15
15
|
|
16
16
|
spec.metadata["homepage_uri"] = spec.homepage
|
@@ -28,6 +28,7 @@ Gem::Specification.new do |spec|
|
|
28
28
|
|
29
29
|
spec.add_runtime_dependency 'tapyrus', '>= 0.3.1'
|
30
30
|
spec.add_runtime_dependency 'activerecord', '~> 7.0.0'
|
31
|
+
spec.add_runtime_dependency 'kaminari'
|
31
32
|
spec.add_development_dependency 'sqlite3'
|
32
33
|
spec.add_development_dependency 'mysql2'
|
33
34
|
spec.add_development_dependency 'rails', '~> 7.0.0'
|
@@ -13,7 +13,7 @@ class CreateTimestamp < ActiveRecord::Migration<%= migration_version %>
|
|
13
13
|
t.string :payment_base
|
14
14
|
t.bigint :prev_id
|
15
15
|
t.boolean :latest, null: false, default: true
|
16
|
-
t.
|
16
|
+
t.string :version, null: false, default: "1"
|
17
17
|
end
|
18
18
|
|
19
19
|
add_index :glueby_timestamps, [:prev_id], unique: true
|
data/lib/glueby/configuration.rb
CHANGED
@@ -24,7 +24,7 @@ module Glueby
|
|
24
24
|
end
|
25
25
|
|
26
26
|
# Specify wallet adapter.
|
27
|
-
# @param [Symbol] adapter - The adapter type :activerecord or :
|
27
|
+
# @param [Symbol] adapter - The adapter type :activerecord, :core, or :mysql is currently supported.
|
28
28
|
def wallet_adapter=(adapter)
|
29
29
|
case adapter
|
30
30
|
when :core
|
@@ -9,7 +9,14 @@ module Glueby
|
|
9
9
|
|
10
10
|
attr_reader :tx
|
11
11
|
|
12
|
-
belongs_to :prev, class_name: 'Glueby::Contract::AR::Timestamp', optional: true
|
12
|
+
belongs_to :prev, class_name: 'Glueby::Contract::AR::Timestamp', inverse_of: :next, optional: true
|
13
|
+
has_one :next, class_name: 'Glueby::Contract::AR::Timestamp', foreign_key: 'prev_id'
|
14
|
+
|
15
|
+
validates :version, presence: true, inclusion: { in: ['1', '2'] }
|
16
|
+
|
17
|
+
def next_id
|
18
|
+
self.next&.id
|
19
|
+
end
|
13
20
|
|
14
21
|
validate :validate_prev
|
15
22
|
|
@@ -35,11 +42,14 @@ module Glueby
|
|
35
42
|
# - content
|
36
43
|
# - prefix(optional)
|
37
44
|
# - timestamp_type(optional)
|
38
|
-
# -
|
45
|
+
# - version [String] Version of the timestamp recording method.
|
46
|
+
# The format in which the timestamp is recorded differs depending on the version.
|
47
|
+
# Version "1" treats the specified content and prefix as a binary string.
|
48
|
+
# Version "2" treats the specified content and prefix as a hexadecimal string with the string set to prefix and content.
|
39
49
|
# @raise [Glueby::ArgumentError] If the timestamp_type is not in :simple or :trackable
|
40
50
|
def initialize(attributes = nil)
|
41
51
|
# Set content_hash from :content attribute
|
42
|
-
hex = attributes[:
|
52
|
+
hex = attributes[:version] == '1' ? false : true
|
43
53
|
content_hash = Timestamp.digest_content(attributes[:content], attributes[:digest] || :sha256, hex)
|
44
54
|
super(
|
45
55
|
wallet_id: attributes[:wallet_id],
|
@@ -48,7 +58,7 @@ module Glueby
|
|
48
58
|
status: :init,
|
49
59
|
timestamp_type: attributes[:timestamp_type] || :simple,
|
50
60
|
prev_id: attributes[:prev_id],
|
51
|
-
|
61
|
+
version: attributes[:version]
|
52
62
|
)
|
53
63
|
rescue ::ArgumentError => e
|
54
64
|
raise Glueby::ArgumentError, e.message
|
@@ -114,6 +124,7 @@ module Glueby
|
|
114
124
|
|
115
125
|
if update_trackable?
|
116
126
|
prev.latest = false
|
127
|
+
prev.next = self
|
117
128
|
prev.save!
|
118
129
|
end
|
119
130
|
end
|
@@ -129,6 +140,12 @@ module Glueby
|
|
129
140
|
raise Errors::FailedToBroadcast, "failed to broadcast (id=#{id}, reason=#{e.message})"
|
130
141
|
end
|
131
142
|
|
143
|
+
def hex?
|
144
|
+
version != '1'
|
145
|
+
end
|
146
|
+
|
147
|
+
alias_method :hex, :hex?
|
148
|
+
|
132
149
|
private
|
133
150
|
|
134
151
|
def wallet
|
@@ -139,11 +156,13 @@ module Glueby
|
|
139
156
|
builder = builder_class.new(wallet, fee_estimator)
|
140
157
|
|
141
158
|
if builder.instance_of?(Contract::Timestamp::TxBuilder::UpdatingTrackable)
|
159
|
+
prev_prefix = prev.hex ? prev.prefix&.htb : prev.prefix
|
160
|
+
prev_content_hash = prev.hex ? prev.content_hash&.htb : prev.content_hash
|
142
161
|
builder.set_prev_timestamp_info(
|
143
162
|
timestamp_utxo: prev.utxo,
|
144
163
|
payment_base: prev.payment_base,
|
145
|
-
prefix:
|
146
|
-
data:
|
164
|
+
prefix: prev_prefix,
|
165
|
+
data: prev_content_hash
|
147
166
|
)
|
148
167
|
end
|
149
168
|
|
@@ -15,6 +15,7 @@ module Glueby
|
|
15
15
|
class UnsupportedTokenType < ArgumentError; end
|
16
16
|
class UnknownScriptPubkey < ArgumentError; end
|
17
17
|
class UnsupportedDigestType < ArgumentError; end
|
18
|
+
class UnsupportedTimestampVersion < ArgumentError; end
|
18
19
|
class PrevTimestampNotFound < ArgumentError; end
|
19
20
|
class PrevTimestampIsNotTrackable < ArgumentError; end
|
20
21
|
class UnnecessaryPrevTimestamp < ArgumentError; end
|
@@ -7,6 +7,51 @@ module Glueby
|
|
7
7
|
# * 1 output to send the change TPC back to the wallet.
|
8
8
|
#
|
9
9
|
# Storing timestamp transaction to the blockchain enables everyone to verify that the data existed at that time and a user signed it.
|
10
|
+
#
|
11
|
+
# == Versioning Timestamp
|
12
|
+
#
|
13
|
+
# The timestamp has an attribute called "version".
|
14
|
+
# Version indicates how the timestamp is recorded in the blockchain. Currently, only versions 1 and 2 are supported, and each is recorded in the following manner
|
15
|
+
# * Version 1: The first version of the blockchain is used to record timestamps.
|
16
|
+
# treats the content and prefix received as parameters as a binary string
|
17
|
+
# * Version 2:.
|
18
|
+
# treats the specified content and prefix as a hexadecimal string with the string set to prefix and content.
|
19
|
+
#
|
20
|
+
# For example, when recording a simple type of timestamp, the difference between the content recorded by version 1 and version 2 is as follows
|
21
|
+
# Version 1:
|
22
|
+
# Save the timestamp as follows:
|
23
|
+
#
|
24
|
+
# Glueby::Contract::Timestamp.new(
|
25
|
+
# wallet: wallet,
|
26
|
+
# content: "1234",
|
27
|
+
# prefix: "071222",
|
28
|
+
# digest: :none,
|
29
|
+
# version: "1"
|
30
|
+
# )
|
31
|
+
#
|
32
|
+
# The output script of the recorded transaction will include OP_RETURN and will look like this:
|
33
|
+
#
|
34
|
+
# OP_RETURN 30373132323231323334
|
35
|
+
#
|
36
|
+
# Note that prefix: "071222" and content: "1234" are interpreted as ASCII strings and their hexadecimal representation "3037313232323132323334" is recorded in the actual blockchain, respectively.
|
37
|
+
#
|
38
|
+
# Version 2:
|
39
|
+
#
|
40
|
+
# To save the timestamp in version 2, simply change the version of the previous example to "2".
|
41
|
+
#
|
42
|
+
# Glueby::Contract::Timestamp.new(
|
43
|
+
# wallet: wallet,
|
44
|
+
# content: "1234",
|
45
|
+
# prefix: "071222",
|
46
|
+
# digest: :none,
|
47
|
+
# version: "2"
|
48
|
+
# )
|
49
|
+
#
|
50
|
+
# The output script will look like this:
|
51
|
+
#
|
52
|
+
# OP_RETURN 0712221234
|
53
|
+
#
|
54
|
+
# In this case, prefix: "071222" and content: "1234" are treated as a hexadecimal string and recorded directly in the blockchain.
|
10
55
|
class Timestamp
|
11
56
|
P2C_DEFAULT_VALUE = 1_000
|
12
57
|
|
@@ -29,7 +74,10 @@ module Glueby
|
|
29
74
|
# - :simple
|
30
75
|
# - :trackable
|
31
76
|
# @param [Integer] prev_timestamp_id The id column of glueby_timestamps that will be updated by the timestamp that will be created
|
32
|
-
# @param [
|
77
|
+
# @param [String] version Version of the timestamp recording method.
|
78
|
+
# The format in which the timestamp is recorded differs depending on the version.
|
79
|
+
# Version "1" treats the specified content and prefix as a binary string.
|
80
|
+
# Version "2" treats the specified content and prefix as a hexadecimal string with the string set to prefix and content.
|
33
81
|
# @raise [Glueby::Contract::Errors::UnsupportedDigestType] if digest is unsupported
|
34
82
|
# @raise [Glueby::Contract::Errors::InvalidTimestampType] if timestamp_type is unsupported
|
35
83
|
def initialize(
|
@@ -41,7 +89,7 @@ module Glueby
|
|
41
89
|
utxo_provider: nil,
|
42
90
|
timestamp_type: :simple,
|
43
91
|
prev_timestamp_id: nil,
|
44
|
-
|
92
|
+
version:
|
45
93
|
)
|
46
94
|
@wallet = wallet
|
47
95
|
@content = content
|
@@ -53,7 +101,8 @@ module Glueby
|
|
53
101
|
raise Glueby::Contract::Errors::InvalidTimestampType, "#{timestamp_type} is invalid type, supported types are :simple, and :trackable." unless [:simple, :trackable].include?(timestamp_type)
|
54
102
|
@timestamp_type = timestamp_type
|
55
103
|
@prev_timestamp_id = prev_timestamp_id
|
56
|
-
|
104
|
+
raise Glueby::Contract::Errors::UnsupportedTimestampVersion, "#{version} is unsupported, supported versions are '1' and '2'." unless ['1', '2'].include?(version)
|
105
|
+
@version = version
|
57
106
|
end
|
58
107
|
|
59
108
|
# broadcast to Tapyrus Core
|
@@ -70,7 +119,7 @@ module Glueby
|
|
70
119
|
timestamp_type: @timestamp_type,
|
71
120
|
digest: @digest,
|
72
121
|
prev_id: @prev_timestamp_id,
|
73
|
-
|
122
|
+
version: @version
|
74
123
|
)
|
75
124
|
@ar.save_with_broadcast!(fee_estimator: @fee_estimator, utxo_provider: @utxo_provider)
|
76
125
|
@ar.txid
|
@@ -86,27 +86,8 @@ module Glueby
|
|
86
86
|
Glueby::AR::SystemInformation.use_only_finalized_utxo?
|
87
87
|
end
|
88
88
|
|
89
|
-
# Sign to pay-to-contract output.
|
90
|
-
#
|
91
|
-
# @param issuer [Glueby::Walelt] Issuer of the token
|
92
|
-
# @param tx [Tapyrus::Tx] The transaction to be signed with metadata
|
93
|
-
# @param funding_tx [Tapyrus::Tx] The funding transaction that has pay-to-contract output in its first output
|
94
|
-
# @param payment_base [String] The public key used to generate pay to contract public key
|
95
|
-
# @param metadata [String] Data that represents token metadata
|
96
|
-
# @return [Tapyrus::Tx] signed tx
|
97
|
-
def sign_to_p2c_output(issuer, tx, funding_tx, payment_base, metadata)
|
98
|
-
utxo = { txid: funding_tx.txid, vout: 0, script_pubkey: funding_tx.outputs[0].script_pubkey.to_hex }
|
99
|
-
issuer.internal_wallet.sign_to_pay_to_contract_address(tx, utxo, payment_base, metadata)
|
100
|
-
end
|
101
|
-
|
102
89
|
private
|
103
90
|
|
104
|
-
def create_p2c_address(wallet, metadata)
|
105
|
-
p2c_address, payment_base = wallet.internal_wallet.create_pay_to_contract_address(metadata)
|
106
|
-
script = Tapyrus::Script.parse_from_addr(p2c_address)
|
107
|
-
[script, p2c_address, payment_base]
|
108
|
-
end
|
109
|
-
|
110
91
|
def issue_reissuable_token(issuer:, amount:, split: 1, fee_estimator:, metadata: nil)
|
111
92
|
txb = Internal::ContractBuilder.new(
|
112
93
|
sender_wallet: issuer.internal_wallet,
|
@@ -244,14 +225,6 @@ module Glueby
|
|
244
225
|
end
|
245
226
|
end
|
246
227
|
end
|
247
|
-
|
248
|
-
# Add dummy inputs and outputs to tx for issue non-reissuable transaction and nft transaction
|
249
|
-
def dummy_issue_tx_from_out_point
|
250
|
-
tx = Tapyrus::Tx.new
|
251
|
-
receiver_colored_script = Tapyrus::Script.parse_from_payload('21c20000000000000000000000000000000000000000000000000000000000000000bc76a914000000000000000000000000000000000000000088ac'.htb)
|
252
|
-
tx.outputs << Tapyrus::TxOut.new(value: 0, script_pubkey: receiver_colored_script)
|
253
|
-
FeeEstimator.dummy_tx(tx)
|
254
|
-
end
|
255
228
|
end
|
256
229
|
|
257
230
|
attr_reader :color_id
|
@@ -206,8 +206,8 @@ module Glueby
|
|
206
206
|
tx = Tapyrus::Tx.new
|
207
207
|
|
208
208
|
amount = receivers.reduce(0) { |sum, r| sum + r[:amount].to_i }
|
209
|
-
utxos = sender.internal_wallet.list_unspent(only_finalized)
|
210
|
-
sum_token, outputs = collect_colored_outputs(utxos,
|
209
|
+
utxos = sender.internal_wallet.list_unspent(only_finalized, color_id: color_id)
|
210
|
+
sum_token, outputs = collect_colored_outputs(utxos, amount)
|
211
211
|
fill_input(tx, outputs)
|
212
212
|
|
213
213
|
receivers.each do |r|
|
@@ -247,8 +247,8 @@ module Glueby
|
|
247
247
|
def create_burn_tx(color_id:, sender:, amount: 0, fee_estimator: FeeEstimator::Fixed.new, only_finalized: true)
|
248
248
|
tx = Tapyrus::Tx.new
|
249
249
|
|
250
|
-
utxos = sender.internal_wallet.list_unspent(only_finalized)
|
251
|
-
sum_token, outputs = collect_colored_outputs(utxos,
|
250
|
+
utxos = sender.internal_wallet.list_unspent(only_finalized, color_id: color_id)
|
251
|
+
sum_token, outputs = collect_colored_outputs(utxos, amount)
|
252
252
|
fill_input(tx, outputs)
|
253
253
|
|
254
254
|
fill_change_token(tx, sender, sum_token - amount, color_id) if amount.positive?
|
@@ -319,12 +319,9 @@ module Glueby
|
|
319
319
|
# Returns the set of utxos that satisfies the specified amount and has the specified color_id.
|
320
320
|
# if amount is not specified or 0, return all utxos with color_id
|
321
321
|
# @param results [Array] response of Glueby::Internal::Wallet#list_unspent
|
322
|
-
# @param color_id [Tapyrus::Color::ColorIdentifier] color identifier
|
323
322
|
# @param amount [Integer]
|
324
|
-
def collect_colored_outputs(results,
|
323
|
+
def collect_colored_outputs(results, amount = 0)
|
325
324
|
results = results.inject([0, []]) do |sum, output|
|
326
|
-
next sum unless output[:color_id] == color_id.to_hex
|
327
|
-
|
328
325
|
new_sum = sum[0] + output[:amount]
|
329
326
|
new_outputs = sum[1] << output
|
330
327
|
return [new_sum, new_outputs] if new_sum >= amount && amount.positive?
|
@@ -90,16 +90,6 @@ module Glueby
|
|
90
90
|
|
91
91
|
private
|
92
92
|
|
93
|
-
def check_wallet_amount!
|
94
|
-
if tpc_amount < fee_provider.fixed_fee
|
95
|
-
raise InsufficientTPC, <<~MESSAGE
|
96
|
-
FeeProvider has insufficient TPC to create fee outputs to fill the UTXO pool.
|
97
|
-
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}'
|
98
|
-
2. Then create UTXOs for paying in UTXO pool with 'rake glueby:fee_provider:manage_utxo_pool'
|
99
|
-
MESSAGE
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
93
|
def tpc_amount
|
104
94
|
wallet.balance(false)
|
105
95
|
end
|
@@ -357,7 +357,7 @@ module Glueby
|
|
357
357
|
end
|
358
358
|
|
359
359
|
def get_fee_estimator(fee_estimator_name)
|
360
|
-
Glueby::Contract::FeeEstimator.
|
360
|
+
Glueby::Contract::FeeEstimator.const_get(fee_estimator_name.capitalize, false).new
|
361
361
|
end
|
362
362
|
|
363
363
|
def valid_fee_estimator?(fee_estimator)
|
@@ -65,6 +65,21 @@ module Glueby
|
|
65
65
|
raise NotImplementedError, "You must implement #{self.class}##{__method__}"
|
66
66
|
end
|
67
67
|
|
68
|
+
# Returns all tokens with specified color_id
|
69
|
+
#
|
70
|
+
# @param [String] wallet_id - The wallet id that is offered by `create_wallet()` method.
|
71
|
+
# @param [Boolean] only_finalized - includes only finalized UTXO value if it
|
72
|
+
# is true. Default is true.
|
73
|
+
# @param [Tapyrus::Color::ColorIdentifier] color_id The color identifier associated with UTXO.
|
74
|
+
# It will return only UTXOs with specified color_id. If color_id is nil, it will return all UTXOs.
|
75
|
+
# If Tapyrus::Color::ColorIdentifier.default is specified, it will return uncolored UTXOs(i.e. TPC)
|
76
|
+
# @param [Integer] page - The page parameter is responsible for specifying the current page being viewed within the paginated results. default is 1.
|
77
|
+
# @param [Integer] per - The per parameter is used to determine the number of items to display per page. default is 25.
|
78
|
+
# @return [Array<Utxo>] The array of the utxos with specified color_id
|
79
|
+
def list_unspent_with_count(wallet_id, only_finalized = true, label = nil, color_id: nil, page: 1, per: 25)
|
80
|
+
raise NotImplementedError, "You must implement #{self.class}##{__method__}"
|
81
|
+
end
|
82
|
+
|
68
83
|
# Returns the UTXOs that the wallet has.
|
69
84
|
# If label is specified, return UTXOs filtered with label
|
70
85
|
#
|
@@ -74,6 +89,9 @@ module Glueby
|
|
74
89
|
# @param [String] label - Label for filtering UTXOs
|
75
90
|
# - If label is nil or :unlabeled, only unlabeled UTXOs will be returned.
|
76
91
|
# - If label=:all, it will return all utxos
|
92
|
+
# @param [Tapyrus::Color::ColorIdentifier] color_id - The color identifier.
|
93
|
+
# It will return only UTXOs with specified color_id. If color_id is nil, it will return all UTXOs.
|
94
|
+
# If Tapyrus::Color::ColorIdentifier.default is specified, it will return uncolored UTXOs(i.e. TPC)
|
77
95
|
# @return [Array of UTXO]
|
78
96
|
#
|
79
97
|
# ## The UTXO structure
|
@@ -84,7 +102,7 @@ module Glueby
|
|
84
102
|
# - finalized: [Boolean] Whether the UTXO is finalized
|
85
103
|
# - color_id: [String] Color id of the UTXO. If it is TPC UTXO, color_id is nil.
|
86
104
|
# - script_pubkey: [String] Script pubkey of the UTXO
|
87
|
-
def list_unspent(wallet_id, only_finalized = true, label = nil)
|
105
|
+
def list_unspent(wallet_id, only_finalized = true, label = nil, color_id: nil)
|
88
106
|
raise NotImplementedError, "You must implement #{self.class}##{__method__}"
|
89
107
|
end
|
90
108
|
|
@@ -139,7 +157,7 @@ module Glueby
|
|
139
157
|
|
140
158
|
# Returns information for the addresses
|
141
159
|
#
|
142
|
-
# @param [String]
|
160
|
+
# @param [String, Array<String>] addresses - The p2pkh address to get information about
|
143
161
|
# @return [Array<Hash>] The array of hash instance which has keys wallet_id, label and purpose.
|
144
162
|
# Returns blank array if the key correspond with the address is not exist.
|
145
163
|
def get_addresses_info(addresses)
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'securerandom'
|
4
|
+
require 'kaminari'
|
4
5
|
|
5
6
|
module Glueby
|
6
7
|
module Internal
|
@@ -89,29 +90,18 @@ module Glueby
|
|
89
90
|
utxos.sum(&:value)
|
90
91
|
end
|
91
92
|
|
92
|
-
def
|
93
|
-
|
94
|
-
utxos =
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
else
|
101
|
-
utxos
|
102
|
-
end
|
93
|
+
def list_unspent_with_count(wallet_id, only_finalized = true, label = nil, color_id: nil, page: 1, per: 25)
|
94
|
+
utxos = list_unspent_internal(wallet_id, color_id, only_finalized, label)
|
95
|
+
utxos = utxos.page(page).per(per) if per > 0
|
96
|
+
{
|
97
|
+
count: utxos.total_count,
|
98
|
+
outputs: utxos_to_h(utxos)
|
99
|
+
}
|
100
|
+
end
|
103
101
|
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
vout: utxo.index,
|
108
|
-
script_pubkey: utxo.script_pubkey,
|
109
|
-
color_id: utxo.color_id,
|
110
|
-
amount: utxo.value,
|
111
|
-
finalized: utxo.status == 'finalized',
|
112
|
-
label: utxo.label
|
113
|
-
}
|
114
|
-
end
|
102
|
+
def list_unspent(wallet_id, only_finalized = true, label = nil, color_id: nil)
|
103
|
+
utxos = list_unspent_internal(wallet_id, color_id, only_finalized, label)
|
104
|
+
utxos_to_h(utxos)
|
115
105
|
end
|
116
106
|
|
117
107
|
def sign_tx(wallet_id, tx, prevtxs = [], sighashtype: Tapyrus::SIGHASH_TYPE[:all])
|
@@ -245,6 +235,37 @@ module Glueby
|
|
245
235
|
key_type: Tapyrus::Key::TYPES[:compressed]
|
246
236
|
)
|
247
237
|
end
|
238
|
+
|
239
|
+
def list_unspent_internal(wallet_id, color_id = nil, only_finalized = true, label = nil)
|
240
|
+
wallet = AR::Wallet.find_by(wallet_id: wallet_id)
|
241
|
+
utxos = wallet.utxos.where(locked_at: nil)
|
242
|
+
utxos = utxos.where(color_id: color_id.to_hex) if color_id && !color_id.default?
|
243
|
+
utxos = utxos.where(color_id: nil) if color_id && color_id.default?
|
244
|
+
utxos = utxos.where(status: :finalized) if only_finalized
|
245
|
+
utxos = utxos.order(:id)
|
246
|
+
utxos = if [:unlabeled, nil].include?(label)
|
247
|
+
utxos = utxos.where(label: nil)
|
248
|
+
elsif label && (label != :all)
|
249
|
+
utxos = utxos.where(label: label)
|
250
|
+
else
|
251
|
+
utxos
|
252
|
+
end
|
253
|
+
utxos
|
254
|
+
end
|
255
|
+
|
256
|
+
def utxos_to_h(utxos)
|
257
|
+
utxos.map do |utxo|
|
258
|
+
{
|
259
|
+
txid: utxo.txid,
|
260
|
+
vout: utxo.index,
|
261
|
+
script_pubkey: utxo.script_pubkey,
|
262
|
+
color_id: utxo.color_id,
|
263
|
+
amount: utxo.value,
|
264
|
+
finalized: utxo.status == 'finalized',
|
265
|
+
label: utxo.label
|
266
|
+
}
|
267
|
+
end
|
268
|
+
end
|
248
269
|
end
|
249
270
|
end
|
250
271
|
end
|
@@ -84,7 +84,7 @@ module Glueby
|
|
84
84
|
|
85
85
|
# If label=nil, it will return unlabeled utxos to protect labeled utxos for specific purpose
|
86
86
|
# If label=:all, it will return all utxos
|
87
|
-
def list_unspent(wallet_id, only_finalized = true, label = nil)
|
87
|
+
def list_unspent(wallet_id, only_finalized = true, label = nil, color_id: nil)
|
88
88
|
perform_as(wallet_id) do |client|
|
89
89
|
min_conf = only_finalized ? 1 : 0
|
90
90
|
res = client.listunspent(min_conf)
|
@@ -97,6 +97,13 @@ module Glueby
|
|
97
97
|
res
|
98
98
|
end
|
99
99
|
|
100
|
+
if color_id
|
101
|
+
res = res.filter do |i|
|
102
|
+
script = Tapyrus::Script.parse_from_payload(i['scriptPubKey'].htb)
|
103
|
+
script.cp2pkh? || script.cp2sh? && color_id == Tapyrus::Color::ColorIdentifier.parse_from_payload(script.chunks[0].pushed_data)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
100
107
|
res.map do |i|
|
101
108
|
script = Tapyrus::Script.parse_from_payload(i['scriptPubKey'].htb)
|
102
109
|
color_id = if script.cp2pkh? || script.cp2sh?
|
@@ -177,7 +184,7 @@ module Glueby
|
|
177
184
|
type = case sighashtype & (~(Tapyrus::SIGHASH_TYPE[:anyonecanpay]))
|
178
185
|
when Tapyrus::SIGHASH_TYPE[:all] then 'ALL'
|
179
186
|
when Tapyrus::SIGHASH_TYPE[:none] then 'NONE'
|
180
|
-
when Tapyrus::SIGHASH_TYPE[:single] then '
|
187
|
+
when Tapyrus::SIGHASH_TYPE[:single] then 'SINGLE'
|
181
188
|
else
|
182
189
|
raise Errors::InvalidSighashType, "Invalid sighash type '#{sighashtype}'"
|
183
190
|
end
|
@@ -93,9 +93,25 @@ module Glueby
|
|
93
93
|
# @param label [String] This label is used to filtered the UTXOs with labeled if a key or Utxo is labeled.
|
94
94
|
# - If label is nil or :unlabeled, only unlabeled UTXOs will be returned.
|
95
95
|
# - If label=:all, all UTXOs will be returned.
|
96
|
-
|
96
|
+
# @param color_id [Tapyrus::Color::ColorIdentifier] The color identifier associated with UTXO.
|
97
|
+
# It will return only UTXOs with specified color_id. If color_id is nil, it will return all UTXOs.
|
98
|
+
# If Tapyrus::Color::ColorIdentifier.default is specified, it will return uncolored UTXOs(i.e. TPC)
|
99
|
+
# @param page [Integer] The page parameter is responsible for specifying the current page being viewed within the paginated results. default is 1.
|
100
|
+
# @param per [Integer] The per parameter is used to determine the number of items to display per page. default is 25.
|
101
|
+
def list_unspent_with_count(only_finalized = true, label = nil, color_id: nil, page: 1, per: 25)
|
102
|
+
wallet_adapter.list_unspent_with_count(id, only_finalized, label, color_id: color_id, page: page, per: per)
|
103
|
+
end
|
104
|
+
|
105
|
+
# @param only_finalized [Boolean] The flag to get a UTXO with status only finalized
|
106
|
+
# @param label [String] This label is used to filtered the UTXOs with labeled if a key or Utxo is labeled.
|
107
|
+
# - If label is nil or :unlabeled, only unlabeled UTXOs will be returned.
|
108
|
+
# - If label=:all, all UTXOs will be returned.
|
109
|
+
# @param color_id [Tapyrus::Color::ColorIdentifier] The color identifier associated with UTXO.
|
110
|
+
# It will return only UTXOs with specified color_id. If color_id is nil, it will return all UTXOs.
|
111
|
+
# If Tapyrus::Color::ColorIdentifier.default is specified, it will return uncolored UTXOs(i.e. TPC)
|
112
|
+
def list_unspent(only_finalized = true, label = :unlabeled, color_id: nil )
|
97
113
|
label = :unlabeled unless label
|
98
|
-
wallet_adapter.list_unspent(id, only_finalized, label)
|
114
|
+
wallet_adapter.list_unspent(id, only_finalized, label, color_id: color_id)
|
99
115
|
end
|
100
116
|
|
101
117
|
def lock_unspent(utxo)
|
@@ -171,8 +187,7 @@ module Glueby
|
|
171
187
|
lock_utxos = false,
|
172
188
|
excludes = []
|
173
189
|
)
|
174
|
-
collect_utxos(amount, label, only_finalized, shuffle, lock_utxos, excludes) do |output|
|
175
|
-
next false unless output[:color_id].nil?
|
190
|
+
collect_utxos(amount, label, Tapyrus::Color::ColorIdentifier.default, only_finalized, shuffle, lock_utxos, excludes) do |output|
|
176
191
|
next yield(output) if block_given?
|
177
192
|
|
178
193
|
true
|
@@ -206,8 +221,7 @@ module Glueby
|
|
206
221
|
lock_utxos = false,
|
207
222
|
excludes = []
|
208
223
|
)
|
209
|
-
collect_utxos(amount, label, only_finalized, shuffle, lock_utxos, excludes) do |output|
|
210
|
-
next false unless output[:color_id] == color_id.to_hex
|
224
|
+
collect_utxos(amount, label, color_id, only_finalized, shuffle, lock_utxos, excludes) do |output|
|
211
225
|
next yield(output) if block_given?
|
212
226
|
|
213
227
|
true
|
@@ -261,7 +275,7 @@ module Glueby
|
|
261
275
|
while current_amount - fee < target_amount
|
262
276
|
sum, utxos = collect_uncolored_outputs(
|
263
277
|
fee + target_amount - current_amount,
|
264
|
-
nil,
|
278
|
+
nil, false, true, true,
|
265
279
|
provided_utxos,
|
266
280
|
&block
|
267
281
|
)
|
@@ -288,7 +302,8 @@ module Glueby
|
|
288
302
|
def collect_utxos(
|
289
303
|
amount,
|
290
304
|
label,
|
291
|
-
|
305
|
+
color_id,
|
306
|
+
only_finalized = true,
|
292
307
|
shuffle = true,
|
293
308
|
lock_utxos = false,
|
294
309
|
excludes = []
|
@@ -296,7 +311,7 @@ module Glueby
|
|
296
311
|
collect_all = amount.nil?
|
297
312
|
|
298
313
|
raise Glueby::ArgumentError, 'amount must be positive' unless collect_all || amount.positive?
|
299
|
-
utxos = list_unspent(only_finalized, label)
|
314
|
+
utxos = list_unspent(only_finalized, label, color_id: color_id)
|
300
315
|
utxos = utxos.shuffle if shuffle
|
301
316
|
|
302
317
|
r = utxos.inject([0, []]) do |(sum, outputs), output|
|
data/lib/glueby/version.rb
CHANGED
data/lib/glueby/wallet.rb
CHANGED
@@ -46,6 +46,10 @@ module Glueby
|
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
49
|
+
def token_utxos(color_id = nil, only_finalized = true, page = 1, per = 25)
|
50
|
+
@internal_wallet.list_unspent_with_count(only_finalized, nil, color_id: color_id, page: page, per: per)
|
51
|
+
end
|
52
|
+
|
49
53
|
private
|
50
54
|
|
51
55
|
def initialize(internal_wallet)
|
data/lib/glueby.rb
CHANGED
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: 1.
|
4
|
+
version: 1.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- azuchi
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-01-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: tapyrus
|
@@ -38,6 +38,20 @@ dependencies:
|
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: 7.0.0
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: kaminari
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
56
|
name: sqlite3
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -173,7 +187,7 @@ metadata:
|
|
173
187
|
homepage_uri: https://github.com/chaintope/glueby
|
174
188
|
source_code_uri: https://github.com/chaintope/glueby
|
175
189
|
changelog_uri: https://github.com/chaintope/glueby
|
176
|
-
post_install_message:
|
190
|
+
post_install_message:
|
177
191
|
rdoc_options: []
|
178
192
|
require_paths:
|
179
193
|
- lib
|
@@ -181,15 +195,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
181
195
|
requirements:
|
182
196
|
- - ">="
|
183
197
|
- !ruby/object:Gem::Version
|
184
|
-
version:
|
198
|
+
version: 3.0.0
|
185
199
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
186
200
|
requirements:
|
187
201
|
- - ">="
|
188
202
|
- !ruby/object:Gem::Version
|
189
203
|
version: '0'
|
190
204
|
requirements: []
|
191
|
-
rubygems_version: 3.
|
192
|
-
signing_key:
|
205
|
+
rubygems_version: 3.5.3
|
206
|
+
signing_key:
|
193
207
|
specification_version: 4
|
194
208
|
summary: A Ruby library of smart contracts that can be used on Tapyrus.
|
195
209
|
test_files: []
|