solace 0.0.2 → 0.0.5

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.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +57 -0
  3. data/LICENSE +21 -0
  4. data/README.md +142 -287
  5. data/lib/solace/address_lookup_table.rb +34 -18
  6. data/lib/solace/composers/base.rb +45 -0
  7. data/lib/solace/composers/spl_token_program_transfer_checked_composer.rb +113 -0
  8. data/lib/solace/composers/system_program_transfer_composer.rb +80 -0
  9. data/lib/solace/concerns/binary_serializable.rb +39 -0
  10. data/lib/solace/connection.rb +101 -44
  11. data/lib/solace/constants.rb +7 -14
  12. data/lib/solace/instruction.rb +30 -19
  13. data/lib/solace/instructions/associated_token_account/create_associated_token_account_instruction.rb +18 -3
  14. data/lib/solace/instructions/spl_token/initialize_account_instruction.rb +24 -3
  15. data/lib/solace/instructions/spl_token/initialize_mint_instruction.rb +18 -1
  16. data/lib/solace/instructions/spl_token/mint_to_instruction.rb +16 -3
  17. data/lib/solace/instructions/spl_token/transfer_checked_instruction.rb +76 -0
  18. data/lib/solace/instructions/spl_token/transfer_instruction.rb +15 -2
  19. data/lib/solace/instructions/system_program/create_account_instruction.rb +18 -3
  20. data/lib/solace/instructions/system_program/transfer_instruction.rb +58 -0
  21. data/lib/solace/keypair.rb +64 -31
  22. data/lib/solace/message.rb +22 -10
  23. data/lib/solace/programs/associated_token_account.rb +58 -11
  24. data/lib/solace/programs/base.rb +6 -0
  25. data/lib/solace/programs/spl_token.rb +52 -14
  26. data/lib/solace/public_key.rb +45 -20
  27. data/lib/solace/serializers/address_lookup_table_deserializer.rb +3 -5
  28. data/lib/solace/serializers/address_lookup_table_serializer.rb +7 -7
  29. data/lib/solace/serializers/base_deserializer.rb +29 -19
  30. data/lib/solace/serializers/base_serializer.rb +18 -9
  31. data/lib/solace/serializers/instruction_deserializer.rb +5 -7
  32. data/lib/solace/serializers/instruction_serializer.rb +4 -6
  33. data/lib/solace/serializers/message_deserializer.rb +3 -5
  34. data/lib/solace/serializers/message_serializer.rb +3 -5
  35. data/lib/solace/serializers/transaction_deserializer.rb +5 -7
  36. data/lib/solace/serializers/transaction_serializer.rb +5 -7
  37. data/lib/solace/transaction.rb +38 -23
  38. data/lib/solace/transaction_composer.rb +115 -0
  39. data/lib/solace/utils/account_context.rb +252 -0
  40. data/lib/solace/utils/codecs.rb +56 -128
  41. data/lib/solace/utils/curve25519_dalek.rb +9 -4
  42. data/lib/solace/utils/pda.rb +22 -24
  43. data/lib/solace/version.rb +2 -1
  44. data/lib/solace.rb +9 -7
  45. metadata +15 -12
  46. data/lib/solace/instructions/transfer_checked_instruction.rb +0 -58
  47. data/lib/solace/instructions/transfer_instruction.rb +0 -48
  48. data/lib/solace/serializable_record.rb +0 -26
  49. data/lib/solace/serializers/base.rb +0 -31
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solace
4
+ module Composers
5
+ # A Base class for all composers
6
+ #
7
+ # @since 0.0.3
8
+ class Base
9
+ # @!attribute params
10
+ # The params for the composer
11
+ #
12
+ # @return [Hash] The parameters passed to the composer
13
+ attr_reader :params
14
+
15
+ # @!attribute account_context
16
+ # The account_context for the composer
17
+ #
18
+ # @return [Utils::AccountContext] The AccountContext instance for the composer
19
+ attr_reader :account_context
20
+
21
+ # Initialize the composer
22
+ #
23
+ # @param params [Hash] Parameters to pass to the composer constructor
24
+ def initialize(params)
25
+ @params = params
26
+ @account_context = Utils::AccountContext.new
27
+ setup_accounts
28
+ end
29
+
30
+ # Setup accounts required for this instruction
31
+ #
32
+ # @return [void]
33
+ def setup_accounts
34
+ raise NotImplementedError, 'Subclasses must implement setup_accounts method'
35
+ end
36
+
37
+ # Build instruction with resolved account indices
38
+ #
39
+ # @return [void]
40
+ def build_instruction(indices)
41
+ raise NotImplementedError, 'Subclasses must implement build_instruction method'
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,113 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solace
4
+ module Composers
5
+ # Composer for creating a SPL Token Program `TransferChecked` instruction.
6
+ #
7
+ # This composer resolves and orders the required accounts for a `TransferChecked` instruction,
8
+ # sets up their access permissions, and delegates construction to the appropriate
9
+ # instruction builder (`Instructions::SplToken::TransferCheckedInstruction`).
10
+ #
11
+ # It is used for transferring SPL tokens with decimal precision and validation checks.
12
+ #
13
+ # Required accounts:
14
+ # - **From**: source token account (writable, non-signer)
15
+ # - **To**: destination token account (writable, non-signer)
16
+ # - **Mint**: mint address (readonly, non-signer)
17
+ # - **Authority**: token owner (writable, signer)
18
+ # - **Program**: SPL Token program (readonly, non-signer)
19
+ #
20
+ # @example Compose and build a transfer_checked instruction
21
+ # composer = SplTokenProgramTransferCheckedComposer.new(
22
+ # from: from_address,
23
+ # to: to_address,
24
+ # mint: mint_address,
25
+ # authority: authority_pubkey,
26
+ # amount: 1_000_000,
27
+ # decimals: 6
28
+ # )
29
+ #
30
+ # @see Instructions::SplToken::TransferCheckedInstruction
31
+ # @since 0.0.3
32
+ class SplTokenProgramTransferCheckedComposer < Base
33
+ # Extracts the to address from the params
34
+ #
35
+ # @return [String] The to address
36
+ def to
37
+ params[:to].is_a?(String) ? params[:to] : params[:to].address
38
+ end
39
+
40
+ # Extracts the from address from the params
41
+ #
42
+ # @return [String] The from address
43
+ def from
44
+ params[:from].is_a?(String) ? params[:from] : params[:from].address
45
+ end
46
+
47
+ # Extracts the authority address from the params
48
+ #
49
+ # The authority is the owner of the token account
50
+ #
51
+ # @return [String] The authority address
52
+ def authority
53
+ params[:authority].is_a?(String) ? params[:authority] : params[:authority].address
54
+ end
55
+
56
+ # Extracts the mint address from the params
57
+ #
58
+ # @return [String] The mint address
59
+ def mint
60
+ params[:mint].is_a?(String) ? params[:mint] : params[:mint].address
61
+ end
62
+
63
+ # Returns the spl token program id
64
+ #
65
+ # @return [String] The spl token program id
66
+ def spl_token_program
67
+ Constants::TOKEN_PROGRAM_ID
68
+ end
69
+
70
+ # Returns the lamports to transfer
71
+ #
72
+ # @return [Integer] The lamports to transfer
73
+ def amount
74
+ params[:amount]
75
+ end
76
+
77
+ # Returns the decimals for the mint of the token
78
+ #
79
+ # @return [Integer] The decimals for the mint
80
+ def decimals
81
+ params[:decimals]
82
+ end
83
+
84
+ # Setup accounts required for transfer instruction
85
+ # Called automatically during initialization
86
+ #
87
+ # @return [void]
88
+ def setup_accounts
89
+ account_context.add_writable_signer(authority)
90
+ account_context.add_writable_nonsigner(to)
91
+ account_context.add_writable_nonsigner(from)
92
+ account_context.add_readonly_nonsigner(mint)
93
+ account_context.add_readonly_nonsigner(spl_token_program)
94
+ end
95
+
96
+ # Build instruction with resolved account indices
97
+ #
98
+ # @param account_context [Utils::AccountContext] The account context
99
+ # @return [Solace::Instruction]
100
+ def build_instruction(account_context)
101
+ Instructions::SplToken::TransferCheckedInstruction.build(
102
+ amount: amount,
103
+ decimals: decimals,
104
+ to_index: account_context.index_of(to),
105
+ from_index: account_context.index_of(from),
106
+ mint_index: account_context.index_of(mint),
107
+ authority_index: account_context.index_of(authority),
108
+ program_index: account_context.index_of(spl_token_program)
109
+ )
110
+ end
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solace
4
+ module Composers
5
+ # Composer for creating a system program transfer instruction.
6
+ #
7
+ # This composer resolves and orders the required accounts for a `Transfer` instruction,
8
+ # sets up their access permissions, and delegates construction to the appropriate
9
+ # instruction builder (`Instructions::SystemProgram::TransferInstruction`).
10
+ #
11
+ # It is used for transferring lamports from one account to another.
12
+ #
13
+ # Required accounts:
14
+ # - **From**: source account (writable, signer)
15
+ # - **To**: destination account (writable, non-signer)
16
+ # - **Program**: System program (readonly, non-signer)
17
+ #
18
+ # @example Compose and build a transfer instruction
19
+ # composer = SystemProgramTransferComposer.new(
20
+ # from: from_address,
21
+ # to: to_address,
22
+ # lamports: 1_000_000
23
+ # )
24
+ #
25
+ # @see Instructions::SystemProgram::TransferInstruction
26
+ # @since 0.0.3
27
+ class SystemProgramTransferComposer < Base
28
+ # Extracts the to address from the params
29
+ #
30
+ # @return [String] The to address
31
+ def to
32
+ params[:to].is_a?(String) ? params[:to] : params[:to].address
33
+ end
34
+
35
+ # Extracts the from address from the params
36
+ #
37
+ # @return [String] The from address
38
+ def from
39
+ params[:from].is_a?(String) ? params[:from] : params[:from].address
40
+ end
41
+
42
+ # Returns the system program id
43
+ #
44
+ # @return [String] The system program id
45
+ def system_program
46
+ Solace::Constants::SYSTEM_PROGRAM_ID
47
+ end
48
+
49
+ # Returns the lamports to transfer
50
+ #
51
+ # @return [Integer] The lamports to transfer
52
+ def lamports
53
+ params[:lamports]
54
+ end
55
+
56
+ # Setup accounts required for transfer instruction
57
+ # Called automatically during initialization
58
+ #
59
+ # @return [void]
60
+ def setup_accounts
61
+ account_context.add_writable_signer(from)
62
+ account_context.add_writable_nonsigner(to)
63
+ account_context.add_readonly_nonsigner(system_program)
64
+ end
65
+
66
+ # Build instruction with resolved account indices
67
+ #
68
+ # @param account_context [Utils::AccountContext] The account context
69
+ # @return [Solace::Instruction]
70
+ def build_instruction(account_context)
71
+ Instructions::SystemProgram::TransferInstruction.build(
72
+ lamports: lamports,
73
+ to_index: account_context.index_of(to),
74
+ from_index: account_context.index_of(from),
75
+ program_index: account_context.index_of(system_program)
76
+ )
77
+ end
78
+ end
79
+ end
80
+ end
@@ -2,7 +2,24 @@
2
2
 
3
3
  module Solace
4
4
  module Concerns
5
+ # Adds binary serialization support to a class
6
+ #
7
+ # Transactions, Messages, Instructions, and AddressLookupTables are all binary serializable.
8
+ # These classes use this concern to add binary serialization support.
9
+ #
10
+ # @see Solace::Transaction
11
+ # @see Solace::Message
12
+ # @see Solace::Instruction
13
+ # @see Solace::AddressLookupTable
14
+ # @since 0.0.1
5
15
  module BinarySerializable
16
+ # Include the module
17
+ #
18
+ # @param base [Class] The base class to include the module into
19
+ def self.included(base)
20
+ base.extend ClassMethods
21
+ end
22
+
6
23
  # Returns the binary decoded from the serialized string
7
24
  #
8
25
  # Expects the class to have a `serialize` method that returns a base64 string.
@@ -25,6 +42,28 @@ module Solace
25
42
  def to_bytes
26
43
  to_binary.bytes
27
44
  end
45
+
46
+ # Serializes the record to a binary format
47
+ #
48
+ # @return [String] The serialized record (binary)
49
+ def serialize
50
+ self.class::SERIALIZER.new(self).call
51
+ rescue NameError => e
52
+ raise "SERIALIZER must be defined: #{e.message}"
53
+ end
54
+
55
+ # Class methods for binary serializable
56
+ module ClassMethods
57
+ # Parse record from bytestream
58
+ #
59
+ # @param stream [IO, StringIO] The input to read bytes from.
60
+ # @return [Solace::Instruction] Parsed instruction instance
61
+ def deserialize(stream)
62
+ self::DESERIALIZER.new(stream).call
63
+ rescue NameError => e
64
+ raise "DESERIALIZER must be defined: #{e.message}"
65
+ end
66
+ end
28
67
  end
29
68
  end
30
69
  end
@@ -5,62 +5,69 @@ require 'json'
5
5
  require 'uri'
6
6
 
7
7
  module Solace
8
+ # Connection to a Solana RPC node
9
+ #
10
+ # This class provides methods for sending JSON-RPC requests to a Solana RPC node and parsing responses.
11
+ # It includes methods for sending transactions, getting account information, and getting blockhashes.
12
+ #
13
+ # @example
14
+ # # Initialize the connection
15
+ # connection = Solace::Connection.new('http://localhost:8899', commitment: 'confirmed')
16
+ #
17
+ # # Get account information
18
+ # connection.get_account_info(account.address)
19
+ #
20
+ # # Request an airdrop
21
+ # result = connection.request_airdrop(account.address, 1000000)
22
+ #
23
+ # # Wait for the transaction to be finalized
24
+ # connection.wait_for_confirmed_signature('finalized') { result['result'] }
25
+ #
26
+ # @since 0.0.1
27
+ #
28
+ # rubocop:disable Metrics/ClassLength
8
29
  class Connection
30
+ # @!attribute [r] rpc_url
31
+ # The URL of the Solana RPC node
9
32
  attr_reader :rpc_url
10
33
 
11
- # !const default options
12
- DEFAULT_OPTIONS = {
13
- encoding: 'base64',
14
- commitment: 'confirmed'
15
- }.freeze
34
+ # @!attribute [r] default_options
35
+ # The default options for RPC requests
36
+ attr_reader :default_options
16
37
 
17
38
  # Initialize the connection with a default or custom RPC URL
18
39
  #
19
40
  # @param rpc_url [String] The URL of the Solana RPC node
41
+ # @param commitment [String] The commitment level for RPC requests
20
42
  # @return [Solace::Connection] The connection object
21
- def initialize(rpc_url = 'http://localhost:8899')
22
- @rpc_url = rpc_url
43
+ def initialize(rpc_url = 'http://localhost:8899', commitment: 'confirmed')
23
44
  @request_id = nil
45
+ @rpc_url = rpc_url
46
+
47
+ # Set default options
48
+ @default_options = {
49
+ commitment: commitment,
50
+ encoding: 'base64'
51
+ }
24
52
  end
25
53
 
26
- # Make an RPC request to the Solana node
54
+ # Sends a JSON-RPC request to the configured Solana RPC server.
27
55
  #
28
- # @param method [String] The RPC method to call
29
- # @param params [Array] Parameters for the RPC method
30
- # @return [Object] Result of the RPC call
56
+ # @param method [String] the JSON-RPC method name
57
+ # @param params [Array] the parameters for the RPC method
58
+ # @return [Hash] the parsed JSON response
59
+ # @raise [RuntimeError] if the response is not successful
31
60
  def rpc_request(method, params = [])
32
- uri = URI(rpc_url)
33
-
34
- req = Net::HTTP::Post.new(uri)
35
- req['Accept'] = 'application/json'
36
- req['Content-Type'] = 'application/json'
37
-
38
- @request_id = SecureRandom.uuid
39
-
40
- req.body = {
41
- jsonrpc: '2.0',
42
- id: @request_id,
43
- method: method,
44
- params: params
45
- }.to_json
46
-
47
- res = Net::HTTP.start(
48
- uri.hostname,
49
- uri.port,
50
- use_ssl: uri.scheme == 'https'
51
- ) do |http|
52
- http.request(req)
53
- end
54
-
55
- raise "RPC error: #{res.body}" unless res.is_a?(Net::HTTPSuccess)
56
-
57
- JSON.parse(res.body)
61
+ request = build_rpc_request(method, params)
62
+ response = perform_http_request(request)
63
+ handle_rpc_response(response)
58
64
  end
59
65
 
60
66
  # Request an airdrop of lamports to a given address
61
67
  #
62
68
  # @param pubkey [String] The public key of the account to receive the airdrop
63
69
  # @param lamports [Integer] Amount of lamports to airdrop
70
+ # @param [Hash{Symbol => Object}] options The options for the request
64
71
  # @return [String] The transaction signature of the airdrop
65
72
  def request_airdrop(pubkey, lamports, options = {})
66
73
  rpc_request(
@@ -68,7 +75,7 @@ module Solace
68
75
  [
69
76
  pubkey,
70
77
  lamports,
71
- DEFAULT_OPTIONS.merge(options)
78
+ default_options.merge(options)
72
79
  ]
73
80
  )
74
81
  end
@@ -97,7 +104,7 @@ module Solace
97
104
  'getAccountInfo',
98
105
  [
99
106
  pubkey,
100
- DEFAULT_OPTIONS
107
+ default_options
101
108
  ]
102
109
  )['result']
103
110
 
@@ -115,7 +122,21 @@ module Solace
115
122
  'getBalance',
116
123
  [
117
124
  pubkey,
118
- DEFAULT_OPTIONS
125
+ default_options
126
+ ]
127
+ )['result']['value']
128
+ end
129
+
130
+ # Get the balance of a token account
131
+ #
132
+ # @param token_account [String] The public key of the token account
133
+ # @return [Hash] Token account balance information with amount and decimals
134
+ def get_token_account_balance(token_account)
135
+ rpc_request(
136
+ 'getTokenAccountBalance',
137
+ [
138
+ token_account,
139
+ default_options
119
140
  ]
120
141
  )['result']['value']
121
142
  end
@@ -124,12 +145,13 @@ module Solace
124
145
  #
125
146
  # @param signature [String] The signature of the transaction
126
147
  # @return [Solace::Transaction] The transaction object
148
+ # @param [Hash{Symbol => Object}] options
127
149
  def get_transaction(signature, options = { maxSupportedTransactionVersion: 0 })
128
150
  rpc_request(
129
151
  'getTransaction',
130
152
  [
131
153
  signature,
132
- DEFAULT_OPTIONS.merge(options)
154
+ default_options.merge(options)
133
155
  ]
134
156
  )['result']
135
157
  end
@@ -143,7 +165,7 @@ module Solace
143
165
  'getSignatureStatuses',
144
166
  [
145
167
  signatures,
146
- DEFAULT_OPTIONS.merge({ 'searchTransactionHistory' => true })
168
+ default_options.merge({ 'searchTransactionHistory' => true })
147
169
  ]
148
170
  )['result']
149
171
  end
@@ -152,12 +174,13 @@ module Solace
152
174
  #
153
175
  # @param transaction [Solace::Transaction] The transaction to send
154
176
  # @return [String] The signature of the transaction
177
+ # @param [Hash{Symbol => Object}] options
155
178
  def send_transaction(transaction, options = {})
156
179
  rpc_request(
157
180
  'sendTransaction',
158
181
  [
159
182
  transaction,
160
- DEFAULT_OPTIONS.merge(options)
183
+ default_options.merge(options)
161
184
  ]
162
185
  )
163
186
  end
@@ -172,16 +195,50 @@ module Solace
172
195
  # Get the signature from the block
173
196
  signature = yield
174
197
 
198
+ interval = 0.1
199
+
175
200
  # Wait for confirmation
176
201
  loop do
177
202
  status = get_signature_status([signature]).dig('value', 0)
178
203
 
179
204
  break if status && status['confirmationStatus'] == commitment
180
205
 
181
- sleep 0.5
206
+ sleep interval
182
207
  end
183
208
 
184
209
  signature
185
210
  end
211
+
212
+ private
213
+
214
+ def build_rpc_request(method, params)
215
+ uri = URI(rpc_url)
216
+ req = Net::HTTP::Post.new(uri)
217
+ req['Accept'] = 'application/json'
218
+ req['Content-Type'] = 'application/json'
219
+ @request_id = SecureRandom.uuid
220
+
221
+ req.body = {
222
+ jsonrpc: '2.0',
223
+ id: @request_id,
224
+ method: method,
225
+ params: params
226
+ }.to_json
227
+
228
+ [uri, req]
229
+ end
230
+
231
+ def perform_http_request((uri, req))
232
+ Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') do |http|
233
+ http.request(req)
234
+ end
235
+ end
236
+
237
+ def handle_rpc_response(response)
238
+ raise "RPC error: #{response.body}" unless response.is_a?(Net::HTTPSuccess)
239
+
240
+ JSON.parse(response.body)
241
+ end
186
242
  end
243
+ # rubocop:enable Metrics/ClassLength
187
244
  end
@@ -7,46 +7,39 @@
7
7
  # @return [Module] Constants module
8
8
  module Solace
9
9
  module Constants
10
- # @!const SYSTEM_PROGRAM_ID
10
+ # @!attribute SYSTEM_PROGRAM_ID
11
11
  # The public key of the System Program (native SOL transfers, account creation, etc)
12
12
  # This is the same across all Solana clusters
13
- # @return [String]
14
13
  SYSTEM_PROGRAM_ID = '11111111111111111111111111111111'
15
14
 
16
- # @!const SYSVAR_RENT_PROGRAM_ID
15
+ # @!attribute SYSVAR_RENT_PROGRAM_ID
17
16
  # The public key of the Rent Program
18
17
  # This is the same across all Solana clusters
19
- # @return [String]
20
18
  SYSVAR_RENT_PROGRAM_ID = 'SysvarRent111111111111111111111111111111111'
21
19
 
22
- # @!const COMPUTE_BUDGET_PROGRAM_ID
20
+ # @!attribute COMPUTE_BUDGET_PROGRAM_ID
23
21
  # The public key of the Compute Budget Program
24
22
  # This is the same across all Solana clusters
25
- # @return [String]
26
23
  COMPUTE_BUDGET_PROGRAM_ID = 'ComputeBudget111111111111111111111111111111'
27
24
 
28
- # @!const TOKEN_PROGRAM_ID
25
+ # @!attribute TOKEN_PROGRAM_ID
29
26
  # The public key of the SPL Token Program
30
27
  # This is the same across all Solana clusters
31
- # @return [String]
32
28
  TOKEN_PROGRAM_ID = 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA'
33
29
 
34
- # @!const ASSOCIATED_TOKEN_ACCOUNT_PROGRAM_ID
30
+ # @!attribute ASSOCIATED_TOKEN_ACCOUNT_PROGRAM_ID
35
31
  # The public key of the Associated Token Account Program
36
32
  # This is the same across all Solana clusters
37
- # @return [String]
38
33
  ASSOCIATED_TOKEN_ACCOUNT_PROGRAM_ID = 'ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL'
39
34
 
40
- # @!const MEMO_PROGRAM_ID
35
+ # @!attribute MEMO_PROGRAM_ID
41
36
  # The public key of the Memo Program
42
37
  # This is the same across all Solana clusters
43
- # @return [String]
44
38
  MEMO_PROGRAM_ID = 'MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr'
45
39
 
46
- # @!const ADDRESS_LOOKUP_TABLE_PROGRAM_ID
40
+ # @!attribute ADDRESS_LOOKUP_TABLE_PROGRAM_ID
47
41
  # The public key of the Address Lookup Table Program
48
42
  # This is the same across all Solana clusters
49
- # @return [String]
50
43
  ADDRESS_LOOKUP_TABLE_PROGRAM_ID = 'AddressLookupTab1e1111111111111111111111111'
51
44
  end
52
45
  end
@@ -1,37 +1,48 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # =============================
4
- # Instruction
5
- # =============================
6
- #
7
- # Class representing a Solana instruction.
8
- #
9
- # The BufferLayout is:
10
- # - [Program index (1 byte)]
11
- # - [Number of accounts (compact u16)]
12
- # - [Accounts (variable length)]
13
- # - [Data length (compact u16)]
14
- # - [Data (variable length)]
15
- #
16
3
  module Solace
17
- class Instruction < Solace::SerializableRecord
18
- # @!const SERIALIZER
4
+ # Class representing a Solana instruction.
5
+ #
6
+ # Handles serialization and deserialization of instruction fields. Instructions are used to
7
+ # encode the data that is sent to a program on the Solana blockchain. Instructions are part of
8
+ # transaction messages. All instruction builders and instruction composers return an instance of
9
+ # this class.
10
+ #
11
+ # The BufferLayout is:
12
+ # - [Program index (1 byte)]
13
+ # - [Number of accounts (compact u16)]
14
+ # - [Accounts (variable length)]
15
+ # - [Data length (compact u16)]
16
+ # - [Data (variable length)]
17
+ #
18
+ # @example
19
+ # instruction = Solace::Instruction.new(
20
+ # program_index: 0,
21
+ # accounts: [1, 2, 3],
22
+ # data: [4, 5, 6]
23
+ # )
24
+ #
25
+ # @since 0.0.1
26
+ class Instruction
27
+ include Solace::Concerns::BinarySerializable
28
+
29
+ # @!attribute SERIALIZER
19
30
  # @return [Solace::Serializers::InstructionSerializer] The serializer for the instruction
20
31
  SERIALIZER = Solace::Serializers::InstructionSerializer
21
32
 
22
- # @!const DESERIALIZER
33
+ # @!attribute DESERIALIZER
23
34
  # @return [Solace::Serializers::InstructionDeserializer] The deserializer for the instruction
24
35
  DESERIALIZER = Solace::Serializers::InstructionDeserializer
25
36
 
26
- # @!attribute [rw] program_index
37
+ # @!attribute [rw] program_index
27
38
  # @return [Integer] The program index of the instruction
28
39
  attr_accessor :program_index
29
40
 
30
- # @!attribute [rw] accounts
41
+ # @!attribute [rw] accounts
31
42
  # @return [Array<Integer>] The accounts of the instruction
32
43
  attr_accessor :accounts
33
44
 
34
- # @!attribute [rw] data
45
+ # @!attribute [rw] data
35
46
  # @return [Array<Integer>] The instruction data
36
47
  attr_accessor :data
37
48
  end
@@ -3,8 +3,23 @@
3
3
  module Solace
4
4
  module Instructions
5
5
  module AssociatedTokenAccount
6
- # A class to build the CreateAssociatedTokenAccount instruction for the Associated Token Account Program.
7
- # This is a special "all-in-one" instruction that creates and initializes the account.
6
+ # Instruction for creating an Associated Token Account.
7
+ #
8
+ # This is a special "all-in-one" instruction that creates and initializes the account. It
9
+ # is used to create an Associated Token Account (ATA) for a given mint and owner.
10
+ #
11
+ # @example Build a CreateAssociatedTokenAccount instruction
12
+ # instruction = Solace::Instructions::AssociatedTokenAccount::CreateAssociatedTokenAccountInstruction.build(
13
+ # funder_index: 0,
14
+ # associated_token_account_index: 1,
15
+ # owner_index: 2,
16
+ # mint_index: 3,
17
+ # system_program_index: 4,
18
+ # token_program_index: 5,
19
+ # program_index: 6
20
+ # )
21
+ #
22
+ # @since 0.0.2
8
23
  class CreateAssociatedTokenAccountInstruction
9
24
  # !@const INSTRUCTION_INDEX
10
25
  # Instruction index for CreateAssociatedTokenAccount
@@ -65,4 +80,4 @@ module Solace
65
80
  end
66
81
  end
67
82
  end
68
- end
83
+ end