solace 0.0.10 → 0.1.0

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 (33) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +104 -23
  3. data/README.md +10 -8
  4. data/lib/solace/composers/base.rb +35 -0
  5. data/lib/solace/composers/spl_token_program_initialize_mint_composer.rb +95 -0
  6. data/lib/solace/composers/spl_token_program_mint_to_composer.rb +86 -0
  7. data/lib/solace/composers/spl_token_program_transfer_composer.rb +90 -0
  8. data/lib/solace/composers/system_program_create_account_composer.rb +98 -0
  9. data/lib/solace/connection.rb +88 -13
  10. data/lib/solace/errors/confirmation_timeout.rb +18 -4
  11. data/lib/solace/errors/http_error.rb +16 -1
  12. data/lib/solace/errors/parse_error.rb +15 -1
  13. data/lib/solace/errors/rpc_error.rb +17 -1
  14. data/lib/solace/errors.rb +8 -3
  15. data/lib/solace/instructions/associated_token_account/create_associated_token_account_instruction.rb +9 -2
  16. data/lib/solace/instructions/spl_token/initialize_mint_instruction.rb +0 -1
  17. data/lib/solace/instructions/spl_token/transfer_instruction.rb +21 -0
  18. data/lib/solace/instructions/system_program/create_account_instruction.rb +30 -0
  19. data/lib/solace/instructions/system_program/transfer_instruction.rb +11 -0
  20. data/lib/solace/programs/associated_token_account.rb +57 -30
  21. data/lib/solace/programs/base.rb +23 -0
  22. data/lib/solace/programs/spl_token.rb +197 -125
  23. data/lib/solace/serializers/base_serializer.rb +29 -1
  24. data/lib/solace/tokens/token.rb +53 -0
  25. data/lib/solace/tokens.rb +86 -0
  26. data/lib/solace/transaction.rb +24 -21
  27. data/lib/solace/transaction_composer.rb +77 -3
  28. data/lib/solace/utils/account_context.rb +1 -1
  29. data/lib/solace/utils/codecs.rb +17 -0
  30. data/lib/solace/utils/pda.rb +13 -5
  31. data/lib/solace/version.rb +3 -2
  32. data/lib/solace.rb +38 -11
  33. metadata +21 -1
@@ -42,6 +42,12 @@ module Solace
42
42
  # The default options for RPC requests
43
43
  attr_reader :default_options
44
44
 
45
+ # Last fetched blockhash
46
+ attr_reader :last_fetched_blockhash
47
+
48
+ # Last fetched blockhash timestamp
49
+ attr_reader :last_fetched_block_height
50
+
45
51
  # Initialize the connection with a default or custom RPC URL
46
52
  #
47
53
  # @param rpc_url [String] The URL of the Solana RPC node
@@ -69,6 +75,27 @@ module Solace
69
75
  }
70
76
  end
71
77
 
78
+ # Gets the version of the Solana node
79
+ #
80
+ # @return [Hash] The version information
81
+ def get_version
82
+ @rpc_client.rpc_request('getVersion')['result']
83
+ end
84
+
85
+ # Get the health status of the Solana node
86
+ #
87
+ # @return [String] The health status
88
+ def get_health
89
+ @rpc_client.rpc_request('getHealth')['result']
90
+ end
91
+
92
+ # Get the genesis hash of the Solana node
93
+ #
94
+ # @return [String] The genesis hash
95
+ def get_genesis_hash
96
+ @rpc_client.rpc_request('getGenesisHash')['result']
97
+ end
98
+
72
99
  # Request an airdrop of lamports to a given address
73
100
  #
74
101
  # @param pubkey [String] The public key of the account to receive the airdrop
@@ -97,12 +124,34 @@ module Solace
97
124
 
98
125
  # Get the latest blockhash from the Solana node
99
126
  #
127
+ # Stores the last fetched blockhash and last valid block height in the connection, as
128
+ # different clients may need to access these values.
129
+ #
130
+ # @example
131
+ # # Initialize the connection
132
+ # connection = Solace::Connection.new('http://localhost:8899', commitment: 'confirmed')
133
+ #
134
+ # # Get the latest blockhash
135
+ # blockhash, last_valid_block_height = connection.get_latest_blockhash
136
+ #
137
+ # puts "Latest blockhash: #{blockhash}"
138
+ # puts "Last valid block height: #{last_valid_block_height}"
139
+ #
140
+ # # Access the last fetched blockhash and height from the connection
141
+ # puts "Stored blockhash: #{connection.last_fetched_blockhash}"
142
+ # puts "Stored last valid block height: #{connection.last_fetched_block_height}"
143
+ #
100
144
  # @return [Array<String, Integer>] The latest blockhash and lastValidBlockHeight
101
145
  def get_latest_blockhash
102
- @rpc_client
103
- .rpc_request('getLatestBlockhash', [build_get_latest_blockhash_options])
104
- .dig('result', 'value')
105
- .values_at('blockhash', 'lastValidBlockHeight')
146
+ result = @rpc_client
147
+ .rpc_request('getLatestBlockhash', [build_get_latest_blockhash_options])
148
+ .dig('result', 'value')
149
+
150
+ # Set the last fetched blockhash and last valid block height in the connection
151
+ @last_fetched_blockhash, @last_fetched_block_height = result.values_at('blockhash', 'lastValidBlockHeight')
152
+
153
+ # Return the blockhash and last valid block height
154
+ [@last_fetched_blockhash, @last_fetched_block_height]
106
155
  end
107
156
 
108
157
  # Get the minimum required lamports for rent exemption
@@ -121,6 +170,14 @@ module Solace
121
170
  @rpc_client.rpc_request('getAccountInfo', [pubkey, default_options]).dig('result', 'value')
122
171
  end
123
172
 
173
+ # Get multiple accounts information from the Solana node
174
+ #
175
+ # @param pubkeys [Array<String>] The public keys of the accounts
176
+ # @return [Array<Object>] The accounts information
177
+ def get_multiple_accounts(pubkeys)
178
+ @rpc_client.rpc_request('getMultipleAccounts', [pubkeys, default_options]).dig('result', 'value')
179
+ end
180
+
124
181
  # Get the balance of a specific account
125
182
  #
126
183
  # @param pubkey [String] The public key of the account
@@ -137,10 +194,19 @@ module Solace
137
194
  @rpc_client.rpc_request('getTokenAccountBalance', [token_account, default_options]).dig('result', 'value')
138
195
  end
139
196
 
197
+ # Gets the token accounts by owner
198
+ #
199
+ # @param owner [String] The public key of the owner
200
+ # @return [Array<Hash>] The token accounts owned by the owner for the specified mint
201
+ def get_token_accounts_by_owner(owner)
202
+ params = [owner, { programId: Constants::TOKEN_PROGRAM_ID }, default_options]
203
+ @rpc_client.rpc_request('getTokenAccountsByOwner', params).dig('result', 'value')
204
+ end
205
+
140
206
  # Get the transaction by signature
141
207
  #
142
208
  # @param signature [String] The signature of the transaction
143
- # @return [Solace::Transaction] The transaction object
209
+ # @return [Transaction] The transaction object
144
210
  # @param [Hash{Symbol => Object}] options
145
211
  def get_transaction(signature, options = { maxSupportedTransactionVersion: 0 })
146
212
  @rpc_client.rpc_request('getTransaction', [signature, default_options.merge(options)])['result']
@@ -173,9 +239,9 @@ module Solace
173
239
  get_signature_statuses([signature])
174
240
  end
175
241
 
176
- # Builds send_tranaction options
242
+ # Builds send_transaction options
177
243
  #
178
- # @params [Hash] The overrides for the options
244
+ # @param overrides[Hash] The overrides for the options
179
245
  # @return [Hash] The options for the send_transaction call
180
246
  def build_send_transaction_options(overrides)
181
247
  {
@@ -188,13 +254,22 @@ module Solace
188
254
 
189
255
  # Send a transaction to the Solana node
190
256
  #
191
- # @param transaction [Solace::Transaction] The transaction to send
257
+ # @param transaction [Transaction] The transaction to send
192
258
  # @param [Hash{Symbol => Object}] overrides
193
259
  # @return [String] The signature of the transaction
194
260
  def send_transaction(transaction, overrides = {})
195
261
  @rpc_client.rpc_request('sendTransaction', [transaction, build_send_transaction_options(overrides)])
196
262
  end
197
263
 
264
+ # Simulate a transaction on the Solana node
265
+ #
266
+ # @param transaction [Transaction] The transaction to simulate
267
+ # @param [Hash{Symbol => Object}] overrides
268
+ # @return [Object] The result of the simulation
269
+ def simulate_transaction(transaction, overrides = {})
270
+ @rpc_client.rpc_request('simulateTransaction', [transaction, build_send_transaction_options(overrides)])
271
+ end
272
+
198
273
  # Wait until the yielded signature reaches the desired commitment or timeout.
199
274
  #
200
275
  # @param commitment [String] One of "processed", "confirmed", "finalized"
@@ -214,7 +289,7 @@ module Solace
214
289
  deadline = monotonic_deadline(timeout)
215
290
 
216
291
  # Wait for confirmation
217
- until dealine_passed?(deadline)
292
+ until deadline_passed?(deadline)
218
293
  return signature if commitment_reached?(signature, commitment)
219
294
 
220
295
  sleep interval
@@ -244,15 +319,15 @@ module Solace
244
319
 
245
320
  # Checks if a timeout deadline has been reached
246
321
  #
247
- # @params deadline [Integer] The deadline for the timeout
248
- # @return [boolean] whether the dealine has passed
249
- def dealine_passed?(deadline)
322
+ # @param deadline [Integer] The deadline for the timeout
323
+ # @return [Boolean] whether the deadline has passed
324
+ def deadline_passed?(deadline)
250
325
  Process.clock_gettime(Process::CLOCK_MONOTONIC) >= deadline
251
326
  end
252
327
 
253
328
  # Sets a deadline given a timeout in seconds
254
329
  #
255
- # @params seconds [Integer] The seconds for the deadline
330
+ # @param seconds [Integer] The seconds for the deadline
256
331
  # @return [Integer] The deadline in seconds
257
332
  def monotonic_deadline(seconds)
258
333
  Process.clock_gettime(Process::CLOCK_MONOTONIC) + seconds
@@ -2,7 +2,21 @@
2
2
 
3
3
  module Solace
4
4
  module Errors
5
- # Waiting for confirmation exceeded timeout
5
+ # Raised when a transaction confirmation times out.
6
+ #
7
+ # This error is raised when waiting for a transaction to be confirmed by the
8
+ # network exceeds the specified timeout period. This can happen when the
9
+ # network is congested, the transaction fee is too low, or the transaction
10
+ # was not successfully processed by the validators.
11
+ #
12
+ # @example Handling confirmation timeout
13
+ # begin
14
+ # connection.wait_for_confirmed_signature(signature, timeout: 30)
15
+ # rescue Solace::Errors::ConfirmationTimeout => e
16
+ # puts "Transaction confirmation timed out: #{e.message}"
17
+ # end
18
+ #
19
+ # @since 0.0.1
6
20
  class ConfirmationTimeout < StandardError
7
21
  attr_reader :signature, :commitment, :timeout
8
22
 
@@ -19,9 +33,9 @@ module Solace
19
33
 
20
34
  # Formats a confirmation timeout error
21
35
  #
22
- # @params [String] signature The signature of the transaction
23
- # @params [String] commitment The commitment level not reached
24
- # @params [Integer] timeout The time out reached
36
+ # @param signature [String] The signature of the transaction
37
+ # @param commitment [String] The commitment level not reached
38
+ # @param timeout [Integer] The time out reached
25
39
  # @return [Solace::Errors::ConfirmationTimeout] The formatted error
26
40
  def self.format(signature, commitment, timeout)
27
41
  new(
@@ -2,7 +2,22 @@
2
2
 
3
3
  module Solace
4
4
  module Errors
5
- # Non-2xx HTTP or low-level network issues
5
+ # Raised when an HTTP request to the RPC node fails.
6
+ #
7
+ # This error is raised for network-level failures when communicating with the
8
+ # Solana RPC node, including connection timeouts, DNS resolution failures,
9
+ # and HTTP protocol errors. This is distinct from RPC-level errors, which are
10
+ # raised as {Solace::Errors::RPCError}.
11
+ #
12
+ # @example Handling HTTP errors
13
+ # begin
14
+ # connection.get_account_info(address)
15
+ # rescue Solace::Errors::HTTPError => e
16
+ # puts "Network error: #{e.message}"
17
+ # end
18
+ #
19
+ # @see Solace::Errors::RPCError
20
+ # @since 0.0.1
6
21
  class HTTPError < StandardError
7
22
  attr_reader :code, :body
8
23
 
@@ -2,7 +2,21 @@
2
2
 
3
3
  module Solace
4
4
  module Errors
5
- # JSON parsing failed
5
+ # Raised when parsing or deserializing data fails.
6
+ #
7
+ # This error is raised when the gem encounters data that cannot be properly
8
+ # parsed or deserialized, such as malformed JSON responses from the RPC node,
9
+ # invalid binary data, or unexpected data structures. This typically indicates
10
+ # either a bug in the gem or an incompatibility with the RPC node's response format.
11
+ #
12
+ # @example Handling parse errors
13
+ # begin
14
+ # transaction = Solace::Transaction.deserialize(binary_data)
15
+ # rescue Solace::Errors::ParseError => e
16
+ # puts "Failed to parse transaction: #{e.message}"
17
+ # end
18
+ #
19
+ # @since 0.0.1
6
20
  class ParseError < StandardError
7
21
  attr_reader :body
8
22
 
@@ -2,7 +2,23 @@
2
2
 
3
3
  module Solace
4
4
  module Errors
5
- # JSON-RPC returned an "error" object
5
+ # Raised when the RPC node returns an error response.
6
+ #
7
+ # This error is raised when the Solana RPC node successfully processes the HTTP
8
+ # request but returns an error in the JSON-RPC response. This includes errors
9
+ # like invalid parameters, insufficient funds, blockhash not found, and other
10
+ # RPC method-specific errors. The error message and code from the RPC response
11
+ # are included in the exception.
12
+ #
13
+ # @example Handling RPC errors
14
+ # begin
15
+ # connection.send_transaction(transaction)
16
+ # rescue Solace::Errors::RPCError => e
17
+ # puts "RPC error (code #{e.code}): #{e.message}"
18
+ # end
19
+ #
20
+ # @see Solace::Errors::HTTPError
21
+ # @since 0.0.1
6
22
  class RPCError < StandardError
7
23
  attr_reader :rpc_code, :rpc_message, :rpc_data
8
24
 
data/lib/solace/errors.rb CHANGED
@@ -1,11 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Solace
4
- # Error handling module
4
+ # The Errors module contains custom exception classes for the Solace gem.
5
5
  #
6
- # This module provides error classes for handling different types of errors that may occur during
7
- # Solana RPC requests and processing transactions.
6
+ # These exceptions provide specific error handling for various failure scenarios
7
+ # when interacting with the Solana blockchain, including:
8
+ # - {Solace::Errors::HTTPError} - HTTP communication failures
9
+ # - {Solace::Errors::RPCError} - RPC method errors returned by the node
10
+ # - {Solace::Errors::ParseError} - Data parsing and deserialization errors
11
+ # - {Solace::Errors::ConfirmationTimeout} - Transaction confirmation timeouts
8
12
  #
13
+ # @see Solace::Connection
9
14
  # @since 0.0.8
10
15
  module Errors
11
16
  # JSON-RPC Errors
@@ -2,6 +2,15 @@
2
2
 
3
3
  module Solace
4
4
  module Instructions
5
+ # The AssociatedTokenAccount module contains instruction builders for the
6
+ # Associated Token Account Program.
7
+ #
8
+ # The Associated Token Account (ATA) Program provides a deterministic way to
9
+ # derive token account addresses for a given wallet and mint. This ensures that
10
+ # each wallet has a single, predictable token account for each token type.
11
+ #
12
+ # @see https://spl.solana.com/associated-token-account
13
+ # @since 0.0.2
5
14
  module AssociatedTokenAccount
6
15
  # Instruction for creating an Associated Token Account.
7
16
  #
@@ -18,8 +27,6 @@ module Solace
18
27
  # token_program_index: 5,
19
28
  # program_index: 6
20
29
  # )
21
- #
22
- # @since 0.0.2
23
30
  class CreateAssociatedTokenAccountInstruction
24
31
  # !@const INSTRUCTION_INDEX
25
32
  # Instruction index for CreateAssociatedTokenAccount
@@ -18,7 +18,6 @@ module Solace
18
18
  # program_index: 3
19
19
  # )
20
20
  #
21
- # @see Solace::Instructions::SystemProgram::CreateAccountInstruction
22
21
  # @since 0.0.2
23
22
  class InitializeMintInstruction
24
23
  # Instruction index for Initialize Mint
@@ -2,6 +2,27 @@
2
2
 
3
3
  module Solace
4
4
  module Instructions
5
+ # The SplToken module contains instruction builders for the SPL Token Program.
6
+ #
7
+ # The SPL Token Program is Solana's standard for fungible and non-fungible tokens.
8
+ # It provides instructions for creating token mints, creating token accounts,
9
+ # minting tokens, transferring tokens, and managing token authorities.
10
+ #
11
+ # This module contains classes that build the low-level instruction data required
12
+ # to interact with the SPL Token Program. Each class corresponds to a specific
13
+ # instruction in the program.
14
+ #
15
+ # @example Building a transfer instruction
16
+ # instruction = Solace::Instructions::SplToken::TransferInstruction.build(
17
+ # source_index: 0,
18
+ # destination_index: 1,
19
+ # owner_index: 2,
20
+ # program_index: 3,
21
+ # amount: 1_000_000
22
+ # )
23
+ #
24
+ # @see https://spl.solana.com/token
25
+ # @since 0.0.2
5
26
  module SplToken
6
27
  # Instruction for transferring SPL tokens.
7
28
  #
@@ -1,6 +1,36 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Solace
4
+ # The Instructions module contains low-level instruction builders for Solana programs.
5
+ #
6
+ # Instructions are the fundamental building blocks of Solana transactions. Each
7
+ # instruction represents a single operation to be executed by an on-chain program.
8
+ # The classes in this module build the binary instruction data and specify the
9
+ # accounts required for each operation.
10
+ #
11
+ # Instructions are organized by program:
12
+ # - {Solace::Instructions::SystemProgram} - System Program instructions
13
+ # - {Solace::Instructions::SplToken} - SPL Token Program instructions
14
+ # - {Solace::Instructions::AssociatedTokenAccount} - Associated Token Account Program instructions
15
+ #
16
+ # Being a low-level primitive, you must build instructions manually.
17
+ #
18
+ # @example Building a system transfer instruction
19
+ #
20
+ # # Assuming the transaction's accounts are ordered as follows:
21
+ # accounts = %w[from_address to_address system_program_id]
22
+ #
23
+ # # Build the instruction by specifying the account indices directly
24
+ # instruction = Solace::Instructions::SystemProgram::TransferInstruction.build(
25
+ # from_index: 0,
26
+ # to_index: 1,
27
+ # program_index: 2,
28
+ # lamports: 1_000_000
29
+ # )
30
+ #
31
+ # @see Solace::Instruction
32
+ # @see Solace::Composers
33
+ # @since 0.0.1
4
34
  module Instructions
5
35
  module SystemProgram
6
36
  # Instruction for creating a new account.
@@ -2,6 +2,17 @@
2
2
 
3
3
  module Solace
4
4
  module Instructions
5
+ # The SystemProgram module contains instruction builders for the System Program.
6
+ #
7
+ # The System Program is Solana's native program for fundamental operations like
8
+ # creating accounts, transferring SOL, and allocating account data. It is the
9
+ # only program that can create new accounts and assign them to other programs.
10
+ #
11
+ # This module contains classes that build the low-level instruction data required
12
+ # to interact with the System Program.
13
+ #
14
+ # @see https://docs.solana.com/developing/runtime-facilities/programs#system-program
15
+ # @since 0.0.1
5
16
  module SystemProgram
6
17
  # Instruction for transferring SOL.
7
18
  #
@@ -24,20 +24,21 @@ module Solace
24
24
  # # Create an associated token account
25
25
  # result = program.create_associated_token_account(
26
26
  # payer: payer,
27
+ # funder: funder,
27
28
  # owner: owner,
28
29
  # mint: mint
29
30
  # )
30
31
  #
31
32
  # # Wait for the transaction to be finalized
32
- # @connection.wait_for_confirmed_signature('finalized') { result['result'] }
33
+ # connection.wait_for_confirmed_signature('finalized') { result['result'] }
33
34
  #
34
35
  # @since 0.0.2
35
36
  class AssociatedTokenAccount < Base
36
37
  class << self
37
38
  # Gets the address of an associated token account.
38
39
  #
39
- # @param owner [Solace::Keypair, Solace::PublicKey] The keypair of the owner.
40
- # @param mint [Solace::Keypair, Solace::PublicKey] The keypair of the mint.
40
+ # @param owner [Keypair, PublicKey] The keypair of the owner.
41
+ # @param mint [Keypair, PublicKey] The keypair of the mint.
41
42
  # @return [String] The address of the associated token account.
42
43
  def get_address(owner:, mint:)
43
44
  Solace::Utils::PDA.find_program_address(
@@ -68,48 +69,76 @@ module Solace
68
69
 
69
70
  # Gets the address of an associated token account, creating it if it doesn't exist.
70
71
  #
71
- # @param payer [Solace::Keypair] The keypair that will pay for fees and rent.
72
- # @param owner [Solace::Keypair, Solace::PublicKey] The keypair of the owner.
73
- # @param mint [Solace::Keypair, Solace::PublicKey] The keypair of the mint.
74
- # @param commitment [String] The commitment level for the get_account_info call.
72
+ # @param payer [Keypair] The keypair that will pay for fees and rent.
73
+ # @param funder [Keypair] The keypair that will pay for rent of the new associated token account.
74
+ # @param owner [Keypair, PublicKey] The keypair of the owner.
75
+ # @param mint [Keypair, PublicKey] The keypair of the mint.
75
76
  # @return [String] The address of the associated token account
76
- def get_or_create_address(payer:, owner:, mint:, commitment: 'confirmed')
77
- ata_address, _bump = get_address(owner: owner, mint: mint)
77
+ def get_or_create_address(
78
+ payer:,
79
+ funder:,
80
+ owner:,
81
+ mint:
82
+ )
83
+ ata_address, = get_address(owner: owner, mint: mint)
78
84
 
79
- account_balance = @connection.get_account_info(ata_address)
85
+ account_balance = connection.get_account_info(ata_address)
80
86
 
81
87
  return ata_address unless account_balance.nil?
82
88
 
83
- response = create_associated_token_account(payer: payer, owner: owner, mint: mint)
84
-
85
- raise 'Failed to create associated token account' unless response['result']
89
+ tx = create_associated_token_account(
90
+ payer: payer,
91
+ funder: funder,
92
+ owner: owner,
93
+ mint: mint
94
+ )
86
95
 
87
- @connection.wait_for_confirmed_signature(commitment) { response }
96
+ connection.wait_for_confirmed_signature { tx.signature }
88
97
 
89
98
  ata_address
90
99
  end
91
100
 
92
101
  # Creates a new associated token account.
93
102
  #
94
- # @param options [Hash] Options for calling the prepare_create_associated_token_account method.
95
- # @return [String] The signature of the transaction.
96
- def create_associated_token_account(**options)
97
- tx = prepare_create_associated_token_account(**options)
103
+ # @param payer [#to_s, Keypair] The keypair that will pay for fees and rent.
104
+ # @param sign [Boolean] Whether to sign the transaction before sending it.
105
+ # @param execute [Boolean] Whether to send the transaction to the cluster.
106
+ # @param composer_opts [Hash] Options for calling the compose_create_associated_token_account method.
107
+ # @return [Transaction] The created or sent transaction.
108
+ def create_associated_token_account(
109
+ payer:,
110
+ sign: true,
111
+ execute: true,
112
+ **composer_opts
113
+ )
114
+ composer = compose_create_associated_token_account(**composer_opts)
115
+
116
+ yield composer if block_given?
117
+
118
+ tx = composer
119
+ .set_fee_payer(payer)
120
+ .compose_transaction
121
+
122
+ if sign
123
+ tx.sign(
124
+ payer,
125
+ composer_opts[:funder]
126
+ )
98
127
 
99
- tx.sign(options[:payer])
128
+ connection.send_transaction(tx.serialize) if execute
129
+ end
100
130
 
101
- @connection.send_transaction(tx.serialize)
131
+ tx
102
132
  end
103
133
 
104
134
  # Prepares a new associated token account and returns the signed transaction.
105
135
  #
106
- # @param owner [Solace::Keypair, Solace::PublicKey] The keypair of the owner.
107
- # @param mint [Solace::Keypair, Solace::PublicKey] The keypair of the mint.
108
- # @param payer [Solace::Keypair] The keypair that will pay for fees and rent.
109
- # @return [Solace::Transaction] The signed transaction.
110
- #
111
- def prepare_create_associated_token_account(
112
- payer:,
136
+ # @param owner [#to_s, PublicKey] The keypair of the owner.
137
+ # @param mint [#to_s, PublicKey] The keypair of the mint.
138
+ # @param funder [#to_s, PublicKey] The keypair that will pay for rent of the new associated token account.
139
+ # @return [Transaction] The signed transaction.
140
+ def compose_create_associated_token_account(
141
+ funder:,
113
142
  owner:,
114
143
  mint:
115
144
  )
@@ -118,15 +147,13 @@ module Solace
118
147
  ix = Solace::Composers::AssociatedTokenAccountProgramCreateAccountComposer.new(
119
148
  mint: mint,
120
149
  owner: owner,
121
- funder: payer,
150
+ funder: funder,
122
151
  ata_address: ata_address
123
152
  )
124
153
 
125
154
  TransactionComposer
126
155
  .new(connection: connection)
127
- .set_fee_payer(payer)
128
156
  .add_instruction(ix)
129
- .compose_transaction
130
157
  end
131
158
  end
132
159
  end
@@ -3,6 +3,29 @@
3
3
  # lib/solace/programs/base.rb
4
4
 
5
5
  module Solace
6
+ # The Programs module contains high-level interfaces to Solana on-chain programs.
7
+ #
8
+ # Programs in this module provide convenient methods for interacting with
9
+ # on-chain programs without needing to manually construct instructions or
10
+ # manage account ordering. They serve as a bridge between the low-level
11
+ # instruction builders and high-level application code.
12
+ #
13
+ # Each program class corresponds to a specific on-chain program:
14
+ # - {Solace::Programs::SplToken} - SPL Token Program
15
+ # - {Solace::Programs::AssociatedTokenAccount} - Associated Token Account Program
16
+ #
17
+ # @example Using a program interface
18
+ # token_program = Solace::Programs::SplToken.new(connection)
19
+ # token_program.transfer(
20
+ # to:,
21
+ # from:,
22
+ # owner:,
23
+ # amount:
24
+ # )
25
+ #
26
+ # @see Solace::Programs::SplToken
27
+ # @see Solace::Programs::AssociatedTokenAccount
28
+ # @since 0.0.2
6
29
  module Programs
7
30
  # Base class for program-specific clients.
8
31
  #