solana-ruby-web3js 2.0.0beta2 → 2.0.0

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: 6bb6650de7a5beae14649fe9cfac20973923d0be4c4f74e9d1e8f373e70842b9
4
- data.tar.gz: c3ad4316d61d4326327bb281a3eb64991011ae14d51a7974de6eaf9705d4ffa5
3
+ metadata.gz: 9f614bab0b21438c2820d0035a0aa33567a11fedd3ecb998666b39e5ab28681d
4
+ data.tar.gz: c63fd671d6328732c39994032f94aff219ff77eda8cd899c5d1f0c29f86f4524
5
5
  SHA512:
6
- metadata.gz: 94c8304f1d05d7cbd8ec22947d98ede21c1892b210ad5cdb43f3e6293f4c6ab288c8aa83b1ba6e40a28d08a191a32ba775966eeb370631d02112cac981309fb6
7
- data.tar.gz: '0085b47b4f44786e0bd0af77827a12cbc191744a16aff61448cafff641a53efa798677ef51b3748966f76547b883fd767d3f48ffe5297f8519cc08eb1ee81e90'
6
+ metadata.gz: 4015bdc6179d57105ea1da82daa9d6ec19f623098d636271fb0e7ab9210d563414eae364271e58be82a2ce9ed6dc0804de53db7e7a15c5d353da4ff30faf5124
7
+ data.tar.gz: 8fca9ec2ccdcc5b3ea72f54fa6fad27fee3fe1aef20b145107382c523a0a70df90812f269fdcdee3d9d62b732e6ebe7ce6ad3e1514257d379db7088de55941d1
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- solana-ruby-web3js (2.0.0beta1)
4
+ solana-ruby-web3js (1.0.1.beta3)
5
5
  base58 (~> 0.2.3)
6
6
  base64 (~> 0.2.0)
7
7
  ed25519
data/README.md CHANGED
@@ -332,75 +332,3 @@ The following methods are supported by the SolanaRuby::WebSocketClient:
332
332
 
333
333
  Several methods have optional parameters where default options are defined in the client. These options can be customized or overridden when calling the methods, but if left unspecified, the client will use its internal defaults.
334
334
 
335
- ## Transaction Helpers
336
-
337
- ### Transfer SOL Between Accounts
338
-
339
- To transfer SOL (the native cryptocurrency of the Solana blockchain) from one account to another, follow these steps:
340
-
341
- #### Requirements:
342
-
343
- - **Sender's Keypair:** Either generate a new keypair or provide the private key for an existing sender account. This keypair is used to sign the transaction.
344
- - **Receiver's Public Key:** Specify the public key of the destination account. You can generate a new keypair for the receiver or use an existing public key.
345
- - **Airdrop Functionality:** For Mainnet, Devnet, or Testnet transactions, ensure that the sender's account is funded with sufficient lamports using the Solana airdrop feature.
346
- - An initialized client to interact with the Solana blockchain.
347
-
348
- #### Example Usage:
349
-
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}"
406
-
@@ -4,26 +4,26 @@ module SolanaRuby
4
4
  attr_reader :size
5
5
 
6
6
  BITS = {
7
- 8 => { directive: 'C', size: 1 }, # 8-bit unsigned integer
8
- 32 => { directive: 'L<', size: 4 }, # 32-bit little-endian unsigned integer
9
- 64 => { directive: 'Q<', size: 8 } # 64-bit little-endian unsigned integer
7
+ 8 => { directive: 'C*', size: 1 },
8
+ 32 => { directive: 'L*', size: 4 },
9
+ 64 => { directive: 'Q*', size: 8 }
10
10
  }
11
11
 
12
12
  def initialize(bits)
13
13
  @bits = bits
14
14
  type = BITS[@bits]
15
- raise "Unsupported size. Supported sizes: #{BITS.keys.join(', ')} bits" unless type
15
+ raise "Can only fit #{BITS.keys}" unless type
16
16
  @size = type[:size]
17
17
  @directive = type[:directive]
18
18
  end
19
19
 
20
- # Serialize the unsigned integer into properly aligned bytes
20
+ # Serialize the unsigned integer into bytes
21
21
  def serialize(obj)
22
22
  raise "Can only serialize integers" unless obj.is_a?(Integer)
23
- raise "Cannot serialize negative integers" if obj.negative?
23
+ raise "Cannot serialize negative integers" if obj < 0
24
24
 
25
25
  if obj >= 256**@size
26
- raise "Integer too large to fit in #{@size} bytes"
26
+ raise "Integer too large (does not fit in #{@size} bytes)"
27
27
  end
28
28
 
29
29
  [obj].pack(@directive).bytes
@@ -31,7 +31,7 @@ module SolanaRuby
31
31
 
32
32
  # Deserialize bytes into the unsigned integer
33
33
  def deserialize(bytes)
34
- raise "Invalid serialization (expected #{@size} bytes, got #{bytes.size})" if bytes.size != @size
34
+ raise "Invalid serialization (wrong size)" if bytes.size != @size
35
35
 
36
36
  bytes.pack('C*').unpack(@directive).first
37
37
  end
@@ -21,9 +21,5 @@ module SolanaRuby
21
21
  def blob1
22
22
  Blob.new(1)
23
23
  end
24
-
25
- def blob32
26
- Blob.new(32)
27
- end
28
24
  end
29
25
  end
@@ -1,5 +1,3 @@
1
- Dir[File.join(__dir__, 'data_types', '*.rb')].each { |file| require file }
2
-
3
1
  module SolanaRuby
4
2
  class Transaction
5
3
  require 'rbnacl'
@@ -72,10 +70,10 @@ module SolanaRuby
72
70
  instructions.push(item)
73
71
  end
74
72
 
75
- def sign(keypairs)
76
- raise 'No signers' unless keypairs.any?
73
+ def sign(keys)
74
+ raise 'No signers' unless keys.any?
77
75
 
78
- keys = keypairs.uniq { |kp| kp[:public_key] }
76
+ keys = keys.uniq{ |k| key[:public_key] }
79
77
  @signatures = keys.map do |key|
80
78
  {
81
79
  signature: nil,
@@ -116,17 +114,15 @@ module SolanaRuby
116
114
  def compile_message
117
115
  check_for_errors
118
116
  fetch_message_data
119
-
120
- # add instruction structure
121
- instructs = add_instructs
122
-
123
- message_data = Message.new(
124
- header: @header,
125
- account_keys: @account_keys,
126
- recent_blockhash: recent_blockhash,
127
- instructions: instructs
117
+ message = Message.new(
118
+ header: {
119
+ num_required_signatures: @num_required_signatures,
120
+ num_readonly_signed_accounts: @num_readonly_signed_accounts,
121
+ num_readonly_unsigned_accounts: @num_readonly_unsigned_accounts,
122
+ },
123
+ account_keys: @account_keys, recent_blockhash: recent_blockhash, instructions: @instructs
128
124
  )
129
- message_data
125
+ message
130
126
  end
131
127
 
132
128
  def check_for_errors
@@ -172,8 +168,11 @@ module SolanaRuby
172
168
  # Split out signing from non-signing keys and count header values
173
169
  signed_keys = []
174
170
  unsigned_keys = []
175
- @header = split_keys(unique_metas, signed_keys, unsigned_keys)
171
+ header_params = split_keys(unique_metas, signed_keys, unsigned_keys)
176
172
  @account_keys = signed_keys + unsigned_keys
173
+
174
+ # add instruction structure
175
+ @instructs = add_instructs
177
176
  end
178
177
 
179
178
  def append_program_id(program_ids, account_metas)
@@ -246,24 +245,19 @@ module SolanaRuby
246
245
  end
247
246
 
248
247
  def split_keys(unique_metas, signed_keys, unsigned_keys)
249
- num_required_signatures = 0
250
- num_readonly_signed_accounts = 0
251
- num_readonly_unsigned_accounts = 0
248
+ @num_required_signatures = 0
249
+ @num_readonly_signed_accounts = 0
250
+ @num_readonly_unsigned_accounts = 0
252
251
  unique_metas.each do |meta|
253
252
  if meta[:is_signer]
254
253
  signed_keys.push(meta[:pubkey])
255
- num_required_signatures += 1
256
- num_readonly_signed_accounts += 1 if (!meta[:is_writable])
254
+ @num_required_signatures += 1
255
+ @num_readonly_signed_accounts += 1 if (!meta[:is_writable])
257
256
  else
258
257
  unsigned_keys.push(meta[:pubkey])
259
- num_readonly_unsigned_accounts += 1 if (!meta[:is_writable])
258
+ @num_readonly_unsigned_accounts += 1 if (!meta[:is_writable])
260
259
  end
261
260
  end
262
- {
263
- num_required_signatures: num_required_signatures,
264
- num_readonly_signed_accounts: num_readonly_signed_accounts,
265
- num_readonly_unsigned_accounts: num_readonly_unsigned_accounts,
266
- }
267
261
  end
268
262
 
269
263
  def partial_sign(message, keys)
@@ -19,59 +19,46 @@ module SolanaRuby
19
19
  instruction: :uint8,
20
20
  amount: :uint64
21
21
  },
22
- # Create account layout
22
+ # Create account layout
23
23
  create_account: {
24
- instruction: :uint32,
24
+ instruction: :uint8,
25
25
  lamports: :uint64,
26
- space: :uint64,
27
- program_id: :blob32
26
+ space: :uint64
28
27
  }
29
28
  }
30
29
 
31
30
  # Method to create a system account (e.g., for SPL token or SOL)
32
- def self.account_instruction(from_pubkey, new_account_pubkey, lamports, space, program_id)
33
- # Encode the instruction data
34
- instruction_data = encode_data(
35
- INSTRUCTION_LAYOUTS[:create_account],
36
- {
37
- instruction: 0, # '0' corresponds to the Create Account instruction
38
- lamports: lamports, # The amount of lamports to transfer to the new account
39
- space: space, # Amount of space allocated for the account's data
40
- program_id: Base58.base58_to_binary(program_id, :bitcoin).bytes # Convert public key to binary
41
- }
42
- )
43
-
44
- # Construct the transaction instruction
31
+ def self.create_account(from_pubkey, new_account_pubkey, lamports, space, owner_pubkey = SYSTEM_PROGRAM_ID)
32
+ instruction_data = encode_data(INSTRUCTION_LAYOUTS[:create_account], { instruction: 0, lamports: lamports, space: space })
45
33
  create_account_instruction = TransactionInstruction.new(
46
34
  keys: [
47
- { pubkey: from_pubkey, is_signer: true, is_writable: true }, # Funder's account
48
- { pubkey: new_account_pubkey, is_signer: true, is_writable: true } # New account
35
+ { pubkey: from_pubkey, is_signer: true, is_writable: true },
36
+ { pubkey: new_account_pubkey, is_signer: false, is_writable: true },
37
+ { pubkey: owner_pubkey, is_signer: false, is_writable: false }
49
38
  ],
50
- program_id: program_id, # Use Solana's system program for account creation
51
- data: instruction_data # Encoded instruction data
39
+ program_id: owner_pubkey,
40
+ data: instruction_data.bytes
52
41
  )
53
-
54
- # return instruction data
55
42
  create_account_instruction
56
43
  end
57
44
 
58
-
59
- def self.create_account(from_pubkey, new_account_pubkey, lamports, space, recent_blockhash, program_id = SYSTEM_PROGRAM_ID)
45
+ def self.create_and_sign_transaction(from_pubkey, new_account_pubkey, lamports, space, recent_blockhash)
60
46
  # Create the transaction
61
47
  transaction = Transaction.new
62
48
  transaction.set_fee_payer(from_pubkey)
63
49
  transaction.set_recent_blockhash(recent_blockhash)
64
50
 
65
51
  # Add the create account instruction to the transaction
66
- instruction = account_instruction(from_pubkey, new_account_pubkey, lamports, space, program_id)
67
- transaction.add_instruction(instruction)
68
-
69
- # return the transaction for signing
52
+ create_account_instruction = create_account(from_pubkey, new_account_pubkey, lamports, space)
53
+ transaction.add_instruction(create_account_instruction)
54
+
55
+ # You would then sign the transaction and send it as needed
56
+ # Example: signing and sending the transaction
70
57
  transaction
71
58
  end
72
59
 
73
60
  # Method to create a SOL transfer instruction
74
- def self.transfer_sol_instruction(from_pubkey, to_pubkey, lamports)
61
+ def self.transfer_sol_transaction(from_pubkey, to_pubkey, lamports)
75
62
  fields = INSTRUCTION_LAYOUTS[:sol_transfer]
76
63
  data = encode_data(fields, { instruction: 2, lamports: lamports })
77
64
  TransactionInstruction.new(
@@ -85,11 +72,11 @@ module SolanaRuby
85
72
  end
86
73
 
87
74
  # Helper to create a new transaction for SOL transfer
88
- def self.sol_transfer(from_pubkey, to_pubkey, lamports, recent_blockhash)
75
+ def self.new_sol_transaction(from_pubkey, to_pubkey, lamports, recent_blockhash)
89
76
  transaction = Transaction.new
90
77
  transaction.set_fee_payer(from_pubkey)
91
78
  transaction.set_recent_blockhash(recent_blockhash)
92
- transfer_instruction = transfer_sol_instruction(from_pubkey, to_pubkey, lamports)
79
+ transfer_instruction = transfer_sol_transaction(from_pubkey, to_pubkey, lamports)
93
80
  transaction.add_instruction(transfer_instruction)
94
81
  transaction
95
82
  end
@@ -120,14 +107,13 @@ module SolanaRuby
120
107
  end
121
108
 
122
109
  # Method to create an associated token account for a given token mint
123
- def self.create_associated_token_account(payer, mint, owner)
110
+ def self.create_associated_token_account(from_pubkey, token_mint, owner_pubkey)
124
111
  data = [0, 0, 0, 0] # No data required for account creation
125
112
  create_account_instruction = TransactionInstruction.new(
126
113
  keys: [
127
- { pubkey: payer, is_signer: true, is_writable: true },
128
- { pubkey: associated_token, is_signer: false, is_writable: true },
129
- { pubkey: owner, is_signer: false, is_writable: false },
130
- { pubkey: mint, is_signer: false, is_writable: false },
114
+ { pubkey: from_pubkey, is_signer: true, is_writable: true },
115
+ { pubkey: owner_pubkey, is_signer: false, is_writable: true },
116
+ { pubkey: token_mint, is_signer: false, is_writable: false },
131
117
  { pubkey: ASSOCIATED_TOKEN_PROGRAM_ID, is_signer: false, is_writable: false },
132
118
  { pubkey: SYSTEM_PROGRAM_ID, is_signer: false, is_writable: false }
133
119
  ],
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SolanaRuby
4
- VERSION = "2.0.0beta2"
4
+ VERSION = "2.0.0"
5
5
  end
@@ -3,55 +3,30 @@
3
3
  Dir[File.join(File.dirname(__dir__), 'lib/solana_ruby/*.rb')].each { |file| require file }
4
4
  Dir[File.join(File.dirname(__dir__), 'lib/solana_ruby/**/*.rb')].each { |file| require file }
5
5
 
6
- # Initialize Solana client
6
+ # Testing Script
7
+
7
8
  client = SolanaRuby::HttpClient.new('http://127.0.0.1:8899')
8
9
 
9
10
  # Fetch the recent blockhash
10
11
  recent_blockhash = client.get_latest_blockhash["blockhash"]
11
- puts "Recent Blockhash: #{recent_blockhash}"
12
12
 
13
- # Sender keypair and public key
14
- private_key = "d22867a84ee1d91485a52c587793002dcaa7ce79a58bb605b3af2682099bb778"
15
- sender_keypair = SolanaRuby::Keypair.from_private_key(private_key)
13
+ # Generate a sender keypair and public key
14
+ sender_keypair = SolanaRuby::Keypair.from_private_key("d22867a84ee1d91485a52c587793002dcaa7ce79a58bb605b3af2682099bb778")
16
15
  sender_pubkey = sender_keypair[:public_key]
17
- puts "Sender Public Key: #{sender_pubkey}"
18
-
19
- # Check sender's account balance
16
+ lamports = 1 * 1_000_000_000
17
+ space = 165
20
18
  balance = client.get_balance(sender_pubkey)
21
- puts "Sender account balance: #{balance} lamports"
22
- if balance == 0
23
- puts "Balance is zero, waiting for balance update..."
24
- sleep(10)
25
- end
19
+ puts "sender account balance: #{balance}, wait for few seconds to update the balance in solana when the balance 0"
20
+
26
21
 
27
- # new keypair and public key (new account)
22
+ # Generate a receiver keypair and public key
28
23
  new_account = SolanaRuby::Keypair.generate
29
24
  new_account_pubkey = new_account[:public_key]
30
- puts "New Account Public Key: #{new_account_pubkey}"
31
-
32
- # Parameters for account creation
33
- lamports = 1 * 1_000_000_000 # Lamports to transfer
34
- space = 165 # Space allocation (bytes)
35
- program_id = SolanaRuby::TransactionHelper::SYSTEM_PROGRAM_ID
36
-
37
- # Create and sign the transaction
38
- transaction = SolanaRuby::TransactionHelper.create_account(
39
- sender_pubkey,
40
- new_account_pubkey,
41
- lamports,
42
- space,
43
- recent_blockhash,
44
- program_id
45
- )
46
-
47
- # Sign transaction with both sender and new account keypairs
48
- transaction.sign([sender_keypair, new_account])
49
-
50
- # Send the transaction
51
- puts "Sending transaction..."
52
- response = client.send_transaction(transaction.to_base64, { encoding: 'base64' })
53
25
 
54
- # Output transaction results
55
- puts "Transaction Signature: #{response}"
56
- puts "New account created successfully with Public Key: #{new_account_pubkey}"
26
+ # create a transaction instruction
27
+ transaction = SolanaRuby::TransactionHelper.create_and_sign_transaction(sender_pubkey, new_account_pubkey, lamports, space, recent_blockhash)
57
28
 
29
+ signed_transaction = transaction.sign([sender_keypair])
30
+ sleep(5)
31
+ response = client.send_transaction(transaction.to_base64, { encoding: 'base64' })
32
+ puts "Response: #{response}"
@@ -35,7 +35,7 @@ puts "Receiver's full private key: #{keypair[:full_private_key]}"
35
35
  puts "Receiver's Public Key: #{keypair[:public_key]}"
36
36
 
37
37
  # Create a new transaction
38
- transaction = SolanaRuby::TransactionHelper.sol_transfer(
38
+ transaction = SolanaRuby::TransactionHelper.new_sol_transaction(
39
39
  sender_pubkey,
40
40
  receiver_pubkey,
41
41
  transfer_lamports,
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.0.0beta2
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - BuildSquad
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-11-28 00:00:00.000000000 Z
11
+ date: 2024-11-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: websocket-client-simple