solana-ruby-web3js 2.1.5 → 2.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3022773f90f2e77d77ba86ab5a6e97d5d4420895ae981c74d57c6bceab87ad86
4
- data.tar.gz: e42e19e6ac071cf7774d601c7b4807beba88e8fcc84d54718ae4d58c6846afdc
3
+ metadata.gz: d2808f06359bc53bf28e0b37def2f3121ec06cd2bfbd395c7dc4d76fadafbb5d
4
+ data.tar.gz: ccf0936cc418819993e11c8e1d8f2560e347dcbe6f04619cd35fdda2bfcff87a
5
5
  SHA512:
6
- metadata.gz: 64ca7a6a80bb656f421fbe95b8590f33f0428b8b1d85abf2b9bd521764b15da424a3dec4859df0cd3ef8f700ef48493204d746d2de658e7dfbd143487e11ecc2
7
- data.tar.gz: dc0d28baf4b451798c379a01a8931e7033ccf9ce99b291d4619572469a620ec572f988467c833613d654f709a03ba1310d21254f3472b665333ffc40359df651
6
+ metadata.gz: 117640ecc3f311f9a934c21b02e406fea8a2d374cb1a63259932a228517aaa5ac23877462bc978253babd944deb3a9f0bcf429e6f5f172f5d7850380b4bd2056
7
+ data.tar.gz: dea3c75aff80061569d54e9a14b82f424fdcdf8d50f60da38756e79addcebb110953fd4312a99d99e9cb87aa0c47f479c7841b57d24140c7d13feacec5dc9744
data/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## 2.1.6 – 2026-02-24
4
+
5
+ ### Fixed
6
+
7
+ - Fixed Ed25519 public key curve validation:
8
+ - Clear x-sign bit correctly
9
+ - Interpret y-coordinate as little-endian
10
+ - Fixed PDA / ATA derivation mismatches caused by incorrect seed hashing
11
+ - Resolves invalid Associated Token Address generation (issue #13)
12
+
13
+ This release fixes cases where previously generated ATAs could differ
14
+ from on-chain derivation and fail with:
15
+ "Provided seeds do not result in a valid address"
16
+
3
17
  ## [0.1.0] - 2024-07-31
4
18
 
5
19
  - Initial release
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- solana-ruby-web3js (2.1.3)
4
+ solana-ruby-web3js (2.1.5)
5
5
  activesupport
6
6
  base58 (~> 0.2.3)
7
7
  base64 (~> 0.2.0)
data/README.md CHANGED
@@ -22,40 +22,46 @@ Or install it yourself as:
22
22
 
23
23
  To start using the Solana RPC client, initialize it with or without the RPC URL. The default URL points to the Solana Mainnet. If you wish to connect to another network like Devnet or Testnet, you can specify the URL.
24
24
 
25
- require 'solana_ruby'
25
+ ```ruby
26
+ require 'solana_ruby'
26
27
 
27
- # Initialize the client (defaults to Mainnet(https://api.mainnet-beta.solana.com))
28
- client = SolanaRuby::HttpClient.new()
28
+ # Initialize the client (defaults to Mainnet(https://api.mainnet-beta.solana.com))
29
+ client = SolanaRuby::HttpClient.new()
29
30
 
30
- # Optionally, provide a custom RPC URL
31
- # client = SolanaRuby::HttpClient.new("https://api.devnet.solana.com")
31
+ # Optionally, provide a custom RPC URL
32
+ # client = SolanaRuby::HttpClient.new("https://api.devnet.solana.com")
33
+ ```
32
34
 
33
35
  ### Fetch Solana Account Balance
34
36
 
35
37
  Once the client is initialized, you can make API calls to the Solana network. For example, to get the solana balance of a given account:
36
38
 
37
- # Replace 'pubkey' with the actual public key of the solana account
39
+ ```ruby
40
+ # Replace 'pubkey' with the actual public key of the solana account
38
41
 
39
- pubkey = 'Fg6PaFpoGXkYsidMpWxTWqSKJf6KJkUxX92cnv7WMd2J'
42
+ pubkey = 'Fg6PaFpoGXkYsidMpWxTWqSKJf6KJkUxX92cnv7WMd2J'
40
43
 
41
- result = client.get_balance(pubkey)
44
+ result = client.get_balance(pubkey)
42
45
 
43
- puts result
46
+ puts result
47
+ ```
44
48
 
45
49
  ### Fetch Parsed Account Info
46
50
 
47
- # Replace 'pubkey' with the actual public key of the account
48
- pubkey = 'Fg6PaFpoGXkYsidMpWxTWqSKJf6KJkUxX92cnv7WMd2J'
51
+ ```ruby
52
+ # Replace 'pubkey' with the actual public key of the account
53
+ pubkey = 'Fg6PaFpoGXkYsidMpWxTWqSKJf6KJkUxX92cnv7WMd2J'
49
54
 
50
- # Example of options that can be passed:
51
- options = {
52
- commitment: 'finalized', # Specifies the level of commitment for querying state (e.g., 'finalized', 'confirmed', 'processed')
53
- encoding: 'jsonParsed' # Specifies the encoding format (e.g., 'jsonParsed', 'base64', etc.)
54
- }
55
+ # Example of options that can be passed:
56
+ options = {
57
+ commitment: 'finalized', # Specifies the level of commitment for querying state (e.g., 'finalized', 'confirmed', 'processed')
58
+ encoding: 'jsonParsed' # Specifies the encoding format (e.g., 'jsonParsed', 'base64', etc.)
59
+ }
55
60
 
56
- result = client.get_parsed_account_info(pubkey, options)
61
+ result = client.get_parsed_account_info(pubkey, options)
57
62
 
58
- puts result
63
+ puts result
64
+ ```
59
65
 
60
66
  ### More Information on Solana Methods
61
67
 
@@ -71,15 +77,15 @@ The options parameter is a hash that can include the following fields and more,
71
77
 
72
78
  - **commitment**: Specifies the level of commitment desired when querying state. Options include:
73
79
 
74
- - 'finalized': Query the most recent block confirmed by supermajority of the cluster.
75
- - 'confirmed': Query the most recent block that has been voted on by supermajority of the cluster.
76
- - 'processed': Query the most recent block regardless of cluster voting.
80
+ - 'finalized': Query the most recent block confirmed by supermajority of the cluster.
81
+ - 'confirmed': Query the most recent block that has been voted on by supermajority of the cluster.
82
+ - 'processed': Query the most recent block regardless of cluster voting.
77
83
 
78
84
  - **encoding**: Defines the format of the returned account data. Possible values include:
79
85
 
80
- - 'jsonParsed': Returns data in a JSON-parsed format.
81
- - 'base64': Returns raw account data in Base64 encoding.
82
- - 'base64+zstd': Returns compressed Base64 data.
86
+ - 'jsonParsed': Returns data in a JSON-parsed format.
87
+ - 'base64': Returns raw account data in Base64 encoding.
88
+ - 'base64+zstd': Returns compressed Base64 data.
83
89
 
84
90
  - **epoch**: Specify the epoch when querying for certain information like epoch details.
85
91
 
@@ -97,15 +103,17 @@ The filters parameter allows you to specify conditions when querying accounts an
97
103
 
98
104
  #### Token Accounts by Owner
99
105
 
100
- # Replace 'owner_pubkey' with the owner's public key
101
- owner_pubkey = 'Fg6PaFpoGXkYsidMpWxTWqSKJf6KJkUxX92cnv7WMd2J'
102
-
103
- # Query for token accounts owned by this public key
104
- filters = [{ mint: 'TokenMintPublicKey' }]
105
-
106
- result = client.get_token_accounts_by_owner(owner_pubkey, filters)
107
-
108
- puts result
106
+ ```ruby
107
+ # Replace 'owner_pubkey' with the owner's public key
108
+ owner_pubkey = 'Fg6PaFpoGXkYsidMpWxTWqSKJf6KJkUxX92cnv7WMd2J'
109
+
110
+ # Query for token accounts owned by this public key
111
+ filters = [{ mint: 'TokenMintPublicKey' }]
112
+
113
+ result = client.get_token_accounts_by_owner(owner_pubkey, filters)
114
+
115
+ puts result
116
+ ```
109
117
 
110
118
  #### Account Filters
111
119
 
@@ -115,101 +123,110 @@ You can use the filters parameter to apply conditions for certain queries, such
115
123
 
116
124
  - Filter accounts by a specific token mint.
117
125
 
118
- ``filters = [{ mint: 'TokenMintPublicKey' }]``
126
+ ```ruby
127
+ filters = [{ mint: 'TokenMintPublicKey' }]
119
128
 
120
- ``result = client.get_token_accounts_by_owner(owner_pubkey, filters)``
129
+ result = client.get_token_accounts_by_owner(owner_pubkey, filters)
130
+ ```
121
131
 
122
132
  #### Program Filter
123
133
 
124
134
  - Filter accounts associated with a particular program, such as the token program.
125
135
 
126
- ``filters = [{ programId: 'TokenProgramPublicKey' }]``
136
+ ```ruby
137
+ filters = [{ programId: 'TokenProgramPublicKey' }]
127
138
 
128
- ``result = client.get_token_accounts_by_owner(owner_pubkey, filters)``
139
+ result = client.get_token_accounts_by_owner(owner_pubkey, filters)
140
+ ```
129
141
 
130
142
  #### Data Size Filter
131
143
 
132
144
  - Filter accounts by the exact size of the account data.
133
145
 
134
- ``filters = [{ dataSize: 165 }]``
146
+ ```ruby
147
+ filters = [{ dataSize: 165 }]
135
148
 
136
- ``result = client.get_program_accounts('ProgramPublicKey', filters)``
149
+ result = client.get_program_accounts('ProgramPublicKey', filters)
150
+ ```
137
151
 
138
152
  #### Memcmp Filter
139
153
 
140
154
  - Filter by matching a specific slice of bytes at a given offset in account data.
141
155
 
142
- ``filters = [{
143
- memcmp: {
144
- offset: 0,
145
- bytes: 'Base58EncodedBytes'
146
- }
147
- }]``
148
-
149
- ``result = client.get_program_accounts('ProgramPublicKey', filters)``
156
+ ```ruby
157
+ filters = [{
158
+ memcmp: {
159
+ offset: 0,
160
+ bytes: 'Base58EncodedBytes'
161
+ }
162
+ }]
163
+
164
+ result = client.get_program_accounts('ProgramPublicKey', filters)
165
+ ```
150
166
 
151
167
  ## WebSocket Methods
152
168
 
153
169
  The SolanaRuby gem also provides WebSocket methods to handle real-time notifications and updates from the Solana blockchain. To use the WebSocket client:
154
170
 
155
- # Initialize the WebSocket client
156
- ws_client = SolanaRuby::WebSocketClient.new("wss://api.mainnet-beta.solana.com")
171
+ ```ruby
172
+ # Initialize the WebSocket client
173
+ ws_client = SolanaRuby::WebSocketClient.new("wss://api.mainnet-beta.solana.com")
157
174
 
158
- # Subscribe to slot change notifications
159
- subscription_id = ws_client.on_slot_change do |slot_info|
160
- puts "Slot changed: #{slot_info}"
161
- end
175
+ # Subscribe to slot change notifications
176
+ subscription_id = ws_client.on_slot_change do |slot_info|
177
+ puts "Slot changed: #{slot_info}"
178
+ end
162
179
 
163
- # Sleep to hold the process and show updates
164
- sleep 60 # Adjust the duration as needed to view updates
180
+ # Sleep to hold the process and show updates
181
+ sleep 60 # Adjust the duration as needed to view updates
165
182
 
166
- # Unsubscribe from slot change notifications
167
- ws_client.remove_slot_change_listener(subscription_id)
168
- puts "Unsubscribed from slot change notifications."
183
+ # Unsubscribe from slot change notifications
184
+ ws_client.remove_slot_change_listener(subscription_id)
185
+ puts "Unsubscribed from slot change notifications."
186
+ ```
169
187
 
170
188
  The following methods are supported by the WebSocketClient:
171
189
 
172
190
  - **Account Change**: Subscribe to changes in an account's state.
173
191
 
174
- ```ws_client.on_account_change(pubkey) { |account_info| puts account_info }```
192
+ `ws_client.on_account_change(pubkey) { |account_info| puts account_info }`
175
193
 
176
194
  - **Program Account Change**: Subscribe to changes in accounts owned by a specific program.
177
195
 
178
- ```ws_client.on_program_account_change(program_id, filters) { |program_account_info| puts program_account_info }```
196
+ `ws_client.on_program_account_change(program_id, filters) { |program_account_info| puts program_account_info }`
179
197
 
180
198
  - **Logs**: Subscribe to transaction logs.
181
199
 
182
- ```ws_client.on_logs { |logs_info| puts logs_info }```
200
+ `ws_client.on_logs { |logs_info| puts logs_info }`
183
201
 
184
202
  - **Logs for a Specific Account**: Subscribe to logs related to a specific account.
185
203
 
186
- ```ws_client.on_logs_for_account(account_pubkey) { |logs_info| puts logs_info }```
204
+ `ws_client.on_logs_for_account(account_pubkey) { |logs_info| puts logs_info }`
187
205
 
188
206
  - **Logs for a Specific Program**: Subscribe to logs related to a specific program.
189
207
 
190
- ```ws_client.on_logs_for_program(program_id) { |logs_info| puts logs_info }```
208
+ `ws_client.on_logs_for_program(program_id) { |logs_info| puts logs_info }`
191
209
 
192
210
  - **Root Change**: Subscribe to root changes.
193
211
 
194
- ws_client.on_root_change { |root_info| puts root_info }
212
+ ws_client.on_root_change { |root_info| puts root_info }
195
213
 
196
214
  - **Signature**: Subscribe to a signature notification.
197
215
 
198
- ```ws_client.on_signature(signature) { |signature_info| puts signature_info }```
216
+ `ws_client.on_signature(signature) { |signature_info| puts signature_info }`
199
217
 
200
218
  - **Slot Change**: Subscribe to slot changes.
201
219
 
202
- ```ws_client.on_slot_change { |slot_info| puts slot_info }```
220
+ `ws_client.on_slot_change { |slot_info| puts slot_info }`
203
221
 
204
222
  - **Unsubscribe Methods**: Each WebSocket method has a corresponding unsubscribe method:
205
223
 
206
- - remove_account_change_listener(subscription_id)
207
- - remove_program_account_listener(subscription_id)
208
- - remove_logs_listener(subscription_id)
209
- - remove_root_listener(subscription_id)
210
- - remove_signature_listener(subscription_id)
211
- - remove_slot_change_listener(subscription_id)
212
-
224
+ - remove_account_change_listener(subscription_id)
225
+ - remove_program_account_listener(subscription_id)
226
+ - remove_logs_listener(subscription_id)
227
+ - remove_root_listener(subscription_id)
228
+ - remove_signature_listener(subscription_id)
229
+ - remove_slot_change_listener(subscription_id)
213
230
 
214
231
  ## Complete List of Available Methods
215
232
 
@@ -218,6 +235,7 @@ The following methods are supported by the WebSocketClient:
218
235
  The following methods are supported by the SolanaRuby::HttpClient:
219
236
 
220
237
  #### Basic
238
+
221
239
  get_balance(pubkey)
222
240
  get_balance_and_context(pubkey)
223
241
  get_slot()
@@ -240,6 +258,7 @@ The following methods are supported by the SolanaRuby::HttpClient:
240
258
  get_recent_prioritization_fees(addresses)
241
259
 
242
260
  #### Account
261
+
243
262
  get_account_info(pubkey)
244
263
  get_parsed_account_info(pubkey, options)
245
264
  get_account_info_and_context(pubkey, options)
@@ -255,6 +274,7 @@ The following methods are supported by the SolanaRuby::HttpClient:
255
274
  get_nonce(pubkey)
256
275
 
257
276
  #### Block
277
+
258
278
  get_nonce(pubkey)
259
279
  get_block(slot, options)
260
280
  get_block_production()
@@ -270,20 +290,24 @@ The following methods are supported by the SolanaRuby::HttpClient:
270
290
  get_block_commitment(block_slot)
271
291
 
272
292
  #### Blockhash
293
+
273
294
  get_latest_blockhash()
274
295
  get_latest_blockhash()
275
296
  get_fee_for_message(blockhash, options)
276
297
  is_blockhash_valid?(blockhash, options)
277
298
 
278
299
  #### Lookup Table
300
+
279
301
  get_address_lookup_table(pubkey)
280
302
 
281
303
  #### Signature
304
+
282
305
  get_signature_statuses(signatures)
283
306
  get_signature_status(signature, options)
284
307
  get_signatures_for_address(address, options)
285
308
 
286
309
  #### Slot
310
+
287
311
  get_slot()
288
312
  get_slot_leader(options)
289
313
  get_slot_leaders(start_slot, limit)
@@ -293,12 +317,14 @@ The following methods are supported by the SolanaRuby::HttpClient:
293
317
  get_max_shred_insert_slot()
294
318
 
295
319
  #### Token
320
+
296
321
  get_token_balance(pubkey, options)
297
322
  get_token_supply(pubkey)
298
323
  get_token_accounts_by_owner(owner_pubkey, filters, options)
299
324
  get_token_largest_accounts(mint_pubkey, options)
300
325
 
301
326
  #### Transaction
327
+
302
328
  send_transaction(signed_transaction, options)
303
329
  confirm_transaction(signature, commitment, timeout)
304
330
  get_transaction(signature, options)
@@ -347,62 +373,64 @@ To transfer SOL (the native cryptocurrency of the Solana blockchain) from one ac
347
373
 
348
374
  #### Example Usage:
349
375
 
350
- require 'solana_ruby'
351
-
352
- # Initialize the client (defaults to Mainnet(https://api.mainnet-beta.solana.com))
353
- client = SolanaRuby::HttpClient.new('https://api.devnet.solana.com')
354
-
355
- # Fetch the recent blockhash
356
- recent_blockhash = client.get_latest_blockhash["blockhash"]
357
-
358
- # Generate or fetch the sender's keypair
359
- # Option 1: Generate a new keypair
360
- sender_keypair = SolanaRuby::Keypair.generate
361
- # Option 2: Use an existing private key
362
- # sender_keypair = SolanaRuby::Keypair.from_private_key("InsertPrivateKeyHere")
363
-
364
- sender_pubkey = sender_keypair[:public_key]
365
-
366
-
367
- # Airdrop some lamports to the sender's account when needed.
368
- lamports = 10 * 1_000_000_000
369
- sleep(1)
370
- result = client.request_airdrop(sender_pubkey, lamports)
371
- puts "Solana Balance #{lamports} lamports added sucessfully for the public key: #{sender_pubkey}"
372
- sleep(10)
373
-
374
-
375
- # Generate or use an existing receiver's public key
376
- # Option 1: Generate a new keypair for the receiver
377
- receiver_keypair = SolanaRuby::Keypair.generate
378
- receiver_pubkey = receiver_keypair[:public_key]
379
- # Option 2: Use an existing public key
380
- # receiver_pubkey = 'InsertExistingPublicKeyHere'
381
-
382
- transfer_lamports = 1 * 1_000_000
383
- puts "Payer's full private key: #{sender_keypair[:full_private_key]}"
384
- puts "Receiver's full private key: #{receiver_keypair[:full_private_key]}"
385
- puts "Receiver's Public Key: #{receiver_keypair[:public_key]}"
386
-
387
- # Create a new transaction
388
- transaction = SolanaRuby::TransactionHelper.sol_transfer(
389
- sender_pubkey,
390
- receiver_pubkey,
391
- transfer_lamports,
392
- recent_blockhash
393
- )
394
-
395
- # Get the sender's private key (ensure it's a string)
396
- private_key = sender_keypair[:private_key]
397
- puts "Private key type: #{private_key.class}, Value: #{private_key.inspect}"
398
-
399
- # Sign the transaction
400
- signed_transaction = transaction.sign([sender_keypair])
401
-
402
- # Send the transaction to the Solana network
403
- sleep(5)
404
- response = client.send_transaction(transaction.to_base64, { encoding: 'base64' })
405
- puts "Response: #{response}"
376
+ ```ruby
377
+ require 'solana_ruby'
378
+
379
+ # Initialize the client (defaults to Mainnet(https://api.mainnet-beta.solana.com))
380
+ client = SolanaRuby::HttpClient.new('https://api.devnet.solana.com')
381
+
382
+ # Fetch the recent blockhash
383
+ recent_blockhash = client.get_latest_blockhash["blockhash"]
384
+
385
+ # Generate or fetch the sender's keypair
386
+ # Option 1: Generate a new keypair
387
+ sender_keypair = SolanaRuby::Keypair.generate
388
+ # Option 2: Use an existing private key
389
+ # sender_keypair = SolanaRuby::Keypair.from_private_key("InsertPrivateKeyHere")
390
+
391
+ sender_pubkey = sender_keypair[:public_key]
392
+
393
+
394
+ # Airdrop some lamports to the sender's account when needed.
395
+ lamports = 10 * 1_000_000_000
396
+ sleep(1)
397
+ result = client.request_airdrop(sender_pubkey, lamports)
398
+ puts "Solana Balance #{lamports} lamports added sucessfully for the public key: #{sender_pubkey}"
399
+ sleep(10)
400
+
401
+
402
+ # Generate or use an existing receiver's public key
403
+ # Option 1: Generate a new keypair for the receiver
404
+ receiver_keypair = SolanaRuby::Keypair.generate
405
+ receiver_pubkey = receiver_keypair[:public_key]
406
+ # Option 2: Use an existing public key
407
+ # receiver_pubkey = 'InsertExistingPublicKeyHere'
408
+
409
+ transfer_lamports = 1 * 1_000_000
410
+ puts "Payer's full private key: #{sender_keypair[:full_private_key]}"
411
+ puts "Receiver's full private key: #{receiver_keypair[:full_private_key]}"
412
+ puts "Receiver's Public Key: #{receiver_keypair[:public_key]}"
413
+
414
+ # Create a new transaction
415
+ transaction = SolanaRuby::TransactionHelper.sol_transfer(
416
+ sender_pubkey,
417
+ receiver_pubkey,
418
+ transfer_lamports,
419
+ recent_blockhash
420
+ )
421
+
422
+ # Get the sender's private key (ensure it's a string)
423
+ private_key = sender_keypair[:private_key]
424
+ puts "Private key type: #{private_key.class}, Value: #{private_key.inspect}"
425
+
426
+ # Sign the transaction
427
+ signed_transaction = transaction.sign([sender_keypair])
428
+
429
+ # Send the transaction to the Solana network
430
+ sleep(5)
431
+ response = client.send_transaction(transaction.to_base64, { encoding: 'base64' })
432
+ puts "Response: #{response}"
433
+ ```
406
434
 
407
435
  ### Account Creation
408
436
 
@@ -419,49 +447,51 @@ The create_account helper allows creating a new account with specified parameter
419
447
 
420
448
  #### Example Usage:
421
449
 
422
- require 'solana_ruby'
423
-
424
- # Initialize the client (defaults to Mainnet(https://api.mainnet-beta.solana.com))
425
- client = SolanaRuby::HttpClient.new('https://api.devnet.solana.com')
426
-
427
- # Fetch the recent blockhash
428
- recent_blockhash = client.get_latest_blockhash["blockhash"]
429
-
430
- # Generate or fetch the sender/payer keypair
431
- # Option 1: Generate a new keypair
432
- sender_keypair = SolanaRuby::Keypair.generate
433
- # Option 2: Use an existing private key
434
- # sender_keypair = SolanaRuby::Keypair.from_private_key("InsertPrivateKeyHere")
435
- sender_pubkey = sender_keypair[:public_key]
436
-
437
- # Generate new account keypair
438
- new_account = SolanaRuby::Keypair.generate
439
- new_account_pubkey = new_account[:public_key]
440
-
441
- # Parameters for account creation
442
- lamports = 1_000_000_000
443
- space = 165
444
- program_id = SolanaRuby::TransactionHelper::SYSTEM_PROGRAM_ID
445
-
446
- # Create the account creation transaction
447
- transaction = SolanaRuby::TransactionHelper.create_account(
448
- sender_pubkey,
449
- new_account_pubkey,
450
- lamports,
451
- space,
452
- recent_blockhash,
453
- program_id
454
- )
455
-
456
- # Sign with both keypairs
457
- transaction.sign([sender_keypair, new_account])
458
-
459
- # Send the transaction
460
- response = client.send_transaction(transaction.to_base64, { encoding: 'base64' })
461
-
462
- # Output transaction results
463
- puts "Transaction Signature: #{response}"
464
- puts "New account created with Public Key: #{new_account_pubkey}"
450
+ ```ruby
451
+ require 'solana_ruby'
452
+
453
+ # Initialize the client (defaults to Mainnet(https://api.mainnet-beta.solana.com))
454
+ client = SolanaRuby::HttpClient.new('https://api.devnet.solana.com')
455
+
456
+ # Fetch the recent blockhash
457
+ recent_blockhash = client.get_latest_blockhash["blockhash"]
458
+
459
+ # Generate or fetch the sender/payer keypair
460
+ # Option 1: Generate a new keypair
461
+ sender_keypair = SolanaRuby::Keypair.generate
462
+ # Option 2: Use an existing private key
463
+ # sender_keypair = SolanaRuby::Keypair.from_private_key("InsertPrivateKeyHere")
464
+ sender_pubkey = sender_keypair[:public_key]
465
+
466
+ # Generate new account keypair
467
+ new_account = SolanaRuby::Keypair.generate
468
+ new_account_pubkey = new_account[:public_key]
469
+
470
+ # Parameters for account creation
471
+ lamports = 1_000_000_000
472
+ space = 165
473
+ program_id = SolanaRuby::TransactionHelper::SYSTEM_PROGRAM_ID
474
+
475
+ # Create the account creation transaction
476
+ transaction = SolanaRuby::TransactionHelper.create_account(
477
+ sender_pubkey,
478
+ new_account_pubkey,
479
+ lamports,
480
+ space,
481
+ recent_blockhash,
482
+ program_id
483
+ )
484
+
485
+ # Sign with both keypairs
486
+ transaction.sign([sender_keypair, new_account])
487
+
488
+ # Send the transaction
489
+ response = client.send_transaction(transaction.to_base64, { encoding: 'base64' })
490
+
491
+ # Output transaction results
492
+ puts "Transaction Signature: #{response}"
493
+ puts "New account created with Public Key: #{new_account_pubkey}"
494
+ ```
465
495
 
466
496
  ### SPL Token Account Creation
467
497
 
@@ -476,44 +506,46 @@ The create_associated_token_account helper allows you to create an associated to
476
506
 
477
507
  #### Example Usage:
478
508
 
479
- require 'solana_ruby'
509
+ ```ruby
510
+ require 'solana_ruby'
480
511
 
481
- # Initialize the Solana client (defaults to Mainnet: https://api.mainnet-beta.solana.com)
482
- client = SolanaRuby::HttpClient.new('https://api.devnet.solana.com')
512
+ # Initialize the Solana client (defaults to Mainnet: https://api.mainnet-beta.solana.com)
513
+ client = SolanaRuby::HttpClient.new('https://api.devnet.solana.com')
483
514
 
484
- # Fetch the recent blockhash
485
- recent_blockhash = client.get_latest_blockhash["blockhash"]
515
+ # Fetch the recent blockhash
516
+ recent_blockhash = client.get_latest_blockhash["blockhash"]
486
517
 
487
- # Load the keypair for the payer
488
- payer_keypair = SolanaRuby::Keypair.load_keypair('InsertYourJsonFilePathHere')
489
- payer_pubkey = payer_keypair.public_key
518
+ # Load the keypair for the payer
519
+ payer_keypair = SolanaRuby::Keypair.load_keypair('InsertYourJsonFilePathHere')
520
+ payer_pubkey = payer_keypair.public_key
490
521
 
491
- # Generate or load the owner keypair
492
- owner_keypair = SolanaRuby::Keypair.generate
493
- owner_pubkey = owner_keypair.public_key
522
+ # Generate or load the owner keypair
523
+ owner_keypair = SolanaRuby::Keypair.generate
524
+ owner_pubkey = owner_keypair.public_key
494
525
 
495
- puts "Owner Public Key: #{owner_pubkey}"
496
- puts "Owner Private Key: #{owner_keypair.private_key}"
526
+ puts "Owner Public Key: #{owner_pubkey}"
527
+ puts "Owner Private Key: #{owner_keypair.private_key}"
497
528
 
498
- # Define the mint public key for the SPL token
499
- mint_pubkey = "InsertMintPublicKeyHere"
529
+ # Define the mint public key for the SPL token
530
+ mint_pubkey = "InsertMintPublicKeyHere"
500
531
 
501
- # Create the associated token account transaction
502
- transaction = SolanaRuby::TransactionHelper.create_associated_token_account(
503
- payer_pubkey,
504
- mint_pubkey,
505
- owner_pubkey,
506
- recent_blockhash
507
- )
532
+ # Create the associated token account transaction
533
+ transaction = SolanaRuby::TransactionHelper.create_associated_token_account(
534
+ payer_pubkey,
535
+ mint_pubkey,
536
+ owner_pubkey,
537
+ recent_blockhash
538
+ )
508
539
 
509
- # Sign the transaction
510
- transaction.sign([payer_keypair])
540
+ # Sign the transaction
541
+ transaction.sign([payer_keypair])
511
542
 
512
- # Send the transaction
513
- response = client.send_transaction(transaction.to_base64, { encoding: 'base64' })
543
+ # Send the transaction
544
+ response = client.send_transaction(transaction.to_base64, { encoding: 'base64' })
514
545
 
515
- # Output transaction results
516
- puts "Transaction Signature: #{response}"
546
+ # Output transaction results
547
+ puts "Transaction Signature: #{response}"
548
+ ```
517
549
 
518
550
  ### Close Account
519
551
 
@@ -530,51 +562,53 @@ The close_account helper allows you to close an associated token account on the
530
562
 
531
563
  #### Example Usage:
532
564
 
533
- require 'solana_ruby'
565
+ ```ruby
566
+ require 'solana_ruby'
534
567
 
535
- # Initialize the Solana client (defaults to Mainnet: https://api.mainnet-beta.solana.com)
536
- client = SolanaRuby::HttpClient.new('https://api.devnet.solana.com')
568
+ # Initialize the Solana client (defaults to Mainnet: https://api.mainnet-beta.solana.com)
569
+ client = SolanaRuby::HttpClient.new('https://api.devnet.solana.com')
537
570
 
538
- # Fetch the recent blockhash
539
- recent_blockhash = client.get_latest_blockhash["blockhash"]
571
+ # Fetch the recent blockhash
572
+ recent_blockhash = client.get_latest_blockhash["blockhash"]
540
573
 
541
- # Load the keypairs
542
- payer_keypair = SolanaRuby::Keypair.from_private_key("InsertPayerPrivateKeyHere")
543
- owner_keypair = SolanaRuby::Keypair.from_private_key("InsertOwnerPrivateKeyHere")
574
+ # Load the keypairs
575
+ payer_keypair = SolanaRuby::Keypair.from_private_key("InsertPayerPrivateKeyHere")
576
+ owner_keypair = SolanaRuby::Keypair.from_private_key("InsertOwnerPrivateKeyHere")
544
577
 
545
- payer_pubkey = payer_keypair[:public_key]
546
- owner_pubkey = owner_keypair[:public_key]
578
+ payer_pubkey = payer_keypair[:public_key]
579
+ owner_pubkey = owner_keypair[:public_key]
547
580
 
548
- # Define the associated token account to be closed and the destination account
549
- account_to_close_pubkey = 'InsertAccountToClosePublicKeyHere' # Replace with the actual account to close
550
- destination_pubkey = 'InsertDestinationPublicKeyHere' # Replace with the actual recipient address
581
+ # Define the associated token account to be closed and the destination account
582
+ account_to_close_pubkey = 'InsertAccountToClosePublicKeyHere' # Replace with the actual account to close
583
+ destination_pubkey = 'InsertDestinationPublicKeyHere' # Replace with the actual recipient address
551
584
 
552
- # Multi-signers (if required)
553
- # multi_signers = [SolanaRuby::Keypair.from_private_key("InsertAdditionalSignerPrivateKeyHere")]
554
- multi_signers = []
585
+ # Multi-signers (if required)
586
+ # multi_signers = [SolanaRuby::Keypair.from_private_key("InsertAdditionalSignerPrivateKeyHere")]
587
+ multi_signers = []
555
588
 
556
- # Extract public keys of multi-signers
557
- multi_signer_pubkeys = multi_signers.map { |signer| signer[:public_key] }
589
+ # Extract public keys of multi-signers
590
+ multi_signer_pubkeys = multi_signers.map { |signer| signer[:public_key] }
558
591
 
559
- # Create the close account transaction
560
- transaction = SolanaRuby::TransactionHelper.close_account(
561
- account_to_close_pubkey,
562
- destination_pubkey,
563
- owner_pubkey,
564
- payer_pubkey,
565
- multi_signer_pubkeys,
566
- recent_blockhash
567
- )
592
+ # Create the close account transaction
593
+ transaction = SolanaRuby::TransactionHelper.close_account(
594
+ account_to_close_pubkey,
595
+ destination_pubkey,
596
+ owner_pubkey,
597
+ payer_pubkey,
598
+ multi_signer_pubkeys,
599
+ recent_blockhash
600
+ )
568
601
 
569
- # Sign the transaction
570
- transaction.sign([payer_keypair, owner_keypair])
602
+ # Sign the transaction
603
+ transaction.sign([payer_keypair, owner_keypair])
571
604
 
572
- # Send the transaction
573
- response = client.send_transaction(transaction.to_base64, { encoding: 'base64' })
605
+ # Send the transaction
606
+ response = client.send_transaction(transaction.to_base64, { encoding: 'base64' })
574
607
 
575
- # Output transaction results
576
- puts "Transaction Signature: #{response}"
577
- puts "Closed account: #{account_to_close_pubkey}, funds sent to: #{destination_pubkey}"
608
+ # Output transaction results
609
+ puts "Transaction Signature: #{response}"
610
+ puts "Closed account: #{account_to_close_pubkey}, funds sent to: #{destination_pubkey}"
611
+ ```
578
612
 
579
613
  ### Get Associated Token Address
580
614
 
@@ -587,19 +621,21 @@ The get_associated_token_address helper fetches the associated token account for
587
621
 
588
622
  #### Example Usage:
589
623
 
590
- require 'solana_ruby'
624
+ ```ruby
625
+ require 'solana_ruby'
591
626
 
592
- # Define mint address and owner public key
593
- mint_address = 'InsertMintPublicKeyHere'
594
- owner_pubkey = 'InsertOwnerPublicKeyHere'
627
+ # Define mint address and owner public key
628
+ mint_address = 'InsertMintPublicKeyHere'
629
+ owner_pubkey = 'InsertOwnerPublicKeyHere'
595
630
 
596
- # Fetch associated token address
597
- associated_token_address = SolanaRuby::TransactionHelpers::TokenAccount.get_associated_token_address(
598
- mint_address,
599
- owner_pubkey
600
- )
631
+ # Fetch associated token address
632
+ associated_token_address = SolanaRuby::TransactionHelpers::TokenAccount.get_associated_token_address(
633
+ mint_address,
634
+ owner_pubkey
635
+ )
601
636
 
602
- puts "Associated Token Address: #{associated_token_address}"
637
+ puts "Associated Token Address: #{associated_token_address}"
638
+ ```
603
639
 
604
640
  ### Mint SPL Tokens
605
641
 
@@ -616,48 +652,50 @@ The mint_spl_tokens helper allows you to mint new SPL tokens to a specified dest
616
652
 
617
653
  #### Example Usage:
618
654
 
619
- require 'solana_ruby'
655
+ ```ruby
656
+ require 'solana_ruby'
620
657
 
621
- # Initialize the Solana client (defaults to Mainnet: https://api.mainnet-beta.solana.com)
622
- client = SolanaRuby::HttpClient.new('https://api.devnet.solana.com')
658
+ # Initialize the Solana client (defaults to Mainnet: https://api.mainnet-beta.solana.com)
659
+ client = SolanaRuby::HttpClient.new('https://api.devnet.solana.com')
623
660
 
624
- # Fetch the recent blockhash
625
- recent_blockhash = client.get_latest_blockhash["blockhash"]
661
+ # Fetch the recent blockhash
662
+ recent_blockhash = client.get_latest_blockhash["blockhash"]
626
663
 
627
- # Define the mint account and recipient
628
- mint_account = "InsertMintPublicKeyHere"
629
- destination_account = "InsertDestinationPublicKeyHere"
664
+ # Define the mint account and recipient
665
+ mint_account = "InsertMintPublicKeyHere"
666
+ destination_account = "InsertDestinationPublicKeyHere"
630
667
 
631
- # Load the mint authority keypair
632
- mint_authority = SolanaRuby::Keypair.load_keypair('InsertYourJsonFilePathHere')
668
+ # Load the mint authority keypair
669
+ mint_authority = SolanaRuby::Keypair.load_keypair('InsertYourJsonFilePathHere')
633
670
 
634
- puts "Mint Authority Public Key: #{mint_authority[:public_key]}"
671
+ puts "Mint Authority Public Key: #{mint_authority[:public_key]}"
635
672
 
636
- # Define the amount to mint (in smallest units)
637
- amount = 1_000_000_00_00 # Adjust based on token decimals
673
+ # Define the amount to mint (in smallest units)
674
+ amount = 1_000_000_00_00 # Adjust based on token decimals
638
675
 
639
- # Multi-signers (if required)
640
- multi_signers = [] # Example: [additional_signer_pubkey]
676
+ # Multi-signers (if required)
677
+ multi_signers = [] # Example: [additional_signer_pubkey]
641
678
 
642
- # Create the mint transaction
643
- transaction = SolanaRuby::TransactionHelper.mint_spl_tokens(
644
- mint_account,
645
- destination_account,
646
- mint_authority[:public_key],
647
- amount,
648
- recent_blockhash,
649
- multi_signers
650
- )
679
+ # Create the mint transaction
680
+ transaction = SolanaRuby::TransactionHelper.mint_spl_tokens(
681
+ mint_account,
682
+ destination_account,
683
+ mint_authority[:public_key],
684
+ amount,
685
+ recent_blockhash,
686
+ multi_signers
687
+ )
651
688
 
652
- # Sign the transaction with the mint authority
653
- transaction.sign([mint_authority])
689
+ # Sign the transaction with the mint authority
690
+ transaction.sign([mint_authority])
654
691
 
655
- # Send the transaction
656
- response = client.send_transaction(transaction.to_base64, { encoding: 'base64' })
692
+ # Send the transaction
693
+ response = client.send_transaction(transaction.to_base64, { encoding: 'base64' })
657
694
 
658
- # Output transaction results
659
- puts "Transaction Signature: #{response}"
660
- puts "Minted #{amount} tokens to: #{destination_account}"
695
+ # Output transaction results
696
+ puts "Transaction Signature: #{response}"
697
+ puts "Minted #{amount} tokens to: #{destination_account}"
698
+ ```
661
699
 
662
700
  ### Burn SPL Tokens
663
701
 
@@ -673,42 +711,44 @@ The burn_spl_tokens helper allows you to burn (destroy) a specified amount of SP
673
711
 
674
712
  #### Example Usage:
675
713
 
676
- require 'solana_ruby'
714
+ ```ruby
715
+ require 'solana_ruby'
677
716
 
678
- # Initialize the Solana client (defaults to Mainnet: https://api.mainnet-beta.solana.com)
679
- client = SolanaRuby::HttpClient.new('https://api.devnet.solana.com')
717
+ # Initialize the Solana client (defaults to Mainnet: https://api.mainnet-beta.solana.com)
718
+ client = SolanaRuby::HttpClient.new('https://api.devnet.solana.com')
680
719
 
681
- # Fetch the recent blockhash
682
- recent_blockhash = client.get_latest_blockhash["blockhash"]
720
+ # Fetch the recent blockhash
721
+ recent_blockhash = client.get_latest_blockhash["blockhash"]
683
722
 
684
- # Define token account and mint address
685
- token_account = "InsertTokenAccountPublicKeyHere"
686
- mint_address = "InsertMintPublicKeyHere"
723
+ # Define token account and mint address
724
+ token_account = "InsertTokenAccountPublicKeyHere"
725
+ mint_address = "InsertMintPublicKeyHere"
687
726
 
688
- # Load the mint authority keypair
689
- mint_authority = SolanaRuby::Keypair.load_keypair('/path/to/id.json')
690
- owner = mint_authority[:public_key]
727
+ # Load the mint authority keypair
728
+ mint_authority = SolanaRuby::Keypair.load_keypair('/path/to/id.json')
729
+ owner = mint_authority[:public_key]
691
730
 
692
- # Define the amount to burn
693
- amount = 500_000 # Tokens to burn in smallest units
731
+ # Define the amount to burn
732
+ amount = 500_000 # Tokens to burn in smallest units
694
733
 
695
- # Create burn transaction
696
- transaction = SolanaRuby::TransactionHelper.burn_spl_tokens(
697
- token_account,
698
- mint_address,
699
- owner,
700
- amount,
701
- recent_blockhash
702
- )
734
+ # Create burn transaction
735
+ transaction = SolanaRuby::TransactionHelper.burn_spl_tokens(
736
+ token_account,
737
+ mint_address,
738
+ owner,
739
+ amount,
740
+ recent_blockhash
741
+ )
703
742
 
704
- # Sign the transaction
705
- transaction.sign([mint_authority])
743
+ # Sign the transaction
744
+ transaction.sign([mint_authority])
706
745
 
707
- # Send the transaction
708
- response = client.send_transaction(transaction.to_base64, { encoding: 'base64' })
746
+ # Send the transaction
747
+ response = client.send_transaction(transaction.to_base64, { encoding: 'base64' })
709
748
 
710
- # Output transaction results
711
- puts "Transaction Signature: #{response}"
749
+ # Output transaction results
750
+ puts "Transaction Signature: #{response}"
751
+ ```
712
752
 
713
753
  ### Transfer SPL Tokens
714
754
 
@@ -727,64 +767,64 @@ The new_spl_token_transaction helper allows you to transfer SPL tokens from one
727
767
 
728
768
  #### Example Usage:
729
769
 
730
- require 'solana_ruby'
731
-
732
- # Initialize the Solana client
733
- client = SolanaRuby::HttpClient.new('http://127.0.0.1:8899')
734
-
735
- # Fetch the recent blockhash
736
- recent_blockhash = client.get_latest_blockhash["blockhash"]
737
-
738
- # Load the fee payer's keypair
739
- fee_payer = SolanaRuby::Keypair.from_private_key('InsertFeePayerPrivateKeyHere')
740
- fee_payer_pubkey = fee_payer[:public_key]
741
-
742
- # Define the SPL token mint address
743
- mint_address = 'InsertMintPublicKeyHere'
744
-
745
- # Define sender and receiver public keys
746
- sender_pubkey = 'InsertSenderPublicKeyHere'
747
- receiver_pubkey = 'InsertReceiverPublicKeyHere'
748
-
749
- # Fetch the associated token accounts
750
- senders_token_account = SolanaRuby::TransactionHelpers::TokenAccount.get_associated_token_address(mint_address, sender_pubkey)
751
- receivers_token_account = SolanaRuby::TransactionHelpers::TokenAccount.get_associated_token_address(mint_address, receiver_pubkey)
752
-
753
- puts "Sender's Token Account: #{senders_token_account}"
754
- puts "Receiver's Token Account: #{receivers_token_account}"
755
-
756
- # Define the transfer amount and decimals
757
- transfer_lamports = 1_000_000 # Amount in smallest units
758
- decimals = 9 # Adjust based on token precision
759
-
760
- # Multi-signers (Optional, default is an empty array)
761
- # multi_signers = [
762
- # SolanaRuby::Keypair.from_private_key('InsertMultiSigner1PrivateKeyHere'),
763
- # SolanaRuby::Keypair.from_private_key('InsertMultiSigner2PrivateKeyHere')
764
- # ]
765
- # multi_signer_pubkeys = multi_signers.map { |signer| signer[:public_key] }
766
- multi_signers = []
767
-
768
- # Create the transaction
769
- transaction = SolanaRuby::TransactionHelper.new_spl_token_transaction(
770
- senders_token_account,
771
- mint_address,
772
- receivers_token_account,
773
- fee_payer_pubkey,
774
- transfer_lamports,
775
- decimals,
776
- recent_blockhash,
777
- multi_signer_pubkeys
778
- )
779
-
780
- # Sign the transaction (Only fee payer, unless multi-signers are provided)
781
- transaction.sign([fee_payer] + multi_signers)
782
-
783
- # Send the transaction
784
- puts "Sending transaction..."
785
- response = client.send_transaction(transaction.to_base64, { encoding: 'base64' })
786
-
787
- # Output transaction results
788
- puts "Transaction Signature: #{response}"
789
-
790
-
770
+ ```ruby
771
+ require 'solana_ruby'
772
+
773
+ # Initialize the Solana client
774
+ client = SolanaRuby::HttpClient.new('http://127.0.0.1:8899')
775
+
776
+ # Fetch the recent blockhash
777
+ recent_blockhash = client.get_latest_blockhash["blockhash"]
778
+
779
+ # Load the fee payer's keypair
780
+ fee_payer = SolanaRuby::Keypair.from_private_key('InsertFeePayerPrivateKeyHere')
781
+ fee_payer_pubkey = fee_payer[:public_key]
782
+
783
+ # Define the SPL token mint address
784
+ mint_address = 'InsertMintPublicKeyHere'
785
+
786
+ # Define sender and receiver public keys
787
+ sender_pubkey = 'InsertSenderPublicKeyHere'
788
+ receiver_pubkey = 'InsertReceiverPublicKeyHere'
789
+
790
+ # Fetch the associated token accounts
791
+ senders_token_account = SolanaRuby::TransactionHelpers::TokenAccount.get_associated_token_address(mint_address, sender_pubkey)
792
+ receivers_token_account = SolanaRuby::TransactionHelpers::TokenAccount.get_associated_token_address(mint_address, receiver_pubkey)
793
+
794
+ puts "Sender's Token Account: #{senders_token_account}"
795
+ puts "Receiver's Token Account: #{receivers_token_account}"
796
+
797
+ # Define the transfer amount and decimals
798
+ transfer_lamports = 1_000_000 # Amount in smallest units
799
+ decimals = 9 # Adjust based on token precision
800
+
801
+ # Multi-signers (Optional, default is an empty array)
802
+ # multi_signers = [
803
+ # SolanaRuby::Keypair.from_private_key('InsertMultiSigner1PrivateKeyHere'),
804
+ # SolanaRuby::Keypair.from_private_key('InsertMultiSigner2PrivateKeyHere')
805
+ # ]
806
+ # multi_signer_pubkeys = multi_signers.map { |signer| signer[:public_key] }
807
+ multi_signers = []
808
+
809
+ # Create the transaction
810
+ transaction = SolanaRuby::TransactionHelper.new_spl_token_transaction(
811
+ senders_token_account,
812
+ mint_address,
813
+ receivers_token_account,
814
+ fee_payer_pubkey,
815
+ transfer_lamports,
816
+ decimals,
817
+ recent_blockhash,
818
+ multi_signer_pubkeys
819
+ )
820
+
821
+ # Sign the transaction (Only fee payer, unless multi-signers are provided)
822
+ transaction.sign([fee_payer] + multi_signers)
823
+
824
+ # Send the transaction
825
+ puts "Sending transaction..."
826
+ response = client.send_transaction(transaction.to_base64, { encoding: 'base64' })
827
+
828
+ # Output transaction results
829
+ puts "Transaction Signature: #{response}"
830
+ ```
@@ -10,12 +10,22 @@ module SolanaRuby
10
10
  def self.on_curve?(public_key)
11
11
  return false unless public_key.bytesize == 32 # Must be exactly 32 bytes
12
12
 
13
- # Extract y-coordinate from the public key
14
- y = public_key.unpack1("H*").to_i(16) % Q
15
-
13
+ # Extract bytes - needed for bitwise operations
14
+ y_bytes = public_key.bytes
15
+ # Ed25519 Curve does not use the x sign bit, y value is (0-254) so we need to clear the bit 255 (x sign bit)
16
+ # Byte 31, bit 7 is the sign bit
17
+ y_bytes[31] &= 0x7F # binary 01111111
18
+
19
+ # shift left bytes by 8 bits to get little-endian order then sum to get integer
20
+ # In little-endian: byte[0] is 2^0, byte[1] is 2^8, ..., byte[31] is 2^248
21
+ y = y_bytes.each_with_index.sum { |byte, index| byte << (8 * index) }
22
+
23
+ # Reduce modulo Q (field arithmetic) to ensure it's within the valid range
24
+ y = y % Q
16
25
  # Compute x² from the Ed25519 curve equation: x² = (y² - 1) / (d * y² + 1) mod Q
17
- numerator = (y**2 - 1) % Q
18
- denominator = (D * y**2 + 1) % Q
26
+ y_squared = (y * y) % Q
27
+ numerator = (y_squared - 1) % Q
28
+ denominator = (D * y_squared + 1) % Q
19
29
 
20
30
  # Compute the modular inverse of the denominator
21
31
  denominator_inv = OpenSSL::BN.new(denominator).mod_inverse(Q).to_i rescue nil
@@ -65,7 +65,8 @@ module SolanaRuby
65
65
 
66
66
  def self.hash_seeds(seeds, program_id)
67
67
  # Combine seeds and program ID with the PDA derivation logic
68
- buffer = seeds.flatten.join + program_id + "ProgramDerivedAddress"
68
+ # strict encoding to binary
69
+ buffer = seeds.join.b + program_id.b + "ProgramDerivedAddress".b
69
70
  RbNaCl::Hash.sha256(buffer)
70
71
  end
71
72
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SolanaRuby
4
- VERSION = "2.1.5"
4
+ VERSION = "2.1.6"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: solana-ruby-web3js
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.5
4
+ version: 2.1.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - BuildSquad
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-03-18 00:00:00.000000000 Z
11
+ date: 2026-02-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: websocket-client-simple
@@ -307,7 +307,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
307
307
  - !ruby/object:Gem::Version
308
308
  version: '0'
309
309
  requirements: []
310
- rubygems_version: 3.5.20
310
+ rubygems_version: 3.5.9
311
311
  signing_key:
312
312
  specification_version: 4
313
313
  summary: Solana Ruby SDK