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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 669a517f72b280a594613b55fcd3e86c6e0f7ef9ba3d6633b0edfbd5dc5b0a0c
4
- data.tar.gz: a542d3ce4edaeb81d3c6e8aee35fadfb9df4a4cd5a618f9f643ac46544f4cc65
3
+ metadata.gz: 844d1bceeb32ec4fb6758548f24c8a0b04b5ef534cd2d387b6146a7923ee2ca0
4
+ data.tar.gz: 4ea095f315b2feac568e5bf4361986b19fe951085050a13250f9e6e84065c51f
5
5
  SHA512:
6
- metadata.gz: c43a013d3007b0853a5501c96dc7b2e737b0aefa5d35844008127ddcdfd59c0770e4ceaf9db99086aa69c294ae20563b022b3d6e370be84701c9fe8a453ce25d
7
- data.tar.gz: 42eab84e19bf00741e1c29a50facb39966f3020a005c2baa3ee63d545d6a43bcc267cb86d17ba09cb05be6d64875504c9a557275f9c365f6ce5764ce95501baf
6
+ metadata.gz: 166e17cb2a4fea1dac6e3497d064402bdce4477797d22f57f7812ee1faacf7ea9c77d94bbfa9172a4f1b92ceaacba2fef007ee0018d3ba4360ac568eefb3c3e8
7
+ data.tar.gz: cdf77b2bf7a7b813aefc1f80f6405a371ff82aad3448097b6030eb74028a770aac282697f128746dd001668171032524aa80906091cebfd871eea98335c1710d
data/CHANGELOG CHANGED
@@ -1,45 +1,126 @@
1
1
  # Change Log
2
2
  All notable changes to this project will be documented in this file.
3
-
3
+
4
4
  The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/).
5
5
 
6
6
  ### Template
7
7
 
8
8
  ```markdown
9
9
  ## [VERSION] - yyyy-mm-dd
10
-
10
+
11
11
  ### Added
12
- 1.
12
+ 1.
13
13
 
14
14
  ### Changed
15
-
15
+
16
16
  ### Fixed
17
17
  ```
18
18
 
19
- ## [0.0.10] - yyyy-mm-dd
20
-
19
+ Got it — here’s your changelog tidied up for clarity and consistency without changing any of the substance. I only fixed grammar/typos and tightened phrasing.
20
+
21
+ ---
22
+
23
+ ## [0.1.0] - 2025-18-10
24
+
25
+ **NOTE (Breaking):**
26
+ All previous `prepare_*` Program methods have been renamed to `compose_*` and now return an **unsigned composer instance**. This enables composition and extensibility that weren’t possible when methods returned a signed transaction that was only editable via low-level manipulation.
27
+ Additionally, unless explicitly required by a composer’s instruction, the `payer:` keyword has been removed from the new `compose_*` methods and is instead only used in their execution counterparts (e.g., `compose_mint_to` → `mint_to`). This allows specifying the fee payer when building the final transaction, while keeping composition steps payer-agnostic.
28
+
21
29
  ### Added
22
- 1.
30
+
31
+ 1. **`Solace::Tokens`** — a structured registry and lookup system for Solana token metadata.
32
+
33
+ * Developers can define token details via a YAML configuration file scoped by network (e.g., `mainnet`, `devnet`).
34
+ * Programmatic access to token metadata:
35
+
36
+ ```ruby
37
+ Solace::Tokens.load(path: 'tokens.yml', network: :devnet)
38
+ Solace::Tokens::USDC.decimals # => 6
39
+ Solace::Tokens.fetch('USDC') # => <Solace::Tokens::Token ...>
40
+ Solace::Tokens.where(decimals: 6)
41
+ ```
42
+ * Dynamically registers constants for each token symbol (`USDC`, `SOL`, etc.).
43
+ * Safety improvements to preserve internal constants (`Token`) during reloads.
44
+
45
+ 2. **`SystemProgramCreateAccountComposer`** — composer for building account creation flows via the Solana System Program.
46
+
47
+ * Wraps `SystemProgram::CreateAccountInstruction`.
48
+ * Handles lamport allocation, rent exemption, and ownership assignment.
49
+ * Simplifies creation of system-owned and program-owned accounts.
50
+
51
+ 3. **`SplTokenProgramInitializeMintComposer`** — composer for initializing new SPL Token mints.
52
+
53
+ * Wraps `SplToken::InitializeMintInstruction`.
54
+ * Supports decimals, mint authority, and optional freeze authority.
55
+ * Designed to pair with `SystemProgramCreateAccountComposer` for one-transaction mint creation.
56
+
57
+ 4. **`SplTokenProgramMintToComposer`** — composer for minting tokens to an ATA.
58
+
59
+ * Wraps `SplToken::MintToInstruction`.
60
+ * Supports minting tokens to a destination ATA.
61
+
62
+ 5. **`SplTokenProgramTransferComposer`** — composer for transferring tokens.
63
+
64
+ * Wraps `SplToken::TransferInstruction`.
65
+ * Supports sending SPL tokens.
66
+
67
+ 6. **`Solace::Connection`** — cached blockhash accessors.
68
+
69
+ * Added `last_fetched_blockhash` and `last_fetched_block_height`.
70
+ * Stores the most recently retrieved blockhash and corresponding `lastValidBlockHeight`.
71
+ * Enables reuse without re-fetching between sequential transactions.
72
+ * `get_latest_blockhash` now sets these values automatically.
73
+
74
+ 7. **`TransactionComposer`** — instruction ordering helpers.
75
+
76
+ * Added `prepend_instruction` and `insert_instruction` for finer control of instruction order.
77
+
78
+ 8. **`Transaction`** — signature helper.
79
+
80
+ * Added `transaction.signature` to get the signature from a signed transaction.
81
+
82
+ 9. **Program method options** — higher-level control.
83
+
84
+ * Added `execute`, `sign`, and a yield block to relevant Program methods for flow control and composer access.
23
85
 
24
86
  ### Changed
25
- 2. Updated `build_instructions` method on `TransactionComposer` to flatten the array, allowing composers to return multiple instructions when relevant (i.e. creating an account and then writing to it).
26
- 3. Changed get_latest_blockhash to use the expected comittment level by the connection or passed options and return array (blockhash and lastValidBlockheight)
27
- 4. Changed default commitment level to `processed` in `Solace::Connection`.
87
+
88
+ 1. `TransactionComposer#build_instructions` now flattens arrays so composers can return multiple instructions (e.g., create an account then initialize it).
89
+
90
+ 2. `Connection#get_latest_blockhash` now uses the connection’s expected commitment (or provided options) and returns `[blockhash, lastValidBlockheight]`.
91
+
92
+ 3. Default commitment level changed to `processed` in `Solace::Connection`.
93
+
94
+ 4. SPL Program: renamed/adjusted kwargs for `compose_create_mint` and moved signing logic to `create_mint`.
95
+
96
+ 5. SPL Program: `compose_mint_to` moved signing logic to `mint_to`.
97
+
98
+ 6. SPL Program: `compose_transfer` moved signing logic to `transfer`.
99
+
100
+ 7. SPL Program: `create_mint`, `compose_create_mint`, and `compose_create_associated_token_account` now accept separate `funder` and `payer` keys. Both may be the same value, but splitting them allows one account to pay transaction fees while another covers rent exemption.
101
+
102
+ 8. All executable Program methods now return the **Solace transaction instance** instead of an encoded signature.
103
+
104
+ 9. Updated `test/bootstrap.rb` to use composers for setting up test fixtures in a single transaction.
28
105
 
29
106
  ### Fixed
30
107
 
108
+ * Improved token loading safety in `Solace::Tokens` to prevent internal constant removal during reloads.
109
+
110
+ ---
111
+
31
112
  ## [0.0.9] - 2025-08-12
32
-
113
+
33
114
  ### Added
34
115
  1. Added `get_program_accounts` to `Solace::Connection`.
35
116
 
36
117
  ### Changed
37
-
118
+
38
119
  ### Fixed
39
120
  1. Removed use of the `try` method for supporting non-rails environments.
40
121
 
41
122
  ## [0.0.8] - 2025-08-11
42
-
123
+
43
124
  ### Added
44
125
  1. Added `load` method to `Solace::Constants` to load constants from a YAML file. This method allows for loading constants from a YAML file (i.e. custom program addresses and mint accounts).
45
126
  2. Added `to_s` and `address` method to `Solace::Keypair` and `Solace::PublicKey` to return the public key as a Base58 string.
@@ -50,22 +131,22 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
50
131
  ### Changed
51
132
  1. All methods that take a `Solace::Keypair` or `Solace::Pubkey` where an address is needed now also accept a plain string address. This prevents the need of creating instances of the classes when all that is needed is the address. This is with the exception of the low-level instruction builders, which only expect the correct data and indicies with no required casting.
52
133
  2. Changed `wait_for_confirmed_signature` method to accept a `timeout`, `interval`, and `commitment` arguments.
53
-
134
+
54
135
  ### Fixed
55
136
  1. Fixed `get_or_create_address` method in `Solace::Programs::AssociatedTokenAccount` to return the address of the associated token account if it already exists by checking if there is any data at the address.
56
137
 
57
138
  ## [0.0.7] - 2025-08-09
58
-
139
+
59
140
  ### Added
60
141
  1. Added `AssociatedTokenAccountProgramCreateAccountComposer` with tests.
61
142
 
62
143
  ### Changed
63
- 1. Updated `AssociatedTokenAccount` to use `AssociatedTokenAccountProgramCreateAccountComposer` and sign the transaction in the `create_associated_token_account` method instead of the `prepare_create_associated_token_account` method.
64
-
144
+ 1. Updated `AssociatedTokenAccount` to use `AssociatedTokenAccountProgramCreateAccountComposer` and sign the transaction in the `create_associated_token_account` method instead of the `compose_create_associated_token_account` method.
145
+
65
146
  ### Fixed
66
147
 
67
148
  ## [0.0.6] - 2025-08-07
68
-
149
+
69
150
  ### Added
70
151
  1. Added `from_address` method to `Solace::PublicKey`.
71
152
  2. Change docs on most methods to include an `@example` section.
@@ -73,13 +154,13 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
73
154
  ### Changed
74
155
  1. Change `private_key` method on Keypair to `pivate_key_bytes`
75
156
  2. Change README to include a practical example of using composers.
76
-
157
+
77
158
  ### Fixed
78
159
  1. Fix `encode_signatures` method in `Solace::Serializers::TransactionSerializer` to correctly count the number of signatures using the `num_required_signatures` field in the message.
79
160
 
80
161
 
81
162
  ## [0.0.3] - 2025-07-30
82
-
163
+
83
164
  ### Added
84
165
  1. Moved `TransferCheckedInstruction` and `TransferInstruction` to `Solace::Instructions::SystemProgram` namespace.
85
166
  2. Added `get_token_account_balance` to `Solace::Connection`.
@@ -94,14 +175,14 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
94
175
 
95
176
  ### Changed
96
177
 
97
- THESE ARE BREAKING CHANGES FROM 0.0.2 TO 0.0.3. Solice is still in alpha and the API is subject to change.
178
+ THESE ARE BREAKING CHANGES FROM 0.0.2 TO 0.0.3. Solice is still in alpha and the API is subject to change.
98
179
 
99
180
  There was a bit of a refactoring of the codebase to make it more maintainable and to make it easier to add new features. Additonally, the SDK now has `Composers` for handling accounts and instructions in a higher level abstraction. These composers are used in the tests and can be used in your own code as well.
100
181
 
101
- Soon, YARD documentation will be added to the SDK and published to https://solace-rb.github.io/solace/.
182
+ Soon, YARD documentation will be added to the SDK and published to https://solace-rb.github.io/solace/.
102
183
 
103
184
  Stay tuned.
104
-
185
+
105
186
  ### Fixed
106
187
 
107
188
  N/A
data/README.md CHANGED
@@ -1,4 +1,5 @@
1
1
  # Solace Ruby SDK Documentation
2
+
2
3
  A Ruby SDK for the Solana blockchain.
3
4
 
4
5
  ## Overview
@@ -10,9 +11,9 @@ Solace is a comprehensive Ruby SDK for interacting with the Solana blockchain. I
10
11
  The Solace SDK is organized into several key layers:
11
12
 
12
13
  ### 1. **Core Classes** (Low-Level)
13
- - **Keypair/PublicKey**: Ed25519 cryptographic operations
14
+ - **Keypair, PublicKey**: Ed25519 cryptographic operations
14
15
  - **Connection**: RPC client for Solana nodes
15
- - **Transaction/Message/Instruction/AddressLookupTable**: Transaction building blocks
16
+ - **Transaction, Message, Instruction, AddressLookupTable**: Transaction building blocks
16
17
  - **Serializers**: Binary serialization/deserialization system
17
18
 
18
19
  ### 2. **Instruction Builders** (Low-Level)
@@ -34,7 +35,8 @@ The Solace SDK is organized into several key layers:
34
35
  - **Codecs**: Base58/Base64 encoding, compact integers, little-endian encoding
35
36
  - **PDA**: Program Derived Address generation
36
37
  - **Curve25519**: Native curve operations via FFI
37
- - **More...**: Checkout `lib/solace/utils`
38
+ - **Token**: Classes for loading and accessing token data
39
+ - **More...**: Checkout `lib/solace/utils`
38
40
 
39
41
  ## Core Components
40
42
 
@@ -199,7 +201,7 @@ For more control, use "prepare" methods that return signed transactions without
199
201
 
200
202
  ```ruby
201
203
  # Prepare transaction without sending
202
- transaction = spl_token.prepare_create_mint(
204
+ transaction = spl_token.compose_create_mint(
203
205
  payer: payer_keypair,
204
206
  decimals: 6,
205
207
  mint_authority: authority_keypair,
@@ -317,10 +319,10 @@ Composers are intended to be extended by developers with custom instruction comp
317
319
  class MyProgramComposer < Solace::Composers::Base
318
320
  # All keyword arguments are passed to the constructor and available
319
321
  # as a `params` hash.
320
- #
322
+ #
321
323
  # The setup_accounts method is called automatically by the transaction composer
322
- # during compilation and should be used to add accounts to the account_context
323
- # with the appropriate access permissions. Conditional logic is fine here given
324
+ # during compilation and should be used to add accounts to the account_context
325
+ # with the appropriate access permissions. Conditional logic is fine here given
324
326
  # and available params to determine the access permissions.
325
327
  def setup_accounts
326
328
  account_context.add_writable_signer(params[:from])
@@ -330,7 +332,7 @@ class MyProgramComposer < Solace::Composers::Base
330
332
 
331
333
  # The build_instruction method is called automatically by the transaction composer
332
334
  # during compilation and should be used to build the instruction using an instruction builder.
333
- #
335
+ #
334
336
  # The passed context to the build_instruction method provides the indices of all accounts
335
337
  # that were added to the account_context in the setup_accounts method. These are accessible
336
338
  # by the index_of method of the context using the account address as a parameter.
@@ -1,6 +1,41 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Solace
4
+ # The Composers module contains classes responsible for building and ordering
5
+ # the accounts and instructions required for common Solana operations.
6
+ #
7
+ # Composers abstract away the complexity of account ordering, permission management,
8
+ # and instruction data construction. They provide a high-level interface for
9
+ # creating instructions that interact with on-chain programs. Each composer
10
+ # corresponds to a specific program instruction (e.g., transferring SOL,
11
+ # minting tokens, creating accounts).
12
+ #
13
+ # Composers handle:
14
+ # - Account resolution and ordering
15
+ # - Permission flags (signer, writable)
16
+ # - Account deduplication
17
+ # - Instruction data formatting
18
+ #
19
+ # @example Using a composer
20
+ # # Initialize a transaction composer
21
+ # composer = TransactionComposer.new(connection: connection)
22
+ #
23
+ # # Create a transfer instruction composer
24
+ # ix = Solace::Composers::SystemProgramTransferComposer.new(
25
+ # from: sender.public_key,
26
+ # to: recipient.public_key,
27
+ # lamports: 1_000_000
28
+ # )
29
+ #
30
+ # # Add the instruction to the transaction composer and compose the transaction
31
+ # tx = composer
32
+ # .add_instruction(ix)
33
+ # .set_fee_payer(sender.public_key)
34
+ # .compose_transaction
35
+ #
36
+ # @see Solace::TransactionComposer
37
+ # @see Solace::Composers::Base
38
+ # @since 0.0.3
4
39
  module Composers
5
40
  # A Base class for all composers
6
41
  #
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solace
4
+ module Composers
5
+ # Composer for initializing a mint via the SPL Token Program.
6
+ #
7
+ # This composer resolves and orders the required accounts for an `InitializeMint` instruction,
8
+ # sets up their access permissions, and delegates construction to the appropriate
9
+ # instruction builder (`Instructions::SplToken::InitializeMintInstruction`).
10
+ #
11
+ # It is used for initializing a new SPL Token mint.
12
+ #
13
+ # Required accounts:
14
+ # - **Mint Account**: the mint account to initialize (writable, non-signer)
15
+ #
16
+ # @example Compose and build an initialize_mint instruction
17
+ # composer = SplTokenProgramInitializeMintComposer.new(
18
+ # decimals: 6,
19
+ # mint_authority: mint_authority_pubkey,
20
+ # freeze_authority: freeze_authority_pubkey,
21
+ # mint_account: mint_address,
22
+ # )
23
+ #
24
+ # @see Instructions::SplToken::InitializeMintInstruction
25
+ # @since 0.1.0
26
+ class SplTokenProgramInitializeMintComposer < Base
27
+ # Extracts the mint account address from the params
28
+ #
29
+ # @return [String] The mint account address
30
+ def mint_account
31
+ params[:mint_account].to_s
32
+ end
33
+
34
+ # Returns the rent sysvar address
35
+ #
36
+ # @return [String] The rent sysvar address
37
+ def rent_sysvar
38
+ Constants::SYSVAR_RENT_PROGRAM_ID.to_s
39
+ end
40
+
41
+ # Returns the spl token program id
42
+ #
43
+ # @return [String] The spl token program id
44
+ def spl_token_program
45
+ Constants::TOKEN_PROGRAM_ID.to_s
46
+ end
47
+
48
+ # Extracts the mint authority address from the params
49
+ #
50
+ # @return [String] The mint authority address
51
+ def mint_authority
52
+ params[:mint_authority].to_s
53
+ end
54
+
55
+ # Extracts the freeze authority address from the params
56
+ #
57
+ # @return [String] The freeze authority address
58
+ def freeze_authority
59
+ params[:freeze_authority]&.to_s
60
+ end
61
+
62
+ # Returns the decimals for the mint
63
+ #
64
+ # @return [Integer] The decimals for the mint
65
+ def decimals
66
+ params[:decimals]
67
+ end
68
+
69
+ # Setup accounts required for transfer instruction
70
+ # Called automatically during initialization
71
+ #
72
+ # @return [void]
73
+ def setup_accounts
74
+ account_context.add_writable_nonsigner(mint_account)
75
+ account_context.add_readonly_nonsigner(rent_sysvar)
76
+ account_context.add_readonly_nonsigner(spl_token_program)
77
+ end
78
+
79
+ # Build instruction with resolved account indices
80
+ #
81
+ # @param account_context [Utils::AccountContext] The account context
82
+ # @return [Solace::Instruction]
83
+ def build_instruction(account_context)
84
+ Instructions::SplToken::InitializeMintInstruction.build(
85
+ mint_account_index: account_context.index_of(mint_account),
86
+ rent_sysvar_index: account_context.index_of(rent_sysvar),
87
+ program_index: account_context.index_of(spl_token_program),
88
+ decimals: decimals,
89
+ mint_authority: mint_authority,
90
+ freeze_authority: freeze_authority
91
+ )
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solace
4
+ module Composers
5
+ # Composer for creating a MintTo instruction for the SPL Token Program.
6
+ #
7
+ # This composer builds a MintTo instruction that can be added to a transaction to mint tokens
8
+ # to a specified token account. It is used to mint new tokens for a given mint and destination account.
9
+ #
10
+ # Required accounts:
11
+ # - **Mint**: The mint account (writable, non-signer)
12
+ # - **Destination**: The token account to mint to (writable, non-signer)
13
+ # - **Mint Authority**: The mint authority account (readonly, signer)
14
+ #
15
+ # @example Build a MintTo instruction
16
+ # composer = Solace::Composers::SplTokenProgramMintToComposer.new(
17
+ # mint: mint,
18
+ # destination: destination,
19
+ # mint_authority: mint_authority,
20
+ # amount: 100
21
+ # )
22
+ #
23
+ # @since 0.1.0
24
+ class SplTokenProgramMintToComposer < Base
25
+ # Extracts the mint address from the params
26
+ #
27
+ # @return [String] The mint address
28
+ def mint
29
+ params[:mint].to_s
30
+ end
31
+
32
+ # Extracts the destination address from the params
33
+ #
34
+ # @return [String] The destination address
35
+ def destination
36
+ params[:destination].to_s
37
+ end
38
+
39
+ # Extracts the mint authority address from the params
40
+ #
41
+ # @return [String] The mint authority address
42
+ def mint_authority
43
+ params[:mint_authority].to_s
44
+ end
45
+
46
+ # Returns the spl token program id
47
+ #
48
+ # @return [String] The spl token program id
49
+ def spl_token_program
50
+ Constants::TOKEN_PROGRAM_ID.to_s
51
+ end
52
+
53
+ # Extracts the amount from the params
54
+ #
55
+ # @return [Integer] The amount
56
+ def amount
57
+ params[:amount].to_i
58
+ end
59
+
60
+ # Setup accounts required for MintTo instruction
61
+ # Called automatically during initialization
62
+ #
63
+ # @return [void]
64
+ def setup_accounts
65
+ account_context.add_writable_nonsigner(mint)
66
+ account_context.add_writable_nonsigner(destination)
67
+ account_context.add_readonly_signer(mint_authority)
68
+ account_context.add_readonly_nonsigner(spl_token_program)
69
+ end
70
+
71
+ # Build instruction with resolved account indices
72
+ #
73
+ # @param account_context [Utils::AccountContext] The account context
74
+ # @return [Solace::Instruction]
75
+ def build_instruction(account_context)
76
+ Instructions::SplToken::MintToInstruction.build(
77
+ amount: amount,
78
+ mint_index: account_context.index_of(mint),
79
+ destination_index: account_context.index_of(destination),
80
+ mint_authority_index: account_context.index_of(mint_authority),
81
+ program_index: account_context.index_of(spl_token_program)
82
+ )
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,90 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solace
4
+ module Composers
5
+ # Composer for creating a SPL Token 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::SplToken::TransferInstruction`).
10
+ #
11
+ # It is used for transferring SPL tokens with decimal precision and validation checks.
12
+ #
13
+ # Required accounts:
14
+ # - **Owner**: token account owner (writable, signer)
15
+ # - **Source**: source token account (writable, non-signer)
16
+ # - **Destination**: destination token account (writable, non-signer)
17
+ #
18
+ # @example Compose and build a transfer instruction
19
+ # composer = SplTokenProgramTransferComposer.new(
20
+ # amount: 1_000_000,
21
+ # owner: owner_address,
22
+ # source: source_address,
23
+ # destination: destination_address,
24
+ # )
25
+ #
26
+ # @see Instructions::SplToken::TransferInstruction
27
+ # @since 0.1.0
28
+ class SplTokenProgramTransferComposer < Base
29
+ # Extracts the owner address from the params
30
+ #
31
+ # @return [String] The owner address
32
+ def owner
33
+ params[:owner].to_s
34
+ end
35
+
36
+ # Extracts the source associated token address from the params
37
+ #
38
+ # @return [String] The source associated token address
39
+ def source
40
+ params[:source].to_s
41
+ end
42
+
43
+ # Extracts the destination associated token address from the params
44
+ #
45
+ # @return [String] The destination associated token address
46
+ def destination
47
+ params[:destination].to_s
48
+ end
49
+
50
+ # Returns the spl token program id
51
+ #
52
+ # @return [String] The spl token program id
53
+ def spl_token_program
54
+ Constants::TOKEN_PROGRAM_ID.to_s
55
+ end
56
+
57
+ # Returns the lamports to transfer
58
+ #
59
+ # @return [Integer] The lamports to transfer
60
+ def amount
61
+ params[:amount]
62
+ end
63
+
64
+ # Setup accounts required for transfer instruction
65
+ # Called automatically during initialization
66
+ #
67
+ # @return [void]
68
+ def setup_accounts
69
+ account_context.add_writable_signer(owner)
70
+ account_context.add_writable_nonsigner(source)
71
+ account_context.add_writable_nonsigner(destination)
72
+ account_context.add_readonly_nonsigner(spl_token_program)
73
+ end
74
+
75
+ # Build instruction with resolved account indices
76
+ #
77
+ # @param account_context [Utils::AccountContext] The account context
78
+ # @return [Solace::Instruction]
79
+ def build_instruction(account_context)
80
+ Instructions::SplToken::TransferInstruction.build(
81
+ amount: amount,
82
+ owner_index: account_context.index_of(owner),
83
+ source_index: account_context.index_of(source),
84
+ destination_index: account_context.index_of(destination),
85
+ program_index: account_context.index_of(spl_token_program)
86
+ )
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,98 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solace
4
+ module Composers
5
+ # Composer for creating an account using the system program.
6
+ #
7
+ # This composer resolves and orders the required accounts for a `CreateAccount` instruction,
8
+ # sets up their access permissions, and delegates construction to the appropriate
9
+ # instruction builder (`Instructions::SystemProgram::CreateAccountInstruction`).
10
+ #
11
+ # It is used for creating new accounts on the Solana blockchain.
12
+ #
13
+ # Required accounts:
14
+ # - **From**: funding account (writable, signer)
15
+ # - **Owner**: owner program id (readonly, non-signer)
16
+ # - **New Account**: new account to create (writable, signer)
17
+ #
18
+ # @example Compose and build a create account instruction
19
+ # composer = SystemProgramCreateAccountComposer.new(
20
+ # from: payer_address,
21
+ # new_account: new_account_address,
22
+ # owner: owner_address,
23
+ # lamports: 1000,
24
+ # space: 1024
25
+ # )
26
+ #
27
+ # @see Instructions::SystemProgram::CreateAccountInstruction
28
+ # @since 0.1.0
29
+ class SystemProgramCreateAccountComposer < Base
30
+ # Extracts the to address from the params
31
+ #
32
+ # @return [String] The from address
33
+ def from
34
+ params[:from].to_s
35
+ end
36
+
37
+ # Extracts the new account address from the params
38
+ #
39
+ # @return [String] The new account address
40
+ def new_account
41
+ params[:new_account].to_s
42
+ end
43
+
44
+ # Returns the system program id
45
+ #
46
+ # @return [String] The system program id
47
+ def system_program
48
+ Solace::Constants::SYSTEM_PROGRAM_ID.to_s
49
+ end
50
+
51
+ # Extracts the owner address from the params
52
+ #
53
+ # @return [String] The owner address
54
+ def owner
55
+ params[:owner].to_s
56
+ end
57
+
58
+ # Returns the lamports to transfer
59
+ #
60
+ # @return [Integer] The lamports to transfer
61
+ def lamports
62
+ params[:lamports]
63
+ end
64
+
65
+ # Returns the space to allocate
66
+ #
67
+ # @return [Integer] The space to allocate
68
+ def space
69
+ params[:space]
70
+ end
71
+
72
+ # Setup accounts required for create account instruction
73
+ # Called automatically during initialization
74
+ #
75
+ # @return [void]
76
+ def setup_accounts
77
+ account_context.add_writable_signer(from)
78
+ account_context.add_writable_signer(new_account)
79
+ account_context.add_readonly_nonsigner(system_program)
80
+ end
81
+
82
+ # Build instruction with resolved account indices
83
+ #
84
+ # @param account_context [Utils::AccountContext] The account context
85
+ # @return [Solace::Instruction]
86
+ def build_instruction(account_context)
87
+ Solace::Instructions::SystemProgram::CreateAccountInstruction.build(
88
+ space: space,
89
+ lamports: lamports,
90
+ owner: owner,
91
+ from_index: account_context.index_of(from),
92
+ new_account_index: account_context.index_of(new_account),
93
+ system_program_index: account_context.index_of(system_program)
94
+ )
95
+ end
96
+ end
97
+ end
98
+ end