stellar-horizon 0.29.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 7f21b25ec3403a5aa4a6d118fb428e7e4de949ea8530ab7fc10d99f96de75477
4
+ data.tar.gz: 79258881494240f18edaaba909e7afb2602ebdeaadd0cf47959383745d8d7870
5
+ SHA512:
6
+ metadata.gz: 42d1ebd3df2be5f4d436e6d83e2d04fd643aa751bc490e546420e844b7b3085fb9124139d47a0ee87d6cb41fc3a743f654b52ac8f0c0334c758f10b972da2d91
7
+ data.tar.gz: 7658aac83aa40803f806eb95e7d3728c2a9bada248f0330883efe75cc99b4eaf76a0d7c4f64d9aa4557015553649e3d6f0e25025faf6e2e5b432196fcb33963d
data/CHANGELOG.md ADDED
@@ -0,0 +1,13 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this
4
+ file. The format is based on [Keep a Changelog](https://keepachangelog.com/)
5
+ and this project adheres to [Semantic Versioning](https://semver.org/).
6
+
7
+ As this project is pre 1.0, breaking changes may happen for minor version
8
+ bumps. A breaking change will get clearly notified in this log.
9
+
10
+ ## [0.29.0](https://www.github.com/astroband/ruby-stellar-sdk/compare/v0.28.0...v0.29.0) (2021-09-07)
11
+
12
+ ### Added
13
+ * Initial setup of the gem, copying all Horizon-related features from `sdk` gem
data/LICENSE ADDED
File without changes
data/README.md ADDED
File without changes
@@ -0,0 +1,298 @@
1
+ require "hyperclient"
2
+ require "active_support/core_ext/object/blank"
3
+ require "securerandom"
4
+
5
+ module Stellar::Horizon
6
+ class AccountRequiresMemoError < StandardError
7
+ attr_reader :account_id, :operation_index
8
+
9
+ def initialize(message, account_id, operation_index)
10
+ super(message)
11
+ @account_id = account_id
12
+ @operation_index = operation_index
13
+ end
14
+ end
15
+
16
+ class Client
17
+ DEFAULT_FEE = 100
18
+
19
+ HORIZON_LOCALHOST_URL = "http://127.0.0.1:8000"
20
+ HORIZON_MAINNET_URL = "https://horizon.stellar.org"
21
+ HORIZON_TESTNET_URL = "https://horizon-testnet.stellar.org"
22
+ FRIENDBOT_URL = "https://friendbot.stellar.org".freeze
23
+
24
+ def self.default(options = {})
25
+ new options.merge(
26
+ horizon: HORIZON_MAINNET_URL
27
+ )
28
+ end
29
+
30
+ def self.default_testnet(options = {})
31
+ new options.merge(
32
+ horizon: HORIZON_TESTNET_URL,
33
+ friendbot: HORIZON_TESTNET_URL
34
+ )
35
+ end
36
+
37
+ def self.localhost(options = {})
38
+ new options.merge(
39
+ horizon: HORIZON_LOCALHOST_URL
40
+ )
41
+ end
42
+
43
+ attr_reader :horizon
44
+
45
+ # @option options [String] :horizon The Horizon server URL.
46
+ def initialize(options)
47
+ @options = options
48
+ @horizon = Hyperclient.new(options[:horizon]) { |client|
49
+ client.faraday_block = lambda do |conn|
50
+ conn.use Faraday::Response::RaiseError
51
+ conn.use FaradayMiddleware::FollowRedirects
52
+ conn.request :url_encoded
53
+ conn.response :hal_json, content_type: /\bjson$/
54
+ conn.adapter :excon
55
+ end
56
+ client.headers = {
57
+ "Accept" => "application/hal+json,application/problem+json,application/json",
58
+ "X-Client-Name" => "ruby-stellar-sdk",
59
+ "X-Client-Version" => Stellar::Horizon::VERSION
60
+ }
61
+ }
62
+ end
63
+
64
+ # @param [Stellar::Account|String] account_or_address
65
+ def account_info(account_or_address)
66
+ account_id = if account_or_address.is_a?(Stellar::Account)
67
+ account_or_address.address
68
+ else
69
+ account_or_address
70
+ end
71
+ @horizon.account(account_id: account_id)._get
72
+ end
73
+
74
+ # @option options [Stellar::Account] :account
75
+ # @option options [Stellar::Account] :destination
76
+ def account_merge(options = {})
77
+ account = options[:account]
78
+ destination = options[:destination]
79
+ sequence = options[:sequence] || (account_info(account).sequence.to_i + 1)
80
+
81
+ transaction = Stellar::TransactionBuilder.account_merge(
82
+ source_account: destination.keypair,
83
+ sequence_number: sequence,
84
+ destination: destination.keypair
85
+ )
86
+
87
+ envelope = transaction.to_envelope(account.keypair)
88
+ submit_transaction(tx_envelope: envelope)
89
+ end
90
+
91
+ def friendbot(account)
92
+ uri = URI.parse(FRIENDBOT_URL)
93
+ uri.query = "addr=#{account.address}"
94
+ Faraday.post(uri.to_s)
95
+ end
96
+
97
+ # @option options [Stellar::Account] :account
98
+ # @option options [Stellar::Account] :funder
99
+ # @option options [Integer] :starting_balance
100
+ def create_account(options = {})
101
+ funder = options[:funder]
102
+ sequence = options[:sequence] || (account_info(funder).sequence.to_i + 1)
103
+ # In the future, the fee should be grabbed from the network's last transactions,
104
+ # instead of using a hard-coded default value.
105
+ fee = options[:fee] || DEFAULT_FEE
106
+
107
+ payment = Stellar::TransactionBuilder.create_account(
108
+ source_account: funder.keypair,
109
+ sequence_number: sequence,
110
+ base_fee: fee,
111
+ destination: options[:account].keypair,
112
+ starting_balance: options[:starting_balance]
113
+ )
114
+ envelope = payment.to_envelope(funder.keypair)
115
+ submit_transaction(tx_envelope: envelope)
116
+ end
117
+
118
+ # @option options [Stellar::Account] :from The source account
119
+ # @option options [Stellar::Account] :to The destination account
120
+ # @option options [Stellar::Amount] :amount The amount to send
121
+ def send_payment(options = {})
122
+ from_account = options[:from]
123
+ tx_source_account = options[:transaction_source] || from_account
124
+ op_source_account = from_account if tx_source_account.present?
125
+
126
+ sequence = options[:sequence] ||
127
+ (account_info(tx_source_account).sequence.to_i + 1)
128
+
129
+ payment = Stellar::TransactionBuilder.new(
130
+ source_account: tx_source_account.keypair,
131
+ sequence_number: sequence
132
+ ).add_operation(
133
+ Stellar::Operation.payment(
134
+ source_account: op_source_account.keypair,
135
+ destination: options[:to].keypair,
136
+ amount: options[:amount].to_payment
137
+ )
138
+ ).set_memo(options[:memo]).set_timeout(0).build
139
+
140
+ signers = [tx_source_account, op_source_account].uniq(&:address)
141
+ to_envelope_args = signers.map(&:keypair)
142
+
143
+ envelope = payment.to_envelope(*to_envelope_args)
144
+ submit_transaction(tx_envelope: envelope)
145
+ end
146
+
147
+ # @option options [Stellar::Account] :account
148
+ # @option options [Integer] :limit
149
+ # @option options [Integer] :cursor
150
+ # @return [Stellar::TransactionPage]
151
+ def transactions(options = {})
152
+ args = options.slice(:limit, :cursor)
153
+
154
+ resource = if options[:account]
155
+ args = args.merge(account_id: options[:account].address)
156
+ @horizon.account_transactions(args)
157
+ else
158
+ @horizon.transactions(args)
159
+ end
160
+
161
+ Stellar::TransactionPage.new(resource)
162
+ end
163
+
164
+ # @param [Array(Symbol,String,Stellar::KeyPair|Stellar::Account)] asset
165
+ # @param [Stellar::Account] source
166
+ # @param [Integer] sequence
167
+ # @param [Integer] fee
168
+ # @param [Integer] limit
169
+ def change_trust(
170
+ asset:,
171
+ source:,
172
+ sequence: nil,
173
+ fee: DEFAULT_FEE,
174
+ limit: nil
175
+ )
176
+ sequence ||= (account_info(source).sequence.to_i + 1)
177
+
178
+ op_args = {
179
+ account: source.keypair,
180
+ sequence: sequence,
181
+ line: asset
182
+ }
183
+ op_args[:limit] = limit unless limit.nil?
184
+
185
+ tx = Stellar::TransactionBuilder.change_trust(
186
+ source_account: source.keypair,
187
+ sequence_number: sequence,
188
+ **op_args
189
+ )
190
+
191
+ envelope = tx.to_envelope(source.keypair)
192
+ submit_transaction(tx_envelope: envelope)
193
+ end
194
+
195
+ # @param [Stellar::TransactionEnvelope] tx_envelope
196
+ # @option options [Boolean] :skip_memo_required_check (false)
197
+ def submit_transaction(tx_envelope:, options: {skip_memo_required_check: false})
198
+ unless options[:skip_memo_required_check]
199
+ check_memo_required(tx_envelope)
200
+ end
201
+ @horizon.transactions._post(tx: tx_envelope.to_xdr(:base64))
202
+ end
203
+
204
+ # Required by SEP-0029
205
+ # @param [Stellar::TransactionEnvelope] tx_envelope
206
+ def check_memo_required(tx_envelope)
207
+ tx = tx_envelope.tx
208
+
209
+ if tx.is_a?(Stellar::FeeBumpTransaction)
210
+ tx = tx.inner_tx.v1!.tx
211
+ end
212
+
213
+ # Check transactions where the .memo field is nil or of type MemoType.memo_none
214
+ if !tx.memo.nil? && tx.memo.type != Stellar::MemoType.memo_none
215
+ return
216
+ end
217
+
218
+ destinations = Set.new
219
+ ot = Stellar::OperationType
220
+
221
+ tx.operations.each_with_index do |op, idx|
222
+ destination = case op.body.type
223
+ when ot.payment, ot.path_payment_strict_receive, ot.path_payment_strict_send
224
+ op.body.value.destination
225
+ when ot.account_merge
226
+ # There is no AccountMergeOp, op.body is an Operation object
227
+ # and op.body.value is a PublicKey (or AccountID) object.
228
+ op.body.value
229
+ else
230
+ next
231
+ end
232
+
233
+ if destinations.include?(destination) || destination.switch == Stellar::CryptoKeyType.key_type_muxed_ed25519
234
+ next
235
+ end
236
+
237
+ destinations.add(destination)
238
+ kp = Stellar::KeyPair.from_public_key(destination.value)
239
+
240
+ begin
241
+ info = account_info(kp.address)
242
+ rescue Faraday::ResourceNotFound
243
+ # Don't raise an error if its a 404, but throw one otherwise
244
+ next
245
+ end
246
+ if info.data["config.memo_required"] == "MQ=="
247
+ # MQ== is the base64 encoded string for the string "1"
248
+ raise AccountRequiresMemoError.new("account requires memo", destination, idx)
249
+ end
250
+ end
251
+ end
252
+
253
+ # DEPRECATED: this function has been moved Stellar::SEP10.build_challenge_tx and
254
+ # will be removed in the next major version release.
255
+ #
256
+ # A wrapper function for Stellar::SEP10::build_challenge_tx.
257
+ #
258
+ # @param server [Stellar::KeyPair] Keypair for server's signing account.
259
+ # @param client [Stellar::KeyPair] Keypair for the account whishing to authenticate with the server.
260
+ # @param anchor_name [String] Anchor's name to be used in the manage_data key.
261
+ # @param timeout [Integer] Challenge duration (default to 5 minutes).
262
+ #
263
+ # @return [String] A base64 encoded string of the raw TransactionEnvelope xdr struct for the transaction.
264
+ def build_challenge_tx(server:, client:, anchor_name:, timeout: 300)
265
+ Stellar::SEP10.build_challenge_tx(
266
+ server: server, client: client, anchor_name: anchor_name, timeout: timeout
267
+ )
268
+ end
269
+
270
+ # DEPRECATED: this function has been moved to Stellar::SEP10::read_challenge_tx and
271
+ # will be removed in the next major version release.
272
+ #
273
+ # A wrapper function for Stellar::SEP10.verify_challenge_transaction
274
+ #
275
+ # @param challenge [String] SEP0010 transaction challenge in base64.
276
+ # @param server [Stellar::KeyPair] Stellar::KeyPair for server where the challenge was generated.
277
+ #
278
+ # @return [Boolean]
279
+ def verify_challenge_tx(challenge:, server:)
280
+ Stellar::SEP10.verify_challenge_tx(challenge_xdr: challenge, server: server)
281
+ true
282
+ end
283
+
284
+ # DEPRECATED: this function has been moved to Stellar::SEP10::verify_tx_signed_by and
285
+ # will be removed in the next major version release.
286
+ #
287
+ # @param transaction_envelope [Stellar::TransactionEnvelope]
288
+ # @param keypair [Stellar::KeyPair]
289
+ #
290
+ # @return [Boolean]
291
+ #
292
+ def verify_tx_signed_by(transaction_envelope:, keypair:)
293
+ Stellar::SEP10.verify_tx_signed_by(
294
+ tx_envelope: transaction_envelope, keypair: keypair
295
+ )
296
+ end
297
+ end
298
+ end
@@ -0,0 +1,9 @@
1
+ require "stellar-sdk"
2
+
3
+ module Stellar
4
+ module Horizon
5
+ VERSION = ::Stellar::VERSION
6
+
7
+ autoload :Client, "#{__dir__}/stellar/horizon/client.rb"
8
+ end
9
+ end
metadata ADDED
@@ -0,0 +1,171 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: stellar-horizon
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.29.0
5
+ platform: ruby
6
+ authors:
7
+ - Sergey Nebolsin
8
+ - Timur Ramazanov
9
+ autorequire:
10
+ bindir: exe
11
+ cert_chain: []
12
+ date: 2021-09-07 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: stellar-sdk
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - '='
19
+ - !ruby/object:Gem::Version
20
+ version: 0.29.0
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - '='
26
+ - !ruby/object:Gem::Version
27
+ version: 0.29.0
28
+ - !ruby/object:Gem::Dependency
29
+ name: excon
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: 0.71.0
35
+ - - "<"
36
+ - !ruby/object:Gem::Version
37
+ version: '1.0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ version: 0.71.0
45
+ - - "<"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.0'
48
+ - !ruby/object:Gem::Dependency
49
+ name: hyperclient
50
+ requirement: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: 0.7.0
55
+ - - "<"
56
+ - !ruby/object:Gem::Version
57
+ version: '2.0'
58
+ type: :runtime
59
+ prerelease: false
60
+ version_requirements: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: 0.7.0
65
+ - - "<"
66
+ - !ruby/object:Gem::Version
67
+ version: '2.0'
68
+ - !ruby/object:Gem::Dependency
69
+ name: toml-rb
70
+ requirement: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: 1.1.1
75
+ - - "<"
76
+ - !ruby/object:Gem::Version
77
+ version: '3.0'
78
+ type: :runtime
79
+ prerelease: false
80
+ version_requirements: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: 1.1.1
85
+ - - "<"
86
+ - !ruby/object:Gem::Version
87
+ version: '3.0'
88
+ - !ruby/object:Gem::Dependency
89
+ name: bundler
90
+ requirement: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - "~>"
93
+ - !ruby/object:Gem::Version
94
+ version: '2.0'
95
+ type: :development
96
+ prerelease: false
97
+ version_requirements: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - "~>"
100
+ - !ruby/object:Gem::Version
101
+ version: '2.0'
102
+ - !ruby/object:Gem::Dependency
103
+ name: rake
104
+ requirement: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - "~>"
107
+ - !ruby/object:Gem::Version
108
+ version: '13'
109
+ type: :development
110
+ prerelease: false
111
+ version_requirements: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - "~>"
114
+ - !ruby/object:Gem::Version
115
+ version: '13'
116
+ - !ruby/object:Gem::Dependency
117
+ name: rspec
118
+ requirement: !ruby/object:Gem::Requirement
119
+ requirements:
120
+ - - "~>"
121
+ - !ruby/object:Gem::Version
122
+ version: '3.9'
123
+ type: :development
124
+ prerelease: false
125
+ version_requirements: !ruby/object:Gem::Requirement
126
+ requirements:
127
+ - - "~>"
128
+ - !ruby/object:Gem::Version
129
+ version: '3.9'
130
+ description:
131
+ email:
132
+ executables: []
133
+ extensions: []
134
+ extra_rdoc_files:
135
+ - README.md
136
+ - LICENSE
137
+ - CHANGELOG.md
138
+ files:
139
+ - CHANGELOG.md
140
+ - LICENSE
141
+ - README.md
142
+ - lib/stellar-horizon.rb
143
+ - lib/stellar/horizon/client.rb
144
+ homepage: https://github.com/stellar/ruby-stellar-sdk/tree/master/horizon
145
+ licenses:
146
+ - Apache-2.0
147
+ metadata:
148
+ github_repo: ssh://github.com/astroband/ruby-stellar-sdk
149
+ documentation_uri: https://rubydoc.info/gems/stellar-sdk/0.29.0/
150
+ changelog_uri: https://github.com/astroband/ruby-stellar-sdk/blob/v0.29.0/horizon/CHANGELOG.md
151
+ source_code_uri: https://github.com/astroband/ruby-stellar-sdk/tree/v0.29.0/horizon
152
+ post_install_message:
153
+ rdoc_options: []
154
+ require_paths:
155
+ - lib
156
+ required_ruby_version: !ruby/object:Gem::Requirement
157
+ requirements:
158
+ - - ">="
159
+ - !ruby/object:Gem::Version
160
+ version: 2.5.0
161
+ required_rubygems_version: !ruby/object:Gem::Requirement
162
+ requirements:
163
+ - - ">="
164
+ - !ruby/object:Gem::Version
165
+ version: '0'
166
+ requirements: []
167
+ rubygems_version: 3.1.4
168
+ signing_key:
169
+ specification_version: 4
170
+ summary: Stellar Horizon client library
171
+ test_files: []