stellar-base 0.23.0.rc2 → 0.25.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (80) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +111 -1
  3. data/README.md +4 -7
  4. data/generated/stellar-base-generated.rb +29 -1
  5. data/generated/stellar/account_entry.rb +3 -13
  6. data/generated/stellar/account_entry/ext.rb +2 -16
  7. data/generated/stellar/account_entry_extension_v1.rb +32 -0
  8. data/generated/stellar/account_entry_extension_v1/ext.rb +28 -0
  9. data/generated/stellar/account_entry_extension_v2.rb +34 -0
  10. data/generated/stellar/{account_entry/ext/v1 → account_entry_extension_v2}/ext.rb +8 -12
  11. data/generated/stellar/account_merge_result_code.rb +3 -1
  12. data/generated/stellar/begin_sponsoring_future_reserves_op.rb +18 -0
  13. data/generated/stellar/begin_sponsoring_future_reserves_result.rb +25 -0
  14. data/generated/stellar/begin_sponsoring_future_reserves_result_code.rb +29 -0
  15. data/generated/stellar/claim_claimable_balance_op.rb +18 -0
  16. data/generated/stellar/claim_claimable_balance_result.rb +25 -0
  17. data/generated/stellar/claim_claimable_balance_result_code.rb +31 -0
  18. data/generated/stellar/claim_predicate.rb +43 -0
  19. data/generated/stellar/claim_predicate_type.rb +30 -0
  20. data/generated/stellar/claimable_balance_entry.rb +44 -0
  21. data/generated/stellar/claimable_balance_entry/ext.rb +24 -0
  22. data/generated/stellar/claimable_balance_id.rb +23 -0
  23. data/generated/stellar/claimable_balance_id_type.rb +20 -0
  24. data/generated/stellar/claimant.rb +31 -0
  25. data/generated/stellar/claimant/v0.rb +22 -0
  26. data/generated/stellar/claimant_type.rb +20 -0
  27. data/generated/stellar/create_claimable_balance_op.rb +22 -0
  28. data/generated/stellar/create_claimable_balance_result.rb +27 -0
  29. data/generated/stellar/create_claimable_balance_result_code.rb +30 -0
  30. data/generated/stellar/end_sponsoring_future_reserves_result.rb +25 -0
  31. data/generated/stellar/end_sponsoring_future_reserves_result_code.rb +25 -0
  32. data/generated/stellar/envelope_type.rb +3 -1
  33. data/generated/stellar/inner_transaction_result.rb +2 -1
  34. data/generated/stellar/inner_transaction_result/result.rb +3 -1
  35. data/generated/stellar/ledger_entry.rb +4 -0
  36. data/generated/stellar/ledger_entry/data.rb +12 -8
  37. data/generated/stellar/ledger_entry/ext.rb +4 -0
  38. data/generated/stellar/ledger_entry_extension_v1.rb +30 -0
  39. data/generated/stellar/ledger_entry_extension_v1/ext.rb +24 -0
  40. data/generated/stellar/ledger_entry_type.rb +7 -5
  41. data/generated/stellar/ledger_key.rb +17 -8
  42. data/generated/stellar/ledger_key/claimable_balance.rb +20 -0
  43. data/generated/stellar/operation.rb +10 -0
  44. data/generated/stellar/operation/body.rb +45 -26
  45. data/generated/stellar/operation_id.rb +32 -0
  46. data/generated/stellar/operation_id/id.rb +24 -0
  47. data/generated/stellar/operation_result.rb +10 -0
  48. data/generated/stellar/operation_result/tr.rb +48 -28
  49. data/generated/stellar/operation_result_code.rb +3 -1
  50. data/generated/stellar/operation_type.rb +25 -15
  51. data/generated/stellar/path_payment_strict_receive_result.rb +2 -1
  52. data/generated/stellar/revoke_sponsorship_op.rb +36 -0
  53. data/generated/stellar/revoke_sponsorship_op/signer.rb +22 -0
  54. data/generated/stellar/revoke_sponsorship_result.rb +25 -0
  55. data/generated/stellar/revoke_sponsorship_result_code.rb +31 -0
  56. data/generated/stellar/revoke_sponsorship_type.rb +22 -0
  57. data/generated/stellar/transaction_result_code.rb +4 -2
  58. data/lib/stellar-base.rb +18 -5
  59. data/lib/stellar/account_flags.rb +1 -1
  60. data/lib/stellar/asset.rb +10 -0
  61. data/lib/stellar/{version.rb → base/version.rb} +1 -1
  62. data/lib/stellar/claim_predicate.rb +198 -0
  63. data/lib/stellar/compat.rb +2 -15
  64. data/lib/stellar/concerns/transaction.rb +2 -3
  65. data/lib/stellar/dsl.rb +89 -0
  66. data/lib/stellar/ext/xdr.rb +50 -0
  67. data/lib/stellar/key_pair.rb +60 -53
  68. data/lib/stellar/ledger_key.rb +32 -0
  69. data/lib/stellar/muxed_account.rb +16 -0
  70. data/lib/stellar/networks.rb +12 -12
  71. data/lib/stellar/operation.rb +59 -1
  72. data/lib/stellar/price.rb +11 -2
  73. data/lib/stellar/transaction.rb +17 -167
  74. data/lib/stellar/transaction_builder.rb +35 -18
  75. data/lib/stellar/transaction_envelope.rb +7 -43
  76. data/lib/stellar/transaction_v0.rb +5 -1
  77. data/lib/stellar/util/strkey.rb +6 -6
  78. metadata +164 -32
  79. data/generated/stellar/account_entry/ext/v1.rb +0 -34
  80. data/lib/stellar/util/continued_fraction.rb +0 -96
@@ -4,7 +4,7 @@ module Stellar
4
4
  # Converts an array of Stellar::AccountFlags members into
5
5
  # an Integer suitable for use in a SetOptionsOp.
6
6
  #
7
- # @param flags=nil [Array<Stellar::AccountFlags>] the flags to combine
7
+ # @param flags [Array<Stellar::AccountFlags>] the flags to combine
8
8
  #
9
9
  # @return [Fixnum] the combined result
10
10
  def self.make_mask(flags = nil)
@@ -6,14 +6,24 @@ module Stellar
6
6
  new(:asset_type_native)
7
7
  end
8
8
 
9
+ # @param code [String] asset code
10
+ # @param issuer [#to_keypair] asset issuer
11
+ #
12
+ # @return [Stellar::Asset::AlphaNum4] asset4 representation
9
13
  def self.alphanum4(code, issuer)
14
+ issuer = issuer.to_keypair if issuer.respond_to?(:to_keypair)
10
15
  raise ArgumentError, "Bad :issuer" unless issuer.is_a?(KeyPair)
11
16
  code = normalize_code(code, 4)
12
17
  an = AlphaNum4.new({asset_code: code, issuer: issuer.account_id})
13
18
  new(:asset_type_credit_alphanum4, an)
14
19
  end
15
20
 
21
+ # @param code [String] asset code
22
+ # @param issuer [#to_keypair] asset issuer
23
+ #
24
+ # @return [Stellar::Asset::AlphaNum4] asset4 representation
16
25
  def self.alphanum12(code, issuer)
26
+ issuer = issuer.to_keypair if issuer.respond_to?(:to_keypair)
17
27
  raise ArgumentError, "Bad :issuer" unless issuer.is_a?(KeyPair)
18
28
  code = normalize_code(code, 12)
19
29
  an = AlphaNum12.new({asset_code: code, issuer: issuer.account_id})
@@ -1,5 +1,5 @@
1
1
  module Stellar
2
2
  module Base
3
- VERSION = "0.23.0.rc2"
3
+ VERSION = "0.25.0"
4
4
  end
5
5
  end
@@ -0,0 +1,198 @@
1
+ # frozen_string_literals: true
2
+ require "active_support/core_ext/integer/time"
3
+ require "active_support/core_ext/string/conversions"
4
+
5
+ module Stellar
6
+ # Represents claim predicate on Stellar network.
7
+ #
8
+ # @see https://developers.stellar.org/docs/glossary/claimable-balance/
9
+ class ClaimPredicate
10
+ module FactoryMethods
11
+ # Constructs an `unconditional` claim predicate.
12
+ #
13
+ # This predicate will be always fulfilled.
14
+ #
15
+ # @return [ClaimPredicate] `unconditional` claim predicate
16
+ def unconditional
17
+ ClaimPredicate.new(ClaimPredicateType::UNCONDITIONAL)
18
+ end
19
+
20
+ # Constructs a `before_relative_time` claim predicate.
21
+ #
22
+ # This predicate will be fulfilled if the closing time of the ledger that includes
23
+ # the Stellar::CreateClaimableBalance operation plus this relative time delta (in seconds)
24
+ # is less than the current time.
25
+ #
26
+ # @param seconds [#to_int|#to_i] seconds since `closeTime` of the ledger in which
27
+ # the ClaimableBalanceEntry was created.
28
+ # @return [ClaimPredicate] `before_relative_time` claim predicate
29
+ def before_relative_time(seconds)
30
+ ClaimPredicate.new(ClaimPredicateType::BEFORE_RELATIVE_TIME, Integer(seconds))
31
+ end
32
+
33
+ # Constructs an `before_absolute_time` claim predicate.
34
+ #
35
+ # This predicate will be fulfilled if the closing time of the ledger that includes
36
+ # the Stellar::CreateClaimableBalance operation is less than provided timestamp.
37
+ #
38
+ # @param timestamp [#to_time|#to_int|#to_i] time value or timestamp
39
+ #
40
+ # @return [ClaimPredicate] `before_absolute_time` claim predicate.
41
+ def before_absolute_time(timestamp)
42
+ timestamp = timestamp.to_time if timestamp.respond_to?(:to_time)
43
+
44
+ ClaimPredicate.new(ClaimPredicateType::BEFORE_ABSOLUTE_TIME, Integer(timestamp))
45
+ end
46
+
47
+ # Constructs either relative or absolute time predicate based on the type of the input.
48
+ #
49
+ # If input is an instance of `ActiveSupport::Duration` class it will be handled as a relative time
50
+ # (seconds since close time of the ledger), otherwise it will be treated as an absolute time.
51
+ #
52
+ # It is intended to work with time helpers provided by ActiveSupport, like `1.day` (relative)
53
+ # or `2.weeks.from_now` (absolute).
54
+ #
55
+ # @example relative time
56
+ # ClaimPredicate.before(2.days + 15.seconds)
57
+ #
58
+ # @example absolute time
59
+ # ClaimPredicate.before(5.hours.from_now)
60
+ #
61
+ # @param time [ActiveSupport::Duration|#to_time|#to_i] duration since ledger close time or absolute time value
62
+ #
63
+ # @return [ClaimPredicate] `before_relative_time` or `before_absolute_time` claim predicate.
64
+ def before(time)
65
+ ActiveSupport::Duration === time ? before_relative_time(time.to_i) : before_absolute_time(time)
66
+ end
67
+
68
+ # Constructs a negated predicate from either relative or absolute time based on the type of the input.
69
+ #
70
+ # @see #before
71
+ # @param (see #before)
72
+ # @return (see #before)
73
+ def after(time)
74
+ ~before(time)
75
+ end
76
+
77
+ # Compose a complex predicate by calling DSL methods from the block.
78
+ #
79
+ # @example
80
+ # ClaimPredicate.compose {
81
+ # after(15.minutes) & before(1.day) | after(1.week.from_now) & before(1.week.from_now + 1.day)
82
+ # }
83
+ #
84
+ # @yieldreturn [ClaimPredicate|nil]
85
+ # @return [ClaimPredicate] `not(before_relative_time)` or `not(before_absolute_time)` claim predicate.
86
+ def compose(&block)
87
+ result = instance_eval(&block)
88
+ result.nil? ? unconditional : result
89
+ end
90
+ end
91
+
92
+ extend FactoryMethods
93
+
94
+ # Constructs an `and` claim predicate.
95
+ #
96
+ # This predicate will be fulfilled if both `self` and `other` predicates are fulfilled.
97
+ #
98
+ # @param other [ClaimPredicate] another predicate
99
+ #
100
+ # @return [ClaimPredicate] `and` claim predicate
101
+ def and(other)
102
+ raise TypeError, "no conversion from #{other.class.name} to ClaimPredicate" unless ClaimPredicate === other
103
+ ClaimPredicate.new(ClaimPredicateType::AND, [self, other])
104
+ end
105
+ alias_method :&, :and
106
+
107
+ # Constructs an `or` claim predicate.
108
+ #
109
+ # This predicate will be fulfilled if either of `self` or `other` predicates is fulfilled.
110
+ #
111
+ # @param other [ClaimPredicate] another predicate.
112
+ #
113
+ # @return [ClaimPredicate] `or` claim predicate
114
+ def or(other)
115
+ raise TypeError, "no conversion from #{other.class.name} to ClaimPredicate" unless ClaimPredicate === other
116
+ ClaimPredicate.new(ClaimPredicateType::OR, [self, other])
117
+ end
118
+ alias_method :|, :or
119
+
120
+ # Constructs a `not` claim predicate.
121
+ #
122
+ # This predicate will be fulfilled if `self` is not fulfilled.
123
+ #
124
+ # @return [ClaimPredicate] `not` claim predicate
125
+ def not
126
+ ClaimPredicate.new(ClaimPredicateType::NOT, self)
127
+ end
128
+ alias_method :~@, :not
129
+
130
+ # Evaluates the predicate value for provided inputs.
131
+ #
132
+ # @param created_at [#to_time|#to_int] closing time of the ledger containing CreateClaimableBalance operation
133
+ # @param claiming_at [#to_time|#to_int|ActiveSupport::Duration] time point to evaluate predicate at, either
134
+ # absolute time or duration relative to `created_at`. In reality predicate will be evaluated by stellar-core
135
+ # using the closing time of a ledger containing ClaimClaimableBalance operation, in either successful
136
+ # or failed state.
137
+ #
138
+ # @return [Boolean] `true` if this predicate would allow claiming the balance, `false` otherwise
139
+ def evaluate(created_at, claiming_at)
140
+ created_at = created_at.to_time if created_at.respond_to?(:to_time)
141
+ claiming_at = created_at + claiming_at if claiming_at.is_a?(ActiveSupport::Duration)
142
+ claiming_at = claiming_at.to_time if claiming_at.respond_to?(:to_time)
143
+
144
+ return false if claiming_at < created_at
145
+
146
+ case switch
147
+ when ClaimPredicateType::UNCONDITIONAL
148
+ true
149
+ when ClaimPredicateType::BEFORE_RELATIVE_TIME
150
+ Integer(claiming_at) < Integer(created_at) + value
151
+ when ClaimPredicateType::BEFORE_ABSOLUTE_TIME
152
+ Integer(claiming_at).to_i < value
153
+ when ClaimPredicateType::AND
154
+ value[0].evaluate(created_at, claiming_at) && value[1].evaluate(created_at, claiming_at)
155
+ when ClaimPredicateType::OR
156
+ value[0].evaluate(created_at, claiming_at) || value[1].evaluate(created_at, claiming_at)
157
+ when ClaimPredicateType::NOT
158
+ !value.evaluate(created_at, claiming_at)
159
+ else
160
+ raise ArgumentError, "evaluation is not implemented for #{switch.name} predicate"
161
+ end
162
+ end
163
+
164
+ def describe
165
+ case switch
166
+ when ClaimPredicateType::UNCONDITIONAL
167
+ "always"
168
+ when ClaimPredicateType::BEFORE_RELATIVE_TIME
169
+ dur = ActiveSupport::Duration.build(value)
170
+ "less than #{dur.inspect} since creation"
171
+ when ClaimPredicateType::BEFORE_ABSOLUTE_TIME
172
+ "before #{Time.at(value).to_formatted_s(:db)}"
173
+ when ClaimPredicateType::AND
174
+ value.map(&:describe).join(" and ")
175
+ when ClaimPredicateType::OR
176
+ "(" << value.map(&:describe).join(" or ") << ")"
177
+ when ClaimPredicateType::NOT
178
+ case value.switch
179
+ when ClaimPredicateType::UNCONDITIONAL
180
+ "never"
181
+ when ClaimPredicateType::BEFORE_RELATIVE_TIME
182
+ dur = ActiveSupport::Duration.build(value.value)
183
+ "#{dur.inspect} or more since creation"
184
+ when ClaimPredicateType::BEFORE_ABSOLUTE_TIME
185
+ "after #{Time.at(value.value).to_formatted_s(:db)}"
186
+ else
187
+ "not (#{value.describe})"
188
+ end
189
+ else
190
+ raise ArgumentError, "evaluation is not implemented for #{switch.name} predicate"
191
+ end
192
+ end
193
+
194
+ def inspect
195
+ "#<ClaimPredicate: #{describe}>"
196
+ end
197
+ end
198
+ end
@@ -1,19 +1,6 @@
1
- require "active_support/deprecation"
2
-
3
- Stellar::Deprecation ||= ActiveSupport::Deprecation.new("next release", "stellar-base")
4
-
5
1
  class << Stellar::Operation
6
- alias manage_offer manage_sell_offer
7
- alias create_passive_offer create_passive_sell_offer
8
-
9
- deprecate deprecator: Stellar::Deprecation,
10
- manage_offer: :manage_sell_offer,
11
- create_passive_offer: :create_passive_sell_offer
12
- end
13
-
14
- class << Stellar::Transaction
15
- alias manage_offer manage_sell_offer
16
- alias create_passive_offer create_passive_sell_offer
2
+ alias_method :manage_offer, :manage_sell_offer
3
+ alias_method :create_passive_offer, :create_passive_sell_offer
17
4
 
18
5
  deprecate deprecator: Stellar::Deprecation,
19
6
  manage_offer: :manage_sell_offer,
@@ -32,9 +32,8 @@ module Stellar::Concerns
32
32
  #
33
33
  # @return [Array<Operation>] the operations
34
34
  def to_operations
35
- # FIXME: what was the purpose of this?
36
- # cloned = Marshal.load Marshal.dump(operations)
37
- operations.each do |op|
35
+ cloned = Marshal.load Marshal.dump(operations)
36
+ cloned.each do |op|
38
37
  op.source_account ||= source_account
39
38
  end
40
39
  end
@@ -0,0 +1,89 @@
1
+ module Stellar
2
+ module DSL
3
+ module_function
4
+
5
+ # Constructs a new ClaimPredicate using DSL
6
+ #
7
+ # @example fulfilled during [T+5min, T+60min] period, where T refers to claimable balance entry creation time
8
+ # Stellar::ClaimPredicate { before_relative_time(1.hour) & ~before_relative_time(5.minutes) }
9
+ #
10
+ # @example not fulfilled starting from today midnight until tomorrow midnight,
11
+ # Stellar::ClaimPredicate { before_absolute_time(Date.today.end_of_day) | ~before_absolute_time(Date.tomorrow.end_of_day) }
12
+ #
13
+ # @example always fulfilled
14
+ # Stellar::ClaimPredicate { }
15
+ def ClaimPredicate(&block)
16
+ return ClaimPredicate.unconditional unless block
17
+ ClaimPredicate.compose(&block)
18
+ end
19
+
20
+ def Claimant(destination, &block)
21
+ Claimant.new(
22
+ ClaimantType.claimant_type_v0,
23
+ Claimant::V0.new(
24
+ destination: KeyPair(destination).account_id,
25
+ predicate: ClaimPredicate(&block)
26
+ )
27
+ )
28
+ end
29
+
30
+ def Asset(subject = nil)
31
+ case subject
32
+ when Asset
33
+ subject
34
+ when nil, /^(XLM[-:])?native$/
35
+ Asset.native
36
+ when /^([0-9A-Z]{1,4})[-:](G[A-Z0-9]{55})$/
37
+ Asset.alphanum4($1, KeyPair($2))
38
+ when /^([0-9A-Z]{5,12})[-:](G[A-Z0-9]{55})$/
39
+ Asset.alphanum12($1, KeyPair($2))
40
+ else
41
+ raise TypeError, "Cannot convert #{subject.inspect} to Stellar::Asset"
42
+ end
43
+ end
44
+
45
+ # Generates Stellar::Keypair from subject, use Stellar::Client.to_keypair as shortcut.
46
+ # @param subject [String|Stellar::Account|Stellar::PublicKey|Stellar::SignerKey|Stellar::Keypair] subject.
47
+ # @return [Stellar::Keypair] Stellar::Keypair instance.
48
+ def KeyPair(subject = nil)
49
+ case subject
50
+ when ->(subj) { subj.respond_to?(:to_keypair) }
51
+ subject.to_keypair
52
+ when PublicKey
53
+ KeyPair.from_public_key(subject.value)
54
+ when SignerKey
55
+ KeyPair.from_raw_seed(subject.value)
56
+ when /^G[A-Z0-9]{55}$/
57
+ KeyPair.from_address(subject.to_str)
58
+ when /^S[A-Z0-9]{55}$/
59
+ KeyPair.from_seed(subject.to_str)
60
+ when /^.{32}$/
61
+ KeyPair.from_raw_seed(subject.to_str)
62
+ when nil
63
+ KeyPair.random
64
+ else
65
+ raise TypeError, "cannot convert #{subject.inspect} to Stellar::KeyPair"
66
+ end
67
+ end
68
+
69
+ # Provides conversion from different input types into the SignerKey to use in ManageData operation.
70
+ # @param input [String|zStellar::Account|Stellar::PublicKey|Stellar::SignerKey|Stellar::Keypair] subject.
71
+ # @return [Stellar::SignerKey] Stellar::Keypair instance.
72
+ def SignerKey(input = nil)
73
+ case input
74
+ when Transaction
75
+ SignerKey.pre_auth_tx(input.hash)
76
+ when /^[0-9A-Za-z+\/=]{44}$/
77
+ SignerKey.hash_x(Stellar::Convert.from_base64(input))
78
+ when /^[0-9a-f]{64}$/
79
+ SignerKey.hash_x(Stellar::Convert.from_hex(input))
80
+ when /^.{32}$/
81
+ SignerKey.hash_x(input)
82
+ else
83
+ SignerKey.ed25519(KeyPair(input))
84
+ end
85
+ end
86
+ end
87
+
88
+ include DSL
89
+ end
@@ -0,0 +1,50 @@
1
+ require "active_support/core_ext/string/inflections"
2
+ require "xdr"
3
+
4
+ # For every member of XDR::Enum define constant on the corresponding enum type class.
5
+ # Constant name is a member name stripped of the common prefix with enum type name.
6
+ XDR::DSL::Enum.redefine_method(:seal) do
7
+ names = [members.keys.first, name.demodulize.underscore + "_"].join(" ")
8
+ common_prefix = /\A(.*_).* \1.*\Z/.match(names)&.values_at(1)&.first
9
+ members.each do |name, value|
10
+ unless common_prefix.nil?
11
+ full_name, name = [name, name.delete_prefix(common_prefix)]
12
+ singleton_class.alias_method(name, full_name)
13
+ end
14
+ const_set(name.upcase, value)
15
+ end
16
+ self.sealed = true
17
+ end
18
+
19
+ XDR::DSL::Union.redefine_method(:switch) do |switch, arm = nil|
20
+ raise ArgumentError, "`switch_on` not defined yet" if switch_type.nil?
21
+
22
+ switch = normalize_switch_declaration(switch)
23
+ self.switches = switches.merge(switch => arm)
24
+
25
+ unless arm.nil?
26
+ define_singleton_method(arm) do |*args, **kwargs|
27
+ value_type = arms[arm]
28
+ value = if value_type.valid?(args.first)
29
+ args.first
30
+ elsif value_type.ancestors.include?(XDR::Struct)
31
+ value_type.new(kwargs)
32
+ elsif value_type.ancestors.include?(XDR::Union)
33
+ value_type.new(*args[0..1])
34
+ else
35
+ args.first
36
+ end
37
+ new(switch, value)
38
+ end
39
+ end
40
+ end
41
+
42
+ # XDR::Union delegates missing methods to the underlying value
43
+ XDR::Union.define_method(:method_missing) do |name, *args|
44
+ return super(name, *args) unless value&.respond_to?(name)
45
+ value&.public_send(name, *args)
46
+ end
47
+
48
+ XDR::Union.define_method(:respond_to_missing?) do |*args|
49
+ value&.respond_to?(*args)
50
+ end
@@ -1,44 +1,58 @@
1
1
  module Stellar
2
2
  class KeyPair
3
- def self.from_seed(seed)
4
- seed_bytes = Util::StrKey.check_decode(:seed, seed)
5
- from_raw_seed seed_bytes
6
- end
7
-
8
- def self.from_raw_seed(seed_bytes)
9
- secret_key = RbNaCl::SigningKey.new(seed_bytes)
10
- public_key = secret_key.verify_key
11
- new(public_key, secret_key)
12
- end
13
-
14
- def self.from_public_key(pk_bytes)
15
- public_key = RbNaCl::VerifyKey.new(pk_bytes)
16
- new(public_key)
17
- end
18
-
19
- def self.from_address(address)
20
- pk_bytes = Util::StrKey.check_decode(:account_id, address)
21
- from_public_key(pk_bytes)
22
- end
23
-
24
- def self.random
25
- secret_key = RbNaCl::SigningKey.generate
26
- public_key = secret_key.verify_key
27
- new(public_key, secret_key)
28
- end
29
-
30
- def self.from_network_passphrase(passphrase)
31
- network_id = Digest::SHA256.digest(passphrase)
32
- from_raw_seed network_id
3
+ module FactoryMethods
4
+ def from_seed(seed)
5
+ seed_bytes = Util::StrKey.check_decode(:seed, seed)
6
+ from_raw_seed seed_bytes
7
+ end
8
+
9
+ def from_address(address)
10
+ pk_bytes = Util::StrKey.check_decode(:account_id, address)
11
+ from_public_key(pk_bytes)
12
+ end
13
+
14
+ def from_raw_seed(seed_bytes)
15
+ secret_key = RbNaCl::SigningKey.new(seed_bytes)
16
+ public_key = secret_key.verify_key
17
+ new(public_key, secret_key)
18
+ end
19
+
20
+ def from_public_key(pk_bytes)
21
+ public_key = RbNaCl::VerifyKey.new(pk_bytes)
22
+ new(public_key)
23
+ end
24
+
25
+ def random
26
+ secret_key = RbNaCl::SigningKey.generate
27
+ public_key = secret_key.verify_key
28
+ new(public_key, secret_key)
29
+ end
30
+
31
+ def from_network_passphrase(passphrase)
32
+ network_id = Digest::SHA256.digest(passphrase)
33
+ from_raw_seed network_id
34
+ end
35
+
36
+ def master
37
+ from_raw_seed(Stellar.current_network_id)
38
+ end
39
+ end
40
+
41
+ extend FactoryMethods
42
+
43
+ # @param [RbNaCl::VerifyKey] public_key
44
+ # @param [RbNaCl::SigningKey, nil] secret_key
45
+ def initialize(public_key, secret_key = nil)
46
+ @public_key = public_key
47
+ @secret_key = secret_key
33
48
  end
34
49
 
35
- def self.master
36
- from_raw_seed(Stellar.current_network_id)
50
+ def address
51
+ Util::StrKey.check_encode(:account_id, raw_public_key)
37
52
  end
38
53
 
39
- def initialize(public_key, secret_key = nil)
40
- @public_key = public_key
41
- @secret_key = secret_key
54
+ def seed
55
+ Util::StrKey.check_encode(:seed, raw_seed)
42
56
  end
43
57
 
44
58
  def account_id
@@ -57,16 +71,17 @@ module Stellar
57
71
  Stellar::SignerKey.new :signer_key_type_ed25519, raw_public_key
58
72
  end
59
73
 
60
- def raw_public_key
61
- @public_key.to_bytes
62
- end
63
-
64
74
  def signature_hint
65
75
  # take last 4 bytes
66
76
  account_id.to_xdr.slice(-4, 4)
67
77
  end
68
78
 
79
+ def raw_public_key
80
+ @public_key.to_bytes
81
+ end
82
+
69
83
  def raw_seed
84
+ raise "no private key" if @secret_key.nil?
70
85
  @secret_key.to_bytes
71
86
  end
72
87
 
@@ -78,25 +93,13 @@ module Stellar
78
93
  @public_key
79
94
  end
80
95
 
81
- def address
82
- pk_bytes = raw_public_key
83
- Util::StrKey.check_encode(:account_id, pk_bytes)
84
- end
85
-
86
- def seed
87
- raise "no private key" if @secret_key.nil?
88
- # TODO: improve the error class above
89
- seed_bytes = raw_seed
90
- Util::StrKey.check_encode(:seed, seed_bytes)
91
- end
92
-
93
96
  def sign?
94
97
  !@secret_key.nil?
95
98
  end
96
99
 
97
100
  def sign(message)
98
- raise "no private key" if @secret_key.nil?
99
- # TODO: improve the error class above
101
+ raise NotImplementedError, "no private key, signing is not available" unless sign?
102
+
100
103
  @secret_key.sign(message)
101
104
  end
102
105
 
@@ -115,5 +118,9 @@ module Stellar
115
118
  rescue RbNaCl::BadSignatureError
116
119
  false
117
120
  end
121
+
122
+ def to_keypair
123
+ self
124
+ end
118
125
  end
119
126
  end