solana-ruby 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1a89b4b3a79a083057806945963669aab8ca3b312223ea7c1e13a41a26c0063b
4
- data.tar.gz: 824eaaa7913f9b499bc6514f1d5fec3d48f3692f399a3205d069425ea32b328c
3
+ metadata.gz: 9ce5e8285735080d504a24b4a1237a9ea2273939b7d77965e0184baf282853ba
4
+ data.tar.gz: 032a7e179b759db0ddca3f42299837838470bf36649bdf118c93375deba04394
5
5
  SHA512:
6
- metadata.gz: 8317d94e7781fb218a31c73a2270daf7ccf5d782f4ec565e89c90994abf871827593a25cec9cb0c83e4bab9bc42a7fc30029c9b289785e3499d81f2c7549a8b9
7
- data.tar.gz: e50e55dd5237008503167a603959cad90877ee88c1d43a434924d64db59688783de6445b3f8eb42e14575e2006a0dfc2635d324db6319683c7bf3494f1d701f7
6
+ metadata.gz: b3d9b31be76b89d2de951324a037dd5cc61d8c04e60eeff30d81730d49d65844a464b8f0d93e7deb08e127aed155479c6b370993bb0fdf7aa553b89440b0ab90
7
+ data.tar.gz: e71dec47fbd4722efee8ed355d70b7b864d952968cbdbcd97fefc454346a68564da8c4816652899306f88c9cb5f8c13060c82cbfaa7e33ad4a93da596f218217
@@ -1,249 +1,772 @@
1
- require 'httparty'
1
+ require 'faraday'
2
+ require 'faye/websocket'
2
3
  require 'json'
4
+ require 'thread'
5
+
6
+ require_relative 'utils'
3
7
 
4
8
  module SolanaRB
9
+ ##
10
+ # Client class for interacting with the Solana JSON RPC API over HTTP and WS.
5
11
  class Client
6
- include HTTParty
7
- base_uri 'https://api.mainnet-beta.solana.com'
8
-
9
- def initialize(api_key = nil)
12
+ ##
13
+ # Initializes a new Client.
14
+ #
15
+ # @param [String, nil] api_key Optional API key for authentication.
16
+ def initialize(api_endpoint = SolanaRB::Utils::MAINNET, api_key = nil)
10
17
  @api_key = api_key
18
+ @api_endpoint = api_endpoint
19
+ # @api_ws = WebSocket::Handshake::Client.new(url: @api_endpoint::WS)
20
+ @api_http = Faraday.new(url: @api_endpoint::HTTP) do |faraday|
21
+ faraday.request :json
22
+ faraday.response :json, content_type: 'application/json'
23
+ faraday.adapter Faraday.default_adapter
24
+ end
11
25
  end
12
26
 
27
+ ##
28
+ # Retrieves account information for a given public key.
29
+ #
30
+ # @param [String] pubkey The public key of the account.
31
+ # @param [Hash] options Optional parameters for the request.
32
+ # @return [Hash] The account information.
13
33
  def get_account_info(pubkey, options = {})
14
- request('getAccountInfo', [pubkey, options])
34
+ request_http('getAccountInfo', [pubkey, options])
15
35
  end
16
36
 
37
+ ##
38
+ # Retrieves the balance for a given public key.
39
+ #
40
+ # @param [String] pubkey The public key of the account.
41
+ # @param [Hash] options Optional parameters for the request.
42
+ # @return [Integer] The balance in lamports.
17
43
  def get_balance(pubkey, options = {})
18
- request('getBalance', [pubkey, options])
44
+ request_http('getBalance', [pubkey, options])
19
45
  end
20
46
 
47
+ ##
48
+ # Retrieves information about a specific block.
49
+ #
50
+ # @param [Integer] slot_number The slot number of the block.
51
+ # @param [Hash] options Optional parameters for the request.
52
+ # @return [Hash] The block information.
21
53
  def get_block(slot_number, options = {})
22
- request('getBlock', [slot_number, options])
54
+ request_http('getBlock', [slot_number, options])
23
55
  end
24
56
 
57
+ ##
58
+ # Retrieves block commitment information for a specific block.
59
+ #
60
+ # @param [Integer] slot_number The slot number of the block.
61
+ # @param [Hash] options Optional parameters for the request.
62
+ # @return [Hash] The block commitment information.
25
63
  def get_block_commitment(slot_number, options = {})
26
- request('getBlockCommitment', [slot_number, options])
64
+ request_http('getBlockCommitment', [slot_number, options])
27
65
  end
28
66
 
67
+ ##
68
+ # Retrieves the current block height.
69
+ #
70
+ # @param [Hash] options Optional parameters for the request.
71
+ # @return [Integer] The current block height.
29
72
  def get_block_height(options = {})
30
- request('getBlockHeight', [options])
73
+ request_http('getBlockHeight', [options])
31
74
  end
32
75
 
76
+ ##
77
+ # Retrieves block production information.
78
+ #
79
+ # @param [Hash] options Optional parameters for the request.
80
+ # @return [Hash] The block production information.
33
81
  def get_block_production(options = {})
34
- request('getBlockProduction', [options])
82
+ request_http('getBlockProduction', [options])
35
83
  end
36
84
 
85
+ ##
86
+ # Retrieves the estimated production time of a specific block.
87
+ #
88
+ # @param [Integer] slot_number The slot number of the block.
89
+ # @param [Hash] options Optional parameters for the request.
90
+ # @return [Integer] The estimated production time in seconds.
37
91
  def get_block_time(slot_number, options = {})
38
- request('getBlockTime', [slot_number, options])
92
+ request_http('getBlockTime', [slot_number, options])
39
93
  end
40
94
 
95
+ ##
96
+ # Retrieves a list of confirmed blocks between two slot numbers.
97
+ #
98
+ # @param [Integer] start_slot The start slot number.
99
+ # @param [Integer] end_slot The end slot number.
100
+ # @param [Hash] options Optional parameters for the request.
101
+ # @return [Array<Integer>] The list of confirmed blocks.
41
102
  def get_blocks(start_slot, end_slot, options = {})
42
- request('getBlocks', [start_slot, end_slot, options])
103
+ request_http('getBlocks', [start_slot, end_slot, options])
43
104
  end
44
105
 
106
+ ##
107
+ # Retrieves a list of confirmed blocks starting from a given slot number with a limit on the number of blocks.
108
+ #
109
+ # @param [Integer] start_slot The start slot number.
110
+ # @param [Integer] limit The maximum number of blocks to return.
111
+ # @param [Hash] options Optional parameters for the request.
112
+ # @return [Array<Integer>] The list of confirmed blocks.
45
113
  def get_blocks_with_limit(start_slot, limit, options = {})
46
- request('getBlocksWithLimit', [start_slot, limit, options])
114
+ request_http('getBlocksWithLimit', [start_slot, limit, options])
47
115
  end
48
116
 
117
+ ##
118
+ # Retrieves the list of cluster nodes.
119
+ #
120
+ # @param [Hash] options Optional parameters for the request.
121
+ # @return [Array<Hash>] The list of cluster nodes.
49
122
  def get_cluster_nodes(options = {})
50
- request('getClusterNodes', [options])
123
+ request_http('getClusterNodes', [options])
51
124
  end
52
125
 
126
+ ##
127
+ # Retrieves epoch information.
128
+ #
129
+ # @param [Hash] options Optional parameters for the request.
130
+ # @return [Hash] The epoch information.
53
131
  def get_epoch_info(options = {})
54
- request('getEpochInfo', [options])
132
+ request_http('getEpochInfo', [options])
55
133
  end
56
134
 
135
+ ##
136
+ # Retrieves the epoch schedule.
137
+ #
138
+ # @param [Hash] options Optional parameters for the request.
139
+ # @return [Hash] The epoch schedule.
57
140
  def get_epoch_schedule(options = {})
58
- request('getEpochSchedule', [options])
141
+ request_http('getEpochSchedule', [options])
59
142
  end
60
143
 
144
+ ##
145
+ # Retrieves the fee for a given message.
146
+ #
147
+ # @param [String] message The message for which the fee is to be calculated.
148
+ # @param [Hash] options Optional parameters for the request.
149
+ # @return [Integer] The fee for the message.
61
150
  def get_fee_for_message(message, options = {})
62
- request('getFeeForMessage', [message, options])
151
+ request_http('getFeeForMessage', [message, options])
63
152
  end
64
153
 
154
+ ##
155
+ # Retrieves the slot of the first available block.
156
+ #
157
+ # @param [Hash] options Optional parameters for the request.
158
+ # @return [Integer] The slot of the first available block.
65
159
  def get_first_available_block(options = {})
66
- request('getFirstAvailableBlock', [options])
160
+ request_http('getFirstAvailableBlock', [options])
67
161
  end
68
162
 
163
+ ##
164
+ # Retrieves the genesis hash.
165
+ #
166
+ # @param [Hash] options Optional parameters for the request.
167
+ # @return [String] The genesis hash.
69
168
  def get_genesis_hash(options = {})
70
- request('getGenesisHash', [options])
169
+ request_http('getGenesisHash', [options])
71
170
  end
72
171
 
172
+ ##
173
+ # Checks the health of the node.
174
+ #
175
+ # @param [Hash] options Optional parameters for the request.
176
+ # @return [String] The health status of the node.
73
177
  def get_health(options = {})
74
- request('getHealth', [options])
178
+ request_http('getHealth', [options])
75
179
  end
76
180
 
181
+ ##
182
+ # Retrieves the highest snapshot slot.
183
+ #
184
+ # @param [Hash] options Optional parameters for the request.
185
+ # @return [Integer] The highest snapshot slot.
77
186
  def get_highest_snapshot_slot(options = {})
78
- request('getHighestSnapshotSlot', [options])
187
+ request_http('getHighestSnapshotSlot', [options])
79
188
  end
80
189
 
190
+ ##
191
+ # Retrieves the identity of the node.
192
+ #
193
+ # @param [Hash] options Optional parameters for the request.
194
+ # @return [Hash] The identity information of the node.
81
195
  def get_identity(options = {})
82
- request('getIdentity', [options])
196
+ request_http('getIdentity', [options])
83
197
  end
84
198
 
199
+ ##
200
+ # Retrieves the current inflation governor settings.
201
+ #
202
+ # @param [Hash] options Optional parameters for the request.
203
+ # @return [Hash] The inflation governor settings.
85
204
  def get_inflation_governor(options = {})
86
- request('getInflationGovernor', [options])
205
+ request_http('getInflationGovernor', [options])
87
206
  end
88
207
 
208
+ ##
209
+ # Retrieves the current inflation rate.
210
+ #
211
+ # @param [Hash] options Optional parameters for the request.
212
+ # @return [Hash] The inflation rate.
89
213
  def get_inflation_rate(options = {})
90
- request('getInflationRate', [options])
214
+ request_http('getInflationRate', [options])
91
215
  end
92
216
 
217
+ ##
218
+ # Retrieves the inflation reward for a given list of addresses.
219
+ #
220
+ # @param [Array<String>] addresses The list of addresses.
221
+ # @param [Hash] options Optional parameters for the request.
222
+ # @return [Array<Hash>] The inflation rewards for the addresses.
93
223
  def get_inflation_reward(addresses, options = {})
94
- request('getInflationReward', [addresses, options])
224
+ request_http('getInflationReward', [addresses, options])
95
225
  end
96
226
 
227
+ ##
228
+ # Retrieves the largest accounts.
229
+ #
230
+ # @param [Hash] options Optional parameters for the request.
231
+ # @return [Array<Hash>] The largest accounts.
97
232
  def get_largest_accounts(options = {})
98
- request('getLargestAccounts', [options])
233
+ request_http('getLargestAccounts', [options])
99
234
  end
100
235
 
236
+ ##
237
+ # Retrieves the latest blockhash.
238
+ #
239
+ # @param [Hash] options Optional parameters for the request.
240
+ # @return [Hash] The latest blockhash.
101
241
  def get_latest_blockhash(options = {})
102
- request('getLatestBlockhash', [options])
242
+ request_http('getLatestBlockhash', [options])
103
243
  end
104
244
 
245
+ ##
246
+ # Retrieves the leader schedule.
247
+ #
248
+ # @param [Hash] options Optional parameters for the request.
249
+ # @return [Hash] The leader schedule.
105
250
  def get_leader_schedule(options = {})
106
- request('getLeaderSchedule', [options])
251
+ request_http('getLeaderSchedule', [options])
107
252
  end
108
253
 
254
+ ##
255
+ # Retrieves the maximum retransmit slot.
256
+ #
257
+ # @param [Hash] options Optional parameters for the request.
258
+ # @return [Integer] The maximum retransmit slot.
109
259
  def get_max_retransmit_slot(options = {})
110
- request('getMaxRetransmitSlot', [options])
260
+ request_http('getMaxRetransmitSlot', [options])
111
261
  end
112
262
 
263
+ ##
264
+ # Retrieves the maximum shred insert slot.
265
+ #
266
+ # @param [Hash] options Optional parameters for the request.
267
+ # @return [Integer] The maximum shred insert slot.
113
268
  def get_max_shred_insert_slot(options = {})
114
- request('getMaxShredInsertSlot', [options])
269
+ request_http('getMaxShredInsertSlot', [options])
115
270
  end
116
271
 
272
+ ##
273
+ # Retrieves the minimum balance required for rent exemption for a given data length.
274
+ #
275
+ # @param [Integer] data_length The length of the data in bytes.
276
+ # @param [Hash] options Optional parameters for the request.
277
+ # @return [Integer] The minimum balance for rent exemption.
117
278
  def get_minimum_balance_for_rent_exemption(data_length, options = {})
118
- request('getMinimumBalanceForRentExemption', [data_length, options])
279
+ request_http('getMinimumBalanceForRentExemption', [data_length, options])
119
280
  end
120
281
 
282
+ ##
283
+ # Retrieves information for multiple accounts.
284
+ #
285
+ # @param [Array<String>] pubkeys The list of public keys.
286
+ # @param [Hash] options Optional parameters for the request.
287
+ # @return [Array<Hash>] The information for the accounts.
121
288
  def get_multiple_accounts(pubkeys, options = {})
122
- request('getMultipleAccounts', [pubkeys, options])
289
+ request_http('getMultipleAccounts', [pubkeys, options])
123
290
  end
124
291
 
292
+ ##
293
+ # Retrieves information for accounts owned by a specific program.
294
+ #
295
+ # @param [String] pubkey The public key of the program.
296
+ # @param [Hash] options Optional parameters for the request.
297
+ # @return [Array<Hash>] The information for the program accounts.
125
298
  def get_program_accounts(pubkey, options = {})
126
- request('getProgramAccounts', [pubkey, options])
299
+ request_http('getProgramAccounts', [pubkey, options])
127
300
  end
128
301
 
302
+ ##
303
+ # Retrieves recent performance samples.
304
+ #
305
+ # @param [Hash] options Optional parameters for the request.
306
+ # @return [Array<Hash>] The recent performance samples.
129
307
  def get_recent_performance_samples(options = {})
130
- request('getRecentPerformanceSamples', [options])
308
+ request_http('getRecentPerformanceSamples', [options])
131
309
  end
132
310
 
311
+ ##
312
+ # Retrieves recent prioritization fees.
313
+ #
314
+ # @param [Hash] options Optional parameters for the request.
315
+ # @return [Hash] The recent prioritization fees.
133
316
  def get_recent_prioritization_fees(options = {})
134
- request('getRecentPrioritizationFees', [options])
317
+ request_http('getRecentPrioritizationFees', [options])
135
318
  end
136
319
 
320
+ ##
321
+ # Retrieves the status of given transaction signatures.
322
+ #
323
+ # @param [Array<String>] signatures The list of transaction signatures.
324
+ # @param [Hash] options Optional parameters for the request.
325
+ # @return [Array<Hash>] The status of the transaction signatures.
137
326
  def get_signature_statuses(signatures, options = {})
138
- request('getSignatureStatuses', [signatures, options])
327
+ request_http('getSignatureStatuses', [signatures, options])
139
328
  end
140
329
 
330
+ ##
331
+ # Retrieves the signatures for a given address.
332
+ #
333
+ # @param [String] address The address for which to retrieve signatures.
334
+ # @param [Hash] options Optional parameters for the request.
335
+ # @return [Array<Hash>] The signatures for the address.
141
336
  def get_signatures_for_address(address, options = {})
142
- request('getSignaturesForAddress', [address, options])
337
+ request_http('getSignaturesForAddress', [address, options])
143
338
  end
144
339
 
340
+ ##
341
+ # Retrieves the current slot.
342
+ #
343
+ # @param [Hash] options Optional parameters for the request.
344
+ # @return [Integer] The current slot.
145
345
  def get_slot(options = {})
146
- request('getSlot', [options])
346
+ request_http('getSlot', [options])
147
347
  end
148
348
 
349
+ ##
350
+ # Retrieves the current slot leader.
351
+ #
352
+ # @param [Hash] options Optional parameters for the request.
353
+ # @return [String] The current slot leader.
149
354
  def get_slot_leader(options = {})
150
- request('getSlotLeader', [options])
355
+ request_http('getSlotLeader', [options])
151
356
  end
152
357
 
358
+ ##
359
+ # Retrieves the slot leaders starting from a given slot with a limit on the number of leaders.
360
+ #
361
+ # @param [Integer] start_slot The start slot number.
362
+ # @param [Integer] limit The maximum number of leaders to return.
363
+ # @param [Hash] options Optional parameters for the request.
364
+ # @return [Array<String>] The slot leaders.
153
365
  def get_slot_leaders(start_slot, limit, options = {})
154
- request('getSlotLeaders', [start_slot, limit, options])
366
+ request_http('getSlotLeaders', [start_slot, limit, options])
155
367
  end
156
368
 
369
+ ##
370
+ # Retrieves the stake activation information for a given public key.
371
+ #
372
+ # @param [String] pubkey The public key of the stake account.
373
+ # @param [Hash] options Optional parameters for the request.
374
+ # @return [Hash] The stake activation information.
157
375
  def get_stake_activation(pubkey, options = {})
158
- request('getStakeActivation', [pubkey, options])
376
+ request_http('getStakeActivation', [pubkey, options])
159
377
  end
160
378
 
379
+ ##
380
+ # Retrieves the minimum delegation for a stake account.
381
+ #
382
+ # @param [Hash] options Optional parameters for the request.
383
+ # @return [Integer] The minimum delegation.
161
384
  def get_stake_minimum_delegation(options = {})
162
- request('getStakeMinimumDelegation', [options])
385
+ request_http('getStakeMinimumDelegation', [options])
163
386
  end
164
387
 
388
+ ##
389
+ # Retrieves the supply information.
390
+ #
391
+ # @param [Hash] options Optional parameters for the request.
392
+ # @return [Hash] The supply information.
165
393
  def get_supply(options = {})
166
- request('getSupply', [options])
394
+ request_http('getSupply', [options])
167
395
  end
168
396
 
397
+ ##
398
+ # Retrieves the token balance for a given token account.
399
+ #
400
+ # @param [String] pubkey The public key of the token account.
401
+ # @param [Hash] options Optional parameters for the request.
402
+ # @return [Hash] The token balance.
169
403
  def get_token_account_balance(pubkey, options = {})
170
- request('getTokenAccountBalance', [pubkey, options])
404
+ request_http('getTokenAccountBalance', [pubkey, options])
171
405
  end
172
406
 
407
+ ##
408
+ # Retrieves token accounts by delegate.
409
+ #
410
+ # @param [String] delegate The delegate address.
411
+ # @param [Hash] opts Additional options for the request.
412
+ # @param [Hash] options Optional parameters for the request.
413
+ # @return [Array<Hash>] The token accounts by delegate.
173
414
  def get_token_accounts_by_delegate(delegate, opts = {}, options = {})
174
- request('getTokenAccountsByDelegate', [delegate, opts, options])
415
+ request_http('getTokenAccountsByDelegate', [delegate, opts, options])
175
416
  end
176
417
 
418
+ ##
419
+ # Retrieves token accounts by owner.
420
+ #
421
+ # @param [String] owner The owner address.
422
+ # @param [Hash] opts Additional options for the request.
423
+ # @param [Hash] options Optional parameters for the request.
424
+ # @return [Array<Hash>] The token accounts by owner.
177
425
  def get_token_accounts_by_owner(owner, opts = {}, options = {})
178
- request('getTokenAccountsByOwner', [owner, opts, options])
426
+ request_http('getTokenAccountsByOwner', [owner, opts, options])
179
427
  end
180
428
 
429
+ ##
430
+ # Retrieves the largest accounts for a given token.
431
+ #
432
+ # @param [String] pubkey The public key of the token.
433
+ # @param [Hash] options Optional parameters for the request.
434
+ # @return [Array<Hash>] The largest accounts for the token.
181
435
  def get_token_largest_accounts(pubkey, options = {})
182
- request('getTokenLargestAccounts', [pubkey, options])
436
+ request_http('getTokenLargestAccounts', [pubkey, options])
183
437
  end
184
438
 
439
+ ##
440
+ # Retrieves the supply of a given token.
441
+ #
442
+ # @param [String] pubkey The public key of the token.
443
+ # @param [Hash] options Optional parameters for the request.
444
+ # @return [Hash] The token supply.
185
445
  def get_token_supply(pubkey, options = {})
186
- request('getTokenSupply', [pubkey, options])
446
+ request_http('getTokenSupply', [pubkey, options])
187
447
  end
188
448
 
449
+ ##
450
+ # Retrieves transaction details for a given signature.
451
+ #
452
+ # @param [String] signature The transaction signature.
453
+ # @param [Hash] options Optional parameters for the request.
454
+ # @return [Hash] The transaction details.
189
455
  def get_transaction(signature, options = {})
190
- request('getTransaction', [signature, options])
456
+ request_http('getTransaction', [signature, options])
191
457
  end
192
458
 
459
+ ##
460
+ # Retrieves the total number of transactions processed by the network.
461
+ #
462
+ # @param [Hash] options Optional parameters for the request.
463
+ # @return [Integer] The total number of transactions.
193
464
  def get_transaction_count(options = {})
194
- request('getTransactionCount', [options])
465
+ request_http('getTransactionCount', [options])
195
466
  end
196
467
 
197
- def get_version(options = {})
198
- request('getVersion', [options])
468
+ ##
469
+ # Retrieves the current version of the Solana software.
470
+ #
471
+ # @return [Hash] The current version information.
472
+ def get_version
473
+ request_http('getVersion')
199
474
  end
200
475
 
476
+ ##
477
+ # Retrieves the list of vote accounts.
478
+ #
479
+ # @param [Hash] options Optional parameters for the request.
480
+ # @return [Hash] The list of vote accounts.
201
481
  def get_vote_accounts(options = {})
202
- request('getVoteAccounts', [options])
482
+ request_http('getVoteAccounts', [options])
203
483
  end
204
484
 
485
+ ##
486
+ # Checks if a given blockhash is valid.
487
+ #
488
+ # @param [String] blockhash The blockhash to check.
489
+ # @param [Hash] options Optional parameters for the request.
490
+ # @return [Boolean] Whether the blockhash is valid.
205
491
  def is_blockhash_valid(blockhash, options = {})
206
- request('isBlockhashValid', [blockhash, options])
492
+ request_http('isBlockhashValid', [blockhash, options])
207
493
  end
208
494
 
495
+ ##
496
+ # Retrieves the minimum ledger slot.
497
+ #
498
+ # @param [Hash] options Optional parameters for the request.
499
+ # @return [Integer] The minimum ledger slot.
209
500
  def minimum_ledger_slot(options = {})
210
- request('minimumLedgerSlot', [options])
501
+ request_http('minimumLedgerSlot', [options])
211
502
  end
212
503
 
504
+ ##
505
+ # Requests an airdrop to a given public key.
506
+ #
507
+ # @param [String] pubkey The public key to receive the airdrop.
508
+ # @param [Integer] lamports The amount of lamports to airdrop.
509
+ # @param [Hash] options Optional parameters for the request.
510
+ # @return [Hash] The airdrop request response.
213
511
  def request_airdrop(pubkey, lamports, options = {})
214
- request('requestAirdrop', [pubkey, lamports, options])
512
+ request_http('requestAirdrop', [pubkey, lamports, options])
215
513
  end
216
514
 
217
- def send_transaction(transaction, options = {})
218
- request('sendTransaction', [transaction, options])
515
+ ##
516
+ # Sends a transaction.
517
+ #
518
+ # @param [Hash] transaction The transaction to send.
519
+ # @return [Hash] The response from the send transaction request.
520
+ def send_transaction(transaction)
521
+ request_http('sendTransaction', [transaction.to_json])
219
522
  end
220
523
 
524
+ ##
525
+ # Simulates a transaction.
526
+ #
527
+ # @param [Hash] transaction The transaction to simulate.
528
+ # @param [Hash] options Optional parameters for the request.
529
+ # @return [Hash] The simulation response.
221
530
  def simulate_transaction(transaction, options = {})
222
- request('simulateTransaction', [transaction, options])
223
- end
224
-
225
- private
226
-
227
- def request(method, params = [])
228
- options = {
229
- headers: { 'Content-Type' => 'application/json' },
230
- body: {
231
- jsonrpc: '2.0',
232
- method: method,
233
- params: params,
234
- id: 1
235
- }.to_json
531
+ request_http('simulateTransaction', [transaction.to_json, options])
532
+ end
533
+
534
+ ##
535
+ # Subscribes to account changes.
536
+ #
537
+ # @param [String] pubkey The public key of the account.
538
+ # @param [Hash] options Optional parameters for the subscription.
539
+ # @yield [Object] The response from the subscription.
540
+ def account_subscribe(pubkey, options = {}, &block)
541
+ request_ws('accountSubscribe', [pubkey, options], &block)
542
+ end
543
+
544
+ ##
545
+ # Unsubscribes from account changes.
546
+ #
547
+ # @param [Integer] subscription_id The subscription ID.
548
+ # @yield [Object] The response from the unsubscription.
549
+ def account_unsubscribe(subscription_id, &block)
550
+ request_ws('accountUnsubscribe', [subscription_id], &block)
551
+ end
552
+
553
+ ##
554
+ # Subscribes to new blocks.
555
+ #
556
+ # @param [Hash] options Optional parameters for the subscription.
557
+ # @yield [Object] The response from the subscription.
558
+ def block_subscribe(options = {}, &block)
559
+ request_ws('blockSubscribe', [options], &block)
560
+ end
561
+
562
+ ##
563
+ # Unsubscribes from new blocks.
564
+ #
565
+ # @param [Integer] subscription_id The subscription ID.
566
+ # @yield [Object] The response from the unsubscription.
567
+ def block_unsubscribe(subscription_id, &block)
568
+ request_ws('blockUnsubscribe', [subscription_id], &block)
569
+ end
570
+
571
+ ##
572
+ # Subscribes to log messages.
573
+ #
574
+ # @param [String, Hash] filter The filter for log messages (e.g., a public key or a set of options).
575
+ # @param [Hash] options Optional parameters for the subscription.
576
+ # @yield [Object] The response from the subscription.
577
+ def logs_subscribe(filter, options = {}, &block)
578
+ request_ws('logsSubscribe', [filter, options], &block)
579
+ end
580
+
581
+ ##
582
+ # Unsubscribes from log messages.
583
+ #
584
+ # @param [Integer] subscription_id The subscription ID.
585
+ # @yield [Object] The response from the unsubscription.
586
+ def logs_unsubscribe(subscription_id, &block)
587
+ request_ws('logsUnsubscribe', [subscription_id], &block)
588
+ end
589
+
590
+ ##
591
+ # Subscribes to program changes.
592
+ #
593
+ # @param [String] pubkey The public key of the program.
594
+ # @param [Hash] options Optional parameters for the subscription.
595
+ # @yield [Object] The response from the subscription.
596
+ def program_subscribe(pubkey, options = {}, &block)
597
+ request_ws('programSubscribe', [pubkey, options], &block)
598
+ end
599
+
600
+ ##
601
+ # Unsubscribes from program changes.
602
+ #
603
+ # @param [Integer] subscription_id The subscription ID.
604
+ # @yield [Object] The response from the unsubscription.
605
+ def program_unsubscribe(subscription_id, &block)
606
+ request_ws('programUnsubscribe', [subscription_id], &block)
607
+ end
608
+
609
+ ##
610
+ # Subscribes to root changes.
611
+ #
612
+ # @yield [Object] The response from the subscription.
613
+ def root_subscribe(&block)
614
+ request_ws('rootSubscribe', &block)
615
+ end
616
+
617
+ ##
618
+ # Unsubscribes from root changes.
619
+ #
620
+ # @param [Integer] subscription_id The subscription ID.
621
+ # @yield [Object] The response from the unsubscription.
622
+ def root_unsubscribe(subscription_id, &block)
623
+ request_ws('rootUnsubscribe', [subscription_id], &block)
624
+ end
625
+
626
+ ##
627
+ # Subscribes to signature status changes.
628
+ #
629
+ # @param [String] signature The signature to monitor.
630
+ # @param [Hash] options Optional parameters for the subscription.
631
+ # @yield [Object] The response from the subscription.
632
+ def signature_subscribe(signature, options = {}, &block)
633
+ request_ws('signatureSubscribe', [signature, options], &block)
634
+ end
635
+
636
+ ##
637
+ # Unsubscribes from signature status changes.
638
+ #
639
+ # @param [Integer] subscription_id The subscription ID.
640
+ # @yield [Object] The response from the unsubscription.
641
+ def signature_unsubscribe(subscription_id, &block)
642
+ request_ws('signatureUnsubscribe', [subscription_id], &block)
643
+ end
644
+
645
+ ##
646
+ # Subscribes to slot changes.
647
+ #
648
+ # @yield [Object] The response from the subscription.
649
+ def slot_subscribe(&block)
650
+ request_ws('slotSubscribe', &block)
651
+ end
652
+
653
+ ##
654
+ # Unsubscribes from slot changes.
655
+ #
656
+ # @param [Integer] subscription_id The subscription ID.
657
+ # @yield [Object] The response from the unsubscription.
658
+ def slot_unsubscribe(subscription_id, &block)
659
+ request_ws('slotUnsubscribe', [subscription_id], &block)
660
+ end
661
+
662
+ ##
663
+ # Subscribes to slot updates.
664
+ #
665
+ # @yield [Object] The response from the subscription.
666
+ def slots_updates_subscribe(&block)
667
+ request_ws('slotsUpdatesSubscribe', &block)
668
+ end
669
+
670
+ ##
671
+ # Unsubscribes from slot updates.
672
+ #
673
+ # @param [Integer] subscription_id The subscription ID.
674
+ # @yield [Object] The response from the unsubscription.
675
+ def slots_updates_unsubscribe(subscription_id, &block)
676
+ request_ws('slotsUpdatesUnsubscribe', [subscription_id], &block)
677
+ end
678
+
679
+ ##
680
+ # Subscribes to vote updates.
681
+ #
682
+ # @yield [Object] The response from the subscription.
683
+ def vote_subscribe(&block)
684
+ request_ws('voteSubscribe', &block)
685
+ end
686
+
687
+ ##
688
+ # Unsubscribes from vote updates.
689
+ #
690
+ # @param [Integer] subscription_id The subscription ID.
691
+ # @yield [Object] The response from the unsubscription.
692
+ def vote_unsubscribe(subscription_id, &block)
693
+ request_ws('voteUnsubscribe', [subscription_id], &block)
694
+ end
695
+
696
+ ##
697
+ # Sends a JSON-RPC request to the Solana API.
698
+ #
699
+ # @param [String] method The RPC method to call.
700
+ # @param [Array] params The parameters for the RPC method.
701
+ # @return [Object] The parsed response from the API.
702
+ def request_http(method, params = nil)
703
+ body = {
704
+ jsonrpc: '2.0',
705
+ method: method,
706
+ id: 1
236
707
  }
708
+ body[:params] = params if params
237
709
 
238
- response = self.class.post('/', options)
239
- handle_response(response)
710
+ response = @api_http.post do |req|
711
+ req.headers['Content-Type'] = 'application/json'
712
+ req.body = body.to_json
713
+ end
714
+
715
+ handle_response_http(response)
240
716
  end
241
717
 
242
- def handle_response(response)
718
+ ##
719
+ # Handles the API response, checking for success and parsing the result.
720
+ #
721
+ # @param [Faraday::Response] response The HTTP response object.
722
+ # @raise [RuntimeError] If the request fails (non-success response).
723
+ # @return [Object] The parsed result from the API response.
724
+ def handle_response_http(response)
243
725
  if response.success?
244
- response.parsed_response['result']
726
+ response.body['result']
245
727
  else
246
- raise "Request failed: #{response.code} #{response.message}"
728
+ raise "Request failed: #{response.status} #{response.reason_phrase}"
729
+ end
730
+ end
731
+
732
+ ##
733
+ # Sends a JSON-RPC request to the Solana API over WebSocket.
734
+ #
735
+ # @param [String] method The RPC method to call.
736
+ # @param [Array] params The parameters for the RPC method.
737
+ # @yield [Object] The parsed response from the API.
738
+
739
+ def request_ws(method, params = nil, &block)
740
+ EM.run do
741
+ ws = Faye::WebSocket::Client.new(@api_endpoint::WS)
742
+
743
+ ws.on :open do |event|
744
+ body = {
745
+ jsonrpc: '2.0',
746
+ method: method,
747
+ id: 1
748
+ }
749
+ body[:params] = params if params
750
+
751
+ ws.send(body.to_json)
752
+ end
753
+
754
+ ws.on :message do |event|
755
+ response = JSON.parse(event.data)
756
+ yield response['result'] if block_given?
757
+ ws.close
758
+ end
759
+
760
+ ws.on :close do |event|
761
+ ws = nil
762
+ EM.stop
763
+ end
764
+
765
+ ws.on :error do |event|
766
+ puts "WebSocket error: #{event.message}"
767
+ ws = nil
768
+ EM.stop
769
+ end
247
770
  end
248
771
  end
249
772
  end
@@ -0,0 +1,105 @@
1
+ require 'rbnacl'
2
+ require 'json'
3
+ require_relative 'utils'
4
+
5
+ module SolanaRB
6
+ ##
7
+ # The Keypair class represents a keypair for signing transactions on the Solana blockchain.
8
+ #
9
+ class Keypair
10
+ attr_reader :public_key, :secret_key
11
+
12
+ ##
13
+ # Initializes a new Keypair.
14
+ #
15
+ # If a +secret_key+ is provided, it must be 64 bytes long. The first 32 bytes are used as the signing key,
16
+ # and the public key is derived from it. If no +secret_key+ is provided, a new keypair is generated.
17
+ #
18
+ # Raises an error if the +secret_key+ is not 64 bytes long.
19
+ #
20
+ # @param [String, nil] secret_key The secret key to use for the keypair, in binary format (optional).
21
+ def initialize(secret_key = nil)
22
+ if secret_key
23
+ raise 'Bad secret key size' unless secret_key.bytesize == 64
24
+ @signing_key = RbNaCl::Signatures::Ed25519::SigningKey.new(secret_key[0, 32])
25
+ @public_key = @signing_key.verify_key.to_bytes
26
+ else
27
+ @signing_key = RbNaCl::Signatures::Ed25519::SigningKey.generate
28
+ @public_key = @signing_key.verify_key.to_bytes
29
+ end
30
+ @secret_key = @signing_key.to_bytes + @public_key
31
+ end
32
+
33
+ ##
34
+ # Generates a new Keypair.
35
+ #
36
+ # @return [Keypair] A new Keypair instance.
37
+ def self.generate
38
+ new
39
+ end
40
+
41
+ ##
42
+ # Creates a Keypair from a provided secret key.
43
+ #
44
+ # @param [String] secret_key The secret key in binary format.
45
+ # @return [Keypair] A new Keypair instance initialized with the provided secret key.
46
+ def self.from_secret_key(secret_key)
47
+ new(secret_key)
48
+ end
49
+
50
+ ##
51
+ # Saves the keypair to a JSON file.
52
+ #
53
+ # The public and secret keys are encoded in Base58 format before being saved.
54
+ #
55
+ # @param [String] file_path The path to the file where the keypair will be saved.
56
+ def save_to_json(file_path)
57
+ data = {
58
+ public_key: Utils::base58_encode(@public_key),
59
+ secret_key: Utils::base58_encode(@secret_key)
60
+ }
61
+ File.write(file_path, data.to_json)
62
+ end
63
+
64
+ ##
65
+ # Loads a keypair from a JSON file.
66
+ #
67
+ # The file must contain the public and secret keys in Base58 format. The method verifies the size of the secret key and
68
+ # checks that the derived public key matches the saved public key.
69
+ #
70
+ # Raises an error if the +secret_key+ is not 64 bytes long or if the derived public key does not match the saved public key.
71
+ #
72
+ # @param [String] file_path The path to the file from which the keypair will be loaded.
73
+ # @return [Keypair] The loaded keypair.
74
+ def self.load_from_json(file_path)
75
+ data = JSON.parse(File.read(file_path), symbolize_names: true)
76
+ secret_key = Utils::base58_decode(data[:secret_key])
77
+ public_key = Utils::base58_decode(data[:public_key])
78
+
79
+ raise 'Bad secret key size' unless secret_key.bytesize == 64
80
+
81
+ signing_key = RbNaCl::Signatures::Ed25519::SigningKey.new(secret_key[0, 32])
82
+ loaded_public_key = signing_key.verify_key.to_bytes
83
+
84
+ raise 'Provided secretKey is invalid' unless loaded_public_key == public_key
85
+
86
+ new(secret_key)
87
+ end
88
+
89
+ ##
90
+ # Returns the public key for this keypair in Base58 format.
91
+ #
92
+ # @return [String] The public key in Base58 format.
93
+ def public_key_base58
94
+ Utils::base58_encode(@public_key)
95
+ end
96
+
97
+ ##
98
+ # Returns the raw secret key for this keypair in Base58 format.
99
+ #
100
+ # @return [String] The secret key in Base58 format.
101
+ def secret_key_base58
102
+ Utils::base58_encode(@secret_key)
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,107 @@
1
+ require 'base58'
2
+ require 'base64'
3
+
4
+ module SolanaRB
5
+ ##
6
+ # The Utils module provides utility methods and constants for interacting with the Solana blockchain.
7
+ #
8
+ module Utils
9
+ ##
10
+ # The system program ID for Solana.
11
+ SYSTEM_PROGRAM_ID = '11111111111111111111111111111111'
12
+
13
+ ##
14
+ # The maximum packet data size for Solana transactions.
15
+ PACKET_DATA_SIZE = 1232
16
+
17
+ ##
18
+ # Endpoints for the mainnet.
19
+ module MAINNET
20
+ ##
21
+ # HTTP endpoint for the mainnet.
22
+ HTTP = 'https://api.mainnet-beta.solana.com'
23
+
24
+ ##
25
+ # WebSocket endpoint for the mainnet.
26
+ WS = 'wss://api.mainnet-beta.solana.com'
27
+ end
28
+
29
+ ##
30
+ # Endpoints for the testnet.
31
+ module TESTNET
32
+ ##
33
+ # HTTP endpoint for the testnet.
34
+ HTTP = 'https://api.testnet.solana.com'
35
+
36
+ ##
37
+ # WebSocket endpoint for the testnet.
38
+ WS = 'wss://api.testnet.solana.com'
39
+ end
40
+
41
+ ##
42
+ # Endpoints for the devnet.
43
+ module DEVNET
44
+ ##
45
+ # HTTP endpoint for the devnet.
46
+ HTTP = 'https://api.devnet.solana.com'
47
+
48
+ ##
49
+ # WebSocket endpoint for the devnet.
50
+ WS = 'wss://api.devnet.solana.com'
51
+ end
52
+
53
+ ##
54
+ # Instruction types for Solana transactions.
55
+ module InstructionType
56
+ CREATE_ACCOUNT = 0
57
+ ASSIGN = 1
58
+ TRANSFER = 2
59
+ CREATE_ACCOUNT_WITH_SEED = 3
60
+ ADVANCE_NONCE_ACCOUNT = 4
61
+ WITHDRAW_NONCE_ACCOUNT = 5
62
+ INITIALIZE_NONCE_ACCOUNT = 6
63
+ AUTHORIZE_NONCE_ACCOUNT = 7
64
+ ALLOCATE = 8
65
+ ALLOCATE_WITH_SEED = 9
66
+ ASSIGN_WITH_SEED = 10
67
+ TRANSFER_WITH_SEED = 11
68
+ end
69
+
70
+ ##
71
+ # Encodes a byte array into a Base58 string.
72
+ #
73
+ # @param [String] bytes The byte array to encode.
74
+ # @return [String] The Base58-encoded string.
75
+ def self.base58_encode(bytes)
76
+ Base58.binary_to_base58(bytes, :bitcoin)
77
+ end
78
+
79
+ ##
80
+ # Decodes a Base58 string into a byte array.
81
+ #
82
+ # @param [String] base58 The Base58 string to decode.
83
+ # @return [String] The decoded byte array.
84
+ def self.base58_decode(base58)
85
+ Base58.base58_to_binary(base58, :bitcoin)
86
+ end
87
+
88
+ ##
89
+ # Encodes a byte array into a Base64 string.
90
+ #
91
+ # @param [String] bytes The byte array to encode.
92
+ # @return [String] The Base64-encoded string.
93
+ def self.base64_encode(bytes)
94
+ Base64.strict_encode64(bytes)
95
+ end
96
+
97
+ ##
98
+ # Decodes a Base64 string into a byte array.
99
+ #
100
+ # @param [String] base64 The Base64 string to decode.
101
+ # @return [String] The decoded byte array.
102
+ def self.base64_decode(base64)
103
+ Base64.strict_decode64(base64)
104
+ end
105
+ end
106
+ Utils.freeze
107
+ end
@@ -1,3 +1,3 @@
1
1
  module SolanaRB
2
- VERSION = '0.1.0'.freeze
3
- end
2
+ VERSION = '0.1.1'.freeze
3
+ end
data/lib/solana-ruby.rb CHANGED
@@ -1,5 +1,7 @@
1
- require_relative 'solana-ruby/version'
2
1
  require_relative 'solana-ruby/client'
2
+ require_relative 'solana-ruby/keypair'
3
+ require_relative 'solana-ruby/utils'
4
+ require_relative 'solana-ruby/version'
3
5
 
4
6
  module SolanaRB
5
7
  end
metadata CHANGED
@@ -1,29 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: solana-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Fabrice Renard
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-06-23 00:00:00.000000000 Z
11
+ date: 2024-06-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: httparty
14
+ name: faraday
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 0.18.0
19
+ version: 2.9.2
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 0.18.0
26
+ version: 2.9.2
27
+ - !ruby/object:Gem::Dependency
28
+ name: faye-websocket
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 1.2.10
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 1.2.10
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: csv
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -38,6 +52,76 @@ dependencies:
38
52
  - - "~>"
39
53
  - !ruby/object:Gem::Version
40
54
  version: '3.1'
55
+ - !ruby/object:Gem::Dependency
56
+ name: ed25519
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.3'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.3'
69
+ - !ruby/object:Gem::Dependency
70
+ name: base58
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 0.2.3
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 0.2.3
83
+ - !ruby/object:Gem::Dependency
84
+ name: base64
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 0.2.0
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 0.2.0
97
+ - !ruby/object:Gem::Dependency
98
+ name: rdoc
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: 6.7.0
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: 6.7.0
111
+ - !ruby/object:Gem::Dependency
112
+ name: rqrcode
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '2.0'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '2.0'
41
125
  - !ruby/object:Gem::Dependency
42
126
  name: rspec
43
127
  requirement: !ruby/object:Gem::Requirement
@@ -75,11 +159,14 @@ extra_rdoc_files: []
75
159
  files:
76
160
  - lib/solana-ruby.rb
77
161
  - lib/solana-ruby/client.rb
162
+ - lib/solana-ruby/keypair.rb
163
+ - lib/solana-ruby/utils.rb
78
164
  - lib/solana-ruby/version.rb
79
165
  homepage: https://github.com/fabricerenard12/solana-ruby
80
166
  licenses:
81
167
  - MIT
82
- metadata: {}
168
+ metadata:
169
+ homepage_uri: https://github.com/fabricerenard12/solana-ruby
83
170
  post_install_message:
84
171
  rdoc_options: []
85
172
  require_paths:
@@ -98,5 +185,5 @@ requirements: []
98
185
  rubygems_version: 3.5.9
99
186
  signing_key:
100
187
  specification_version: 4
101
- summary: A Ruby wrapper for the Solana blockchain API
188
+ summary: A Ruby SDK for the Solana blockchain API
102
189
  test_files: []