tapyrus 0.3.9 → 0.4.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.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +2 -2
  3. data/.ruby-version +1 -1
  4. data/README.md +43 -2
  5. data/lib/tapyrus/ext_key.rb +8 -4
  6. data/lib/tapyrus/key.rb +1 -1
  7. data/lib/tapyrus/key_path.rb +17 -13
  8. data/lib/tapyrus/message/fee_filter.rb +2 -2
  9. data/lib/tapyrus/message/header_and_short_ids.rb +4 -4
  10. data/lib/tapyrus/message/inventory.rb +1 -1
  11. data/lib/tapyrus/message/network_addr.rb +2 -2
  12. data/lib/tapyrus/message/ping.rb +2 -2
  13. data/lib/tapyrus/message/pong.rb +2 -2
  14. data/lib/tapyrus/message/send_cmpct.rb +2 -2
  15. data/lib/tapyrus/message/version.rb +3 -3
  16. data/lib/tapyrus/mnemonic.rb +9 -4
  17. data/lib/tapyrus/pstt/input.rb +422 -0
  18. data/lib/tapyrus/pstt/key_origin_info.rb +63 -0
  19. data/lib/tapyrus/pstt/output.rb +129 -0
  20. data/lib/tapyrus/pstt/proprietary.rb +54 -0
  21. data/lib/tapyrus/pstt/tx.rb +658 -0
  22. data/lib/tapyrus/pstt.rb +335 -0
  23. data/lib/tapyrus/rpc.rb +0 -2
  24. data/lib/tapyrus/script/script.rb +14 -4
  25. data/lib/tapyrus/secp256k1/rfc6979.rb +6 -3
  26. data/lib/tapyrus/tip0020.rb +341 -0
  27. data/lib/tapyrus/tx.rb +6 -2
  28. data/lib/tapyrus/tx_out.rb +2 -2
  29. data/lib/tapyrus/util.rb +3 -3
  30. data/lib/tapyrus/version.rb +1 -1
  31. data/lib/tapyrus/wallet/account.rb +2 -2
  32. data/lib/tapyrus/wallet/db.rb +3 -3
  33. data/lib/tapyrus/wallet/master_key.rb +2 -2
  34. data/lib/tapyrus.rb +3 -3
  35. data/tapyrusrb.gemspec +0 -3
  36. metadata +10 -61
  37. data/exe/tapyrusrb-cli +0 -5
  38. data/exe/tapyrusrbd +0 -42
  39. data/lib/tapyrus/network/connection.rb +0 -70
  40. data/lib/tapyrus/network/message_handler.rb +0 -244
  41. data/lib/tapyrus/network/peer.rb +0 -210
  42. data/lib/tapyrus/network/peer_discovery.rb +0 -43
  43. data/lib/tapyrus/network/pool.rb +0 -135
  44. data/lib/tapyrus/network.rb +0 -11
  45. data/lib/tapyrus/node/cli.rb +0 -114
  46. data/lib/tapyrus/node/configuration.rb +0 -36
  47. data/lib/tapyrus/node/spv.rb +0 -78
  48. data/lib/tapyrus/node.rb +0 -7
  49. data/lib/tapyrus/rpc/http_server.rb +0 -64
  50. data/lib/tapyrus/rpc/request_handler.rb +0 -146
@@ -0,0 +1,341 @@
1
+ require "uri"
2
+
3
+ module Tapyrus
4
+ module TIP0020
5
+ # Token metadata class based on TIP-0020 specification
6
+ # @see https://github.com/chaintope/tips/blob/main/tip-0020.md
7
+ class Metadata
8
+ CURRENT_VERSION = "1.0"
9
+ MAX_NAME_LENGTH = 64
10
+ MAX_SYMBOL_LENGTH = 12
11
+ MAX_DESCRIPTION_LENGTH = 256
12
+ MIN_DECIMALS = 0
13
+ MAX_DECIMALS = 18
14
+ MAX_DATA_URI_SIZE = 32 * 1024 # 32KB
15
+
16
+ VALID_TOKEN_TYPES = %i[reissuable non_reissuable nft].freeze
17
+ NFT_FIELDS = %i[image animation_url external_url attributes].freeze
18
+
19
+ attr_accessor :token_type,
20
+ :version,
21
+ :name,
22
+ :symbol,
23
+ :decimals,
24
+ :description,
25
+ :icon,
26
+ :issuer,
27
+ :website,
28
+ :terms,
29
+ :properties,
30
+ :image,
31
+ :animation_url,
32
+ :external_url,
33
+ :attributes
34
+
35
+ # @param token_type [Symbol] Token type (:reissuable, :non_reissuable, :nft)
36
+ # @param version [String] Schema version (default: "1.0")
37
+ # @param name [String] Human-readable token name (max 64 characters, required)
38
+ # @param symbol [String] Token symbol (max 12 characters, required)
39
+ # @param decimals [Integer] Number of decimal places for display (0-18, default: 0)
40
+ # @param description [String] Token description (max 256 characters)
41
+ # @param icon [String] HTTPS URL or Data URI for icon
42
+ # @param issuer [Hash] Issuer information object
43
+ # @param website [String] Official website URL (HTTPS required)
44
+ # @param terms [String] URL to terms of service document (HTTPS required)
45
+ # @param properties [Hash] Additional custom properties
46
+ # @param image [String] NFT image URL (HTTPS or Data URI) - only for NFT
47
+ # @param animation_url [String] NFT animation/video/audio URL (HTTPS or Data URI) - only for NFT
48
+ # @param external_url [String] External URL to view NFT (HTTPS required) - only for NFT
49
+ # @param attributes [Array<Hash>] NFT attributes array with trait_type, value, display_type - only for NFT
50
+ def initialize(
51
+ token_type:,
52
+ version: CURRENT_VERSION,
53
+ name:,
54
+ symbol:,
55
+ decimals: 0,
56
+ description: nil,
57
+ icon: nil,
58
+ issuer: nil,
59
+ website: nil,
60
+ terms: nil,
61
+ properties: nil,
62
+ image: nil,
63
+ animation_url: nil,
64
+ external_url: nil,
65
+ attributes: nil
66
+ )
67
+ @token_type = token_type
68
+ @version = version
69
+ @name = name
70
+ @symbol = symbol
71
+ @decimals = decimals
72
+ @description = description
73
+ @icon = icon
74
+ @issuer = issuer
75
+ @website = website
76
+ @terms = terms
77
+ @properties = properties
78
+ @image = image
79
+ @animation_url = animation_url
80
+ @external_url = external_url
81
+ @attributes = attributes
82
+ validate!
83
+ end
84
+
85
+ # Validate metadata fields
86
+ # @raise [ArgumentError] if validation fails
87
+ def validate!
88
+ raise ArgumentError, "token_type is required" if token_type.nil?
89
+ unless VALID_TOKEN_TYPES.include?(token_type)
90
+ raise ArgumentError, "token_type must be one of #{VALID_TOKEN_TYPES.join(", ")}"
91
+ end
92
+ validate_nft_fields!
93
+ raise ArgumentError, "version is required" if version.nil? || version.empty?
94
+ raise ArgumentError, "version must be #{CURRENT_VERSION}" unless version == CURRENT_VERSION
95
+ raise ArgumentError, "name is required" if name.nil? || name.empty?
96
+ raise ArgumentError, "name must be #{MAX_NAME_LENGTH} characters or less" if name.length > MAX_NAME_LENGTH
97
+ raise ArgumentError, "symbol is required" if symbol.nil? || symbol.empty?
98
+ if symbol.length > MAX_SYMBOL_LENGTH
99
+ raise ArgumentError, "symbol must be #{MAX_SYMBOL_LENGTH} characters or less"
100
+ end
101
+ if decimals < MIN_DECIMALS || decimals > MAX_DECIMALS
102
+ raise ArgumentError, "decimals must be between #{MIN_DECIMALS} and #{MAX_DECIMALS}"
103
+ end
104
+ if description && description.length > MAX_DESCRIPTION_LENGTH
105
+ raise ArgumentError, "description must be #{MAX_DESCRIPTION_LENGTH} characters or less"
106
+ end
107
+ raise ArgumentError, "icon must be an HTTPS URL or Data URI" if icon && !valid_icon_format?(icon)
108
+ raise ArgumentError, "website must be an HTTPS URL" if website && !valid_https_url?(website)
109
+ raise ArgumentError, "terms must be an HTTPS URL" if terms && !valid_https_url?(terms)
110
+ raise ArgumentError, "image must be an HTTPS URL or Data URI" if image && !valid_media_url?(image)
111
+ if animation_url && !valid_media_url?(animation_url)
112
+ raise ArgumentError, "animation_url must be an HTTPS URL or Data URI"
113
+ end
114
+ raise ArgumentError, "external_url must be an HTTPS URL" if external_url && !valid_https_url?(external_url)
115
+ validate_issuer! if issuer
116
+ end
117
+
118
+ # Validate issuer object fields
119
+ # @raise [ArgumentError] if validation fails
120
+ def validate_issuer!
121
+ return unless issuer.is_a?(Hash)
122
+ issuer_url = issuer[:url] || issuer["url"]
123
+ raise ArgumentError, "issuer.url must be an HTTPS URL" if issuer_url && !valid_https_url?(issuer_url)
124
+ issuer_email = issuer[:email] || issuer["email"]
125
+ raise ArgumentError, "issuer.email must be a valid email address" if issuer_email && !valid_email?(issuer_email)
126
+ end
127
+
128
+ # Validate NFT-specific fields are only used with NFT token type
129
+ # @raise [ArgumentError] if NFT fields are used with non-NFT token type
130
+ def validate_nft_fields!
131
+ return if token_type == :nft
132
+ nft_fields_present = NFT_FIELDS.select { |field| send(field) }
133
+ unless nft_fields_present.empty?
134
+ raise ArgumentError, "#{nft_fields_present.join(", ")} can only be used with NFT token type"
135
+ end
136
+ end
137
+
138
+ # Convert to Hash
139
+ # @return [Hash] metadata as hash
140
+ def to_h
141
+ result = { version: version, name: name, symbol: symbol }
142
+ result[:decimals] = decimals if decimals != 0
143
+ result[:description] = description if description
144
+ result[:icon] = icon if icon
145
+ result[:issuer] = issuer if issuer
146
+ result[:website] = website if website
147
+ result[:terms] = terms if terms
148
+ result[:properties] = properties if properties
149
+ # NFT fields
150
+ result[:image] = image if image
151
+ result[:animation_url] = animation_url if animation_url
152
+ result[:external_url] = external_url if external_url
153
+ result[:attributes] = attributes if attributes
154
+ result
155
+ end
156
+
157
+ # Canonicalize metadata according to RFC 8785 (JCS)
158
+ # @return [String] canonicalized JSON string
159
+ def canonicalize
160
+ jcs_serialize(to_h)
161
+ end
162
+
163
+ # Calculate SHA256 hash of canonicalized metadata
164
+ # @return [String] 32-byte binary hash
165
+ def digest
166
+ Tapyrus.sha256(canonicalize)
167
+ end
168
+
169
+ # Calculate SHA256 hash and return as hex string
170
+ # @return [String] 64-character hex string
171
+ def digest_hex
172
+ digest.bth
173
+ end
174
+
175
+ # Calculate P2C commitment: c = SHA256(P || h)
176
+ # @param pubkey [String] payment base public key (33 bytes compressed, hex string)
177
+ # @return [String] 32-byte binary commitment
178
+ def commitment(pubkey)
179
+ pubkey_bin = pubkey.htb
180
+ raise ArgumentError, "pubkey must be 33 bytes compressed public key" unless pubkey_bin.bytesize == 33
181
+ Tapyrus.sha256(pubkey_bin + digest)
182
+ end
183
+
184
+ # Calculate P2C commitment and return as hex string
185
+ # @param pubkey [String] payment base public key (33 bytes compressed, hex string)
186
+ # @return [String] 64-character hex string
187
+ def commitment_hex(pubkey)
188
+ commitment(pubkey).bth
189
+ end
190
+
191
+ # Derive P2C public key: P' = P + c * G
192
+ # @param pubkey [String] payment base public key (33 bytes compressed, hex string)
193
+ # @return [String] P2C public key (33 bytes compressed, hex string)
194
+ # @raise [ArgumentError] if derivation results in point at infinity
195
+ def derive_p2c_pubkey(pubkey)
196
+ c = commitment(pubkey)
197
+ c_int = c.bth.to_i(16)
198
+
199
+ # P + c * G
200
+ group = ECDSA::Group::Secp256k1
201
+ point_p = Tapyrus::Key.new(pubkey: pubkey).to_point
202
+ point_cg = group.generator * c_int
203
+ point_p_prime = point_p + point_cg
204
+
205
+ raise ArgumentError, "P2C derivation resulted in point at infinity" if point_p_prime.infinity?
206
+
207
+ # Compress the result
208
+ ECDSA::Format::PointOctetString.encode(point_p_prime, compression: true).bth
209
+ end
210
+
211
+ # Derive P2C address
212
+ # @param pubkey [String] payment base public key (33 bytes compressed, hex string)
213
+ # @return [String] P2C address
214
+ def derive_p2c_address(pubkey)
215
+ p2c_pubkey = derive_p2c_pubkey(pubkey)
216
+ Tapyrus::Key.new(pubkey: p2c_pubkey).to_p2pkh
217
+ end
218
+
219
+ # Create ColorIdentifier based on token type
220
+ # @param pubkey [String] payment base public key (33 bytes compressed, hex string) - required for :reissuable
221
+ # @param out_point [Tapyrus::OutPoint] out point - required for :non_reissuable and :nft
222
+ # @return [Tapyrus::Color::ColorIdentifier] color identifier
223
+ def derive_color_id(pubkey: nil, out_point: nil)
224
+ case token_type
225
+ when :reissuable
226
+ raise ArgumentError, "pubkey is required for reissuable token" unless pubkey
227
+ p2c_pubkey = derive_p2c_pubkey(pubkey)
228
+ script = Tapyrus::Script.to_p2pkh(Tapyrus::Key.new(pubkey: p2c_pubkey).hash160)
229
+ Tapyrus::Color::ColorIdentifier.reissuable(script)
230
+ when :non_reissuable
231
+ raise ArgumentError, "out_point is required for non_reissuable token" unless out_point
232
+ Tapyrus::Color::ColorIdentifier.non_reissuable(out_point)
233
+ when :nft
234
+ raise ArgumentError, "out_point is required for nft token" unless out_point
235
+ Tapyrus::Color::ColorIdentifier.nft(out_point)
236
+ end
237
+ end
238
+
239
+ # Parse from JSON string
240
+ # @param json_str [String] JSON string
241
+ # @param token_type [Symbol] Token type (:reissuable, :non_reissuable, :nft)
242
+ # @return [Metadata] metadata instance
243
+ def self.parse(json_str, token_type:)
244
+ data = JSON.parse(json_str, symbolize_names: true)
245
+ new(
246
+ token_type: token_type,
247
+ version: data[:version] || CURRENT_VERSION,
248
+ name: data[:name],
249
+ symbol: data[:symbol],
250
+ decimals: data[:decimals] || 0,
251
+ description: data[:description],
252
+ icon: data[:icon],
253
+ issuer: data[:issuer],
254
+ website: data[:website],
255
+ terms: data[:terms],
256
+ properties: data[:properties],
257
+ image: data[:image],
258
+ animation_url: data[:animation_url],
259
+ external_url: data[:external_url],
260
+ attributes: data[:attributes]
261
+ )
262
+ end
263
+
264
+ private
265
+
266
+ # Check if the URL is a valid HTTPS URL
267
+ def valid_https_url?(url)
268
+ uri = URI.parse(url)
269
+ uri.is_a?(URI::HTTPS)
270
+ rescue URI::InvalidURIError
271
+ false
272
+ end
273
+
274
+ # Check if the icon format is valid (HTTPS URL or Data URI)
275
+ def valid_icon_format?(icon)
276
+ valid_media_url?(icon)
277
+ end
278
+
279
+ # Check if media URL is valid (HTTPS URL or Data URI with size limit)
280
+ def valid_media_url?(url)
281
+ return url.bytesize <= MAX_DATA_URI_SIZE if url.start_with?("data:")
282
+ valid_https_url?(url)
283
+ end
284
+
285
+ # Check if email format is valid
286
+ def valid_email?(email)
287
+ # Basic email format validation
288
+ email.match?(/\A[^@\s]+@[^@\s]+\.[^@\s]+\z/)
289
+ end
290
+
291
+ # RFC 8785 JSON Canonicalization Scheme serialization
292
+ # @param obj [Object] object to serialize
293
+ # @return [String] canonicalized JSON string
294
+ def jcs_serialize(obj)
295
+ case obj
296
+ when Hash
297
+ pairs =
298
+ obj
299
+ .keys
300
+ .map(&:to_s)
301
+ .sort
302
+ .map { |key| "#{jcs_serialize(key)}:#{jcs_serialize(obj[key.to_sym] || obj[key])}" }
303
+ "{#{pairs.join(",")}}"
304
+ when Array
305
+ "[#{obj.map { |v| jcs_serialize(v) }.join(",")}]"
306
+ when String
307
+ JSON.generate(obj)
308
+ when Integer
309
+ obj.to_s
310
+ when Float
311
+ # RFC 8785 requires specific float formatting
312
+ jcs_format_float(obj)
313
+ when TrueClass, FalseClass
314
+ obj.to_s
315
+ when NilClass
316
+ "null"
317
+ else
318
+ JSON.generate(obj)
319
+ end
320
+ end
321
+
322
+ # Format float according to RFC 8785
323
+ def jcs_format_float(num)
324
+ return "0" if num.zero?
325
+ return "null" if num.nan? || num.infinite?
326
+
327
+ # Use exponential notation for very large or very small numbers
328
+ if num.abs >= 1e21 || (num != 0 && num.abs < 1e-6)
329
+ # Exponential format
330
+ exp = Math.log10(num.abs).floor
331
+ mantissa = num / (10**exp)
332
+ "#{mantissa}e#{exp >= 0 ? "+" : ""}#{exp}"
333
+ else
334
+ # Remove trailing zeros
335
+ str = num.to_s
336
+ str.sub(/\.?0+$/, "")
337
+ end
338
+ end
339
+ end
340
+ end
341
+ end
data/lib/tapyrus/tx.rb CHANGED
@@ -47,6 +47,10 @@ module Tapyrus
47
47
  to_hex.to_i(16)
48
48
  end
49
49
 
50
+ def eql?(other)
51
+ other.is_a?(Tx) && self == other
52
+ end
53
+
50
54
  def tx_hash
51
55
  Tapyrus.double_sha256(to_payload).bth
52
56
  end
@@ -118,9 +122,9 @@ module Tapyrus
118
122
  # verify input signature.
119
123
  # @param [Integer] input_index
120
124
  # @param [Tapyrus::Script] script_pubkey the script pubkey for target input.
121
- # @param [Array] flags the flags used when execute script interpreter.
125
+ # @param [Integer] flags the flags used when execute script interpreter.
122
126
  def verify_input_sig(input_index, script_pubkey, flags: STANDARD_SCRIPT_VERIFY_FLAGS)
123
- flags << SCRIPT_VERIFY_P2SH if script_pubkey.p2sh?
127
+ flags |= SCRIPT_VERIFY_P2SH if script_pubkey.p2sh?
124
128
  verify_input_sig_for_legacy(input_index, script_pubkey, flags)
125
129
  end
126
130
 
@@ -17,14 +17,14 @@ module Tapyrus
17
17
 
18
18
  def self.parse_from_payload(payload)
19
19
  buf = payload.is_a?(String) ? StringIO.new(payload) : payload
20
- value = buf.read(8).unpack("q").first
20
+ value = buf.read(8).unpack("Q<").first
21
21
  script_size = Tapyrus.unpack_var_int_from_io(buf)
22
22
  new(value: value, script_pubkey: Script.parse_from_payload(buf.read(script_size)))
23
23
  end
24
24
 
25
25
  def to_payload
26
26
  s = script_pubkey.to_payload
27
- [value].pack("Q") << Tapyrus.pack_var_int(s.length) << s
27
+ [value].pack("Q<") << Tapyrus.pack_var_int(s.length) << s
28
28
  end
29
29
 
30
30
  def to_empty_payload
data/lib/tapyrus/util.rb CHANGED
@@ -23,7 +23,7 @@ module Tapyrus
23
23
  elsif i <= 0xffffffff
24
24
  [0xfe, i].pack("CV")
25
25
  elsif i <= 0xffffffffffffffff
26
- [0xff, i].pack("CQ")
26
+ [0xff, i].pack("CQ<")
27
27
  else
28
28
  raise "int(#{i}) too large!"
29
29
  end
@@ -37,7 +37,7 @@ module Tapyrus
37
37
  when 0xfe
38
38
  payload.unpack("xVa*")
39
39
  when 0xff
40
- payload.unpack("xQa*")
40
+ payload.unpack("xQ<a*")
41
41
  else
42
42
  payload.unpack("Ca*")
43
43
  end
@@ -52,7 +52,7 @@ module Tapyrus
52
52
  when 0xfe
53
53
  buf.read(4)&.unpack("V")&.first
54
54
  when 0xff
55
- buf.read(8)&.unpack("Q")&.first
55
+ buf.read(8)&.unpack("Q<")&.first
56
56
  else
57
57
  uchar
58
58
  end
@@ -1,3 +1,3 @@
1
1
  module Tapyrus
2
- VERSION = "0.3.9"
2
+ VERSION = "0.4.0"
3
3
  end
@@ -32,7 +32,7 @@ module Tapyrus
32
32
  payload = buf.read
33
33
  name, payload = Tapyrus.unpack_var_string(payload)
34
34
  name = name.force_encoding("utf-8")
35
- purpose, index, receive_depth, change_depth, lookahead = payload.unpack("I*")
35
+ purpose, index, receive_depth, change_depth, lookahead = payload.unpack("V*")
36
36
  a = Account.new(account_key, purpose, index, name)
37
37
  a.receive_depth = receive_depth
38
38
  a.change_depth = change_depth
@@ -43,7 +43,7 @@ module Tapyrus
43
43
  def to_payload
44
44
  payload = account_key.to_payload
45
45
  payload << Tapyrus.pack_var_string(name.unpack("H*").first.htb)
46
- payload << [purpose, index, receive_depth, change_depth, lookahead].pack("I*")
46
+ payload << [purpose, index, receive_depth, change_depth, lookahead].pack("V*")
47
47
  payload
48
48
  end
49
49
 
@@ -30,7 +30,7 @@ module Tapyrus
30
30
 
31
31
  def save_account(account)
32
32
  level_db.batch do
33
- id = [account.purpose, account.index].pack("I*").bth
33
+ id = [account.purpose, account.index].pack("V*").bth
34
34
  key = KEY_PREFIX[:account] + id
35
35
  level_db.put(key, account.to_payload)
36
36
  end
@@ -38,14 +38,14 @@ module Tapyrus
38
38
 
39
39
  def save_key(account, purpose, index, key)
40
40
  pubkey = key.pub
41
- id = [account.purpose, account.index, purpose, index].pack("I*").bth
41
+ id = [account.purpose, account.index, purpose, index].pack("V*").bth
42
42
  k = KEY_PREFIX[:key] + id
43
43
  level_db.put(k, pubkey)
44
44
  key
45
45
  end
46
46
 
47
47
  def get_keys(account)
48
- id = [account.purpose, account.index].pack("I*").bth
48
+ id = [account.purpose, account.index].pack("V*").bth
49
49
  from = KEY_PREFIX[:key] + id + "00000000"
50
50
  to = KEY_PREFIX[:key] + id + "ffffffff"
51
51
  level_db.each(from: from, to: to).map { |k, v| v }
@@ -80,7 +80,7 @@ module Tapyrus
80
80
  encrypted_data = ""
81
81
  encrypted_data << enc.update(seed)
82
82
  encrypted_data << enc.final
83
- @seed = encrypted_data
83
+ @seed = encrypted_data.bth
84
84
  @encrypted = true
85
85
  end
86
86
 
@@ -91,7 +91,7 @@ module Tapyrus
91
91
  dec.decrypt
92
92
  dec.key, dec.iv = key_iv(dec, passphrase)
93
93
  decrypted_data = ""
94
- decrypted_data << dec.update(seed)
94
+ decrypted_data << dec.update(seed.htb)
95
95
  decrypted_data << dec.final
96
96
  @seed = decrypted_data
97
97
  @encrypted = false
data/lib/tapyrus.rb CHANGED
@@ -2,9 +2,9 @@
2
2
  # https://github.com/lian/bitcoin-ruby/blob/master/COPYING
3
3
 
4
4
  require "tapyrus/version"
5
- require "eventmachine"
6
5
  require "ecdsa"
7
6
  require "securerandom"
7
+ require "stringio"
8
8
  require "json"
9
9
  require "jwt"
10
10
  require "ffi"
@@ -36,12 +36,10 @@ module Tapyrus
36
36
  autoload :ExtKey, "tapyrus/ext_key"
37
37
  autoload :ExtPubkey, "tapyrus/ext_key"
38
38
  autoload :Opcodes, "tapyrus/opcodes"
39
- autoload :Node, "tapyrus/node"
40
39
  autoload :Base58, "tapyrus/base58"
41
40
  autoload :Secp256k1, "tapyrus/secp256k1"
42
41
  autoload :Mnemonic, "tapyrus/mnemonic"
43
42
  autoload :ValidationState, "tapyrus/validation"
44
- autoload :Network, "tapyrus/network"
45
43
  autoload :Store, "tapyrus/store"
46
44
  autoload :RPC, "tapyrus/rpc"
47
45
  autoload :Wallet, "tapyrus/wallet"
@@ -54,6 +52,8 @@ module Tapyrus
54
52
  autoload :BIP175, "tapyrus/bip175"
55
53
  autoload :Contract, "tapyrus/contract"
56
54
  autoload :TIP0137, "tapyrus/tip0137"
55
+ autoload :TIP0020, "tapyrus/tip0020"
56
+ autoload :PSTT, "tapyrus/pstt"
57
57
  autoload :JWS, "tapyrus/jws"
58
58
 
59
59
  require_relative "tapyrus/constants"
data/tapyrusrb.gemspec CHANGED
@@ -21,13 +21,10 @@ Gem::Specification.new do |spec|
21
21
  spec.require_paths = ["lib"]
22
22
 
23
23
  spec.add_runtime_dependency "ecdsa"
24
- spec.add_runtime_dependency "eventmachine"
25
24
  spec.add_runtime_dependency "murmurhash3"
26
25
  spec.add_runtime_dependency "daemon-spawn"
27
- spec.add_runtime_dependency "thor"
28
26
  spec.add_runtime_dependency "ffi"
29
27
  spec.add_runtime_dependency "leb128", "~> 1.0.0"
30
- spec.add_runtime_dependency "eventmachine_httpserver"
31
28
  spec.add_runtime_dependency "iniparse"
32
29
  spec.add_runtime_dependency "siphash"
33
30
  spec.add_runtime_dependency "activesupport", ">= 5.2.3"
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tapyrus
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.9
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - azuchi
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2025-03-17 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: ecdsa
@@ -23,20 +23,6 @@ dependencies:
23
23
  - - ">="
24
24
  - !ruby/object:Gem::Version
25
25
  version: '0'
26
- - !ruby/object:Gem::Dependency
27
- name: eventmachine
28
- requirement: !ruby/object:Gem::Requirement
29
- requirements:
30
- - - ">="
31
- - !ruby/object:Gem::Version
32
- version: '0'
33
- type: :runtime
34
- prerelease: false
35
- version_requirements: !ruby/object:Gem::Requirement
36
- requirements:
37
- - - ">="
38
- - !ruby/object:Gem::Version
39
- version: '0'
40
26
  - !ruby/object:Gem::Dependency
41
27
  name: murmurhash3
42
28
  requirement: !ruby/object:Gem::Requirement
@@ -65,20 +51,6 @@ dependencies:
65
51
  - - ">="
66
52
  - !ruby/object:Gem::Version
67
53
  version: '0'
68
- - !ruby/object:Gem::Dependency
69
- name: thor
70
- requirement: !ruby/object:Gem::Requirement
71
- requirements:
72
- - - ">="
73
- - !ruby/object:Gem::Version
74
- version: '0'
75
- type: :runtime
76
- prerelease: false
77
- version_requirements: !ruby/object:Gem::Requirement
78
- requirements:
79
- - - ">="
80
- - !ruby/object:Gem::Version
81
- version: '0'
82
54
  - !ruby/object:Gem::Dependency
83
55
  name: ffi
84
56
  requirement: !ruby/object:Gem::Requirement
@@ -107,20 +79,6 @@ dependencies:
107
79
  - - "~>"
108
80
  - !ruby/object:Gem::Version
109
81
  version: 1.0.0
110
- - !ruby/object:Gem::Dependency
111
- name: eventmachine_httpserver
112
- requirement: !ruby/object:Gem::Requirement
113
- requirements:
114
- - - ">="
115
- - !ruby/object:Gem::Version
116
- version: '0'
117
- type: :runtime
118
- prerelease: false
119
- version_requirements: !ruby/object:Gem::Requirement
120
- requirements:
121
- - - ">="
122
- - !ruby/object:Gem::Version
123
- version: '0'
124
82
  - !ruby/object:Gem::Dependency
125
83
  name: iniparse
126
84
  requirement: !ruby/object:Gem::Requirement
@@ -308,8 +266,6 @@ email:
308
266
  - azuchi@chaintope.com
309
267
  executables:
310
268
  - tapyrus-script-debugger
311
- - tapyrusrb-cli
312
- - tapyrusrbd
313
269
  extensions: []
314
270
  extra_rdoc_files: []
315
271
  files:
@@ -328,8 +284,6 @@ files:
328
284
  - bin/console
329
285
  - bin/setup
330
286
  - exe/tapyrus-script-debugger
331
- - exe/tapyrusrb-cli
332
- - exe/tapyrusrbd
333
287
  - lib/openassets.rb
334
288
  - lib/openassets/marker_output.rb
335
289
  - lib/openassets/payload.rb
@@ -401,21 +355,15 @@ files:
401
355
  - lib/tapyrus/mnemonic/wordlist/italian.txt
402
356
  - lib/tapyrus/mnemonic/wordlist/japanese.txt
403
357
  - lib/tapyrus/mnemonic/wordlist/spanish.txt
404
- - lib/tapyrus/network.rb
405
- - lib/tapyrus/network/connection.rb
406
- - lib/tapyrus/network/message_handler.rb
407
- - lib/tapyrus/network/peer.rb
408
- - lib/tapyrus/network/peer_discovery.rb
409
- - lib/tapyrus/network/pool.rb
410
- - lib/tapyrus/node.rb
411
- - lib/tapyrus/node/cli.rb
412
- - lib/tapyrus/node/configuration.rb
413
- - lib/tapyrus/node/spv.rb
414
358
  - lib/tapyrus/opcodes.rb
415
359
  - lib/tapyrus/out_point.rb
360
+ - lib/tapyrus/pstt.rb
361
+ - lib/tapyrus/pstt/input.rb
362
+ - lib/tapyrus/pstt/key_origin_info.rb
363
+ - lib/tapyrus/pstt/output.rb
364
+ - lib/tapyrus/pstt/proprietary.rb
365
+ - lib/tapyrus/pstt/tx.rb
416
366
  - lib/tapyrus/rpc.rb
417
- - lib/tapyrus/rpc/http_server.rb
418
- - lib/tapyrus/rpc/request_handler.rb
419
367
  - lib/tapyrus/rpc/tapyrus_core_client.rb
420
368
  - lib/tapyrus/script/color.rb
421
369
  - lib/tapyrus/script/debugger.rb
@@ -437,6 +385,7 @@ files:
437
385
  - lib/tapyrus/store/db.rb
438
386
  - lib/tapyrus/store/db/level_db.rb
439
387
  - lib/tapyrus/store/spv_chain.rb
388
+ - lib/tapyrus/tip0020.rb
440
389
  - lib/tapyrus/tip0137.rb
441
390
  - lib/tapyrus/tx.rb
442
391
  - lib/tapyrus/tx_builder.rb
@@ -470,7 +419,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
470
419
  - !ruby/object:Gem::Version
471
420
  version: '0'
472
421
  requirements: []
473
- rubygems_version: 3.6.3
422
+ rubygems_version: 4.0.3
474
423
  specification_version: 4
475
424
  summary: The implementation of Tapyrus Protocol for Ruby.
476
425
  test_files: []
data/exe/tapyrusrb-cli DELETED
@@ -1,5 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require "tapyrus"
4
-
5
- Tapyrus::Node::CLI.start(ARGV)