solace 0.1.4 → 0.1.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.
@@ -2,11 +2,13 @@
2
2
 
3
3
  module Solace
4
4
  module Programs
5
- # Client for interacting with the SPL Token Program.
5
+ # Client for interacting with the legacy SPL Token Program.
6
6
  #
7
- # This client provides methods for interacting with the SPL Token Program. It is a wrapper around
8
- # the SPL Token Program and provides a more convenient interface for creating and managing SPL
9
- # Token mints and accounts.
7
+ # This client provides methods for creating mints, minting tokens, and
8
+ # transferring tokens via the legacy SPL Token program
9
+ # (+TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA+). The shared method shape
10
+ # comes from {TokenProgramInterface}; this class supplies the SPL-bound
11
+ # composer classes.
10
12
  #
11
13
  # @example Create an SPL Token mint
12
14
  # # Initialize the program with a connection
@@ -25,8 +27,11 @@ module Solace
25
27
  # # Wait for the transaction to be finalized
26
28
  # connection.wait_for_confirmed_signature('finalized') { result['result'] }
27
29
  #
30
+ # @see Solace::Programs::Token2022 for the Token-2022 successor program.
28
31
  # @since 0.0.2
29
32
  class SplToken < Base
33
+ include TokenProgramInterface
34
+
30
35
  # Initializes a new SPL Token client.
31
36
  #
32
37
  # @param connection [Solace::Connection] The connection to the Solana cluster.
@@ -34,263 +39,22 @@ module Solace
34
39
  super(connection: connection, program_id: Solace::Constants::TOKEN_PROGRAM_ID)
35
40
  end
36
41
 
37
- # Creates a new SPL Token mint.
38
- #
39
- # @param payer [#to_s, PublicKey] The keypair that will pay for fees and rent.
40
- # @param sign [Boolean] Whether to sign the transaction.
41
- # @param execute [Boolean] Whether to execute the transaction.
42
- # @param composer_opts [Hash] Options for calling the compose_create_mint method.
43
- # @return [String] The signature of the transaction.
44
- def create_mint(
45
- payer:,
46
- sign: true,
47
- execute: true,
48
- **composer_opts
49
- )
50
- composer = compose_create_mint(**composer_opts)
51
-
52
- yield composer if block_given?
53
-
54
- tx = composer
55
- .set_fee_payer(payer)
56
- .compose_transaction
57
-
58
- if sign
59
- tx.sign(
60
- payer,
61
- composer_opts[:funder],
62
- composer_opts[:mint_account]
63
- )
64
-
65
- connection.send_transaction(tx.serialize) if execute
66
- end
67
-
68
- tx
69
- end
70
-
71
- # Prepares a new SPL Token mint transaction.
72
- #
73
- # @param funder [#to_s, PublicKey] The keypair that will pay for rent of the new mint account.
74
- # @param decimals [Integer] The number of decimal places for the token.
75
- # @param mint_authority [#to_s, PublicKey] The base58 public key for the mint authority.
76
- # @param freeze_authority [#to_s, PublicKey] (Optional) The base58 public key for the freeze authority.
77
- # @param mint_account [#to_s, PublicKey] (Optional) The keypair for the new mint.
78
- # @return [TransactionComposer] A composer with required instructions.
79
- # rubocop:disable Metrics/MethodLength
80
- def compose_create_mint(
81
- funder:,
82
- decimals:,
83
- mint_authority:,
84
- freeze_authority: nil,
85
- mint_account: Solace::Keypair.generate
86
- )
87
- # Mint accounts need 82 bytes of space, and we need to fund it with enough lamports to be rent-exempt
88
- rent_lamports = connection.get_minimum_lamports_for_rent_exemption(82)
89
-
90
- # Build the account for the mint
91
- create_account_ix = Composers::SystemProgramCreateAccountComposer.new(
92
- from: funder,
93
- new_account: mint_account,
94
- owner: program_id,
95
- lamports: rent_lamports,
96
- space: 82
97
- )
42
+ private
98
43
 
99
- # Build the initialize mint composer
100
- initialize_mint_ix = Composers::SplTokenProgramInitializeMintComposer.new(
101
- decimals: decimals,
102
- mint_account: mint_account,
103
- mint_authority: mint_authority,
104
- freeze_authority: freeze_authority
105
- )
106
-
107
- TransactionComposer
108
- .new(connection: @connection)
109
- .add_instruction(create_account_ix)
110
- .add_instruction(initialize_mint_ix)
44
+ def initialize_mint_composer_class
45
+ Composers::SplTokenProgramInitializeMintComposer
111
46
  end
112
- # rubocop:enable Metrics/MethodLength
113
-
114
- # Mint tokens to a token account
115
- #
116
- # @param payer [#to_s, PublicKey] The keypair that will pay for fees and rent.
117
- # @param sign [Boolean] Whether to sign the transaction.
118
- # @param execute [Boolean] Whether to execute the transaction.
119
- # @param composer_opts [Hash] Options for calling the compose_mint_to method.
120
- # @return [String] The signature of the transaction.
121
- def mint_to(
122
- payer:,
123
- sign: true,
124
- execute: true,
125
- **composer_opts
126
- )
127
- composer = compose_mint_to(**composer_opts)
128
-
129
- yield composer if block_given?
130
-
131
- tx = composer
132
- .set_fee_payer(payer)
133
- .compose_transaction
134
-
135
- if sign
136
- tx.sign(
137
- payer,
138
- composer_opts[:mint_authority]
139
- )
140
47
 
141
- connection.send_transaction(tx.serialize) if execute
142
- end
143
-
144
- tx
48
+ def mint_to_composer_class
49
+ Composers::SplTokenProgramMintToComposer
145
50
  end
146
51
 
147
- # Prepares a mint to instruction and returns the signed transaction.
148
- #
149
- # @param [Integer] amount The amount of tokens to mint.
150
- # @param [#to_s, PublicKey] mint The mint of the token.
151
- # @param [#to_s, PublicKey] destination The destination of the token.
152
- # @param [#to_s, PublicKey] mint_authority The mint authority of the token.
153
- # @return [TransactionComposer] A composer with required instructions.
154
- #
155
- # @param [Boolean] ensure_account
156
- def compose_mint_to(
157
- mint:,
158
- amount:,
159
- destination:,
160
- mint_authority:
161
- )
162
- ix = Composers::SplTokenProgramMintToComposer.new(
163
- amount: amount,
164
- mint: mint,
165
- destination: destination,
166
- mint_authority: mint_authority
167
- )
168
-
169
- TransactionComposer
170
- .new(connection: connection)
171
- .add_instruction(ix)
52
+ def transfer_composer_class
53
+ Composers::SplTokenProgramTransferComposer
172
54
  end
173
55
 
174
- # Transfers tokens from one account to another
175
- #
176
- # @param payer [#to_s, PublicKey] The keypair that will pay for fees and rent.
177
- # @param sign [Boolean] Whether to sign the transaction.
178
- # @param execute [Boolean] Whether to execute the transaction.
179
- # @param composer_opts [Hash] Options for calling the compose_transfer method.
180
- # @return [String] The signature of the transaction.
181
- def transfer(
182
- payer:,
183
- sign: true,
184
- execute: true,
185
- **composer_opts
186
- )
187
- composer = compose_transfer(**composer_opts)
188
-
189
- yield composer if block_given?
190
-
191
- tx = composer
192
- .set_fee_payer(payer)
193
- .compose_transaction
194
-
195
- if sign
196
- tx.sign(
197
- payer,
198
- composer_opts[:owner]
199
- )
200
-
201
- connection.send_transaction(tx.serialize) if execute
202
- end
203
- tx
204
- end
205
-
206
- # Prepares a transfer instruction and returns the signed transaction.
207
- #
208
- # @param source [#to_s, PublicKey] The source token account address.
209
- # @param destination [#to_s, PublicKey] The destination token account address.
210
- # @param amount [Integer] The number of tokens to transfer.
211
- # @param owner [#to_s, PublicKey] The keypair of the owner of the source account.
212
- # @return [TransactionComposer] A composer with required instructions.
213
- #
214
- def compose_transfer(
215
- amount:,
216
- source:,
217
- destination:,
218
- owner:
219
- )
220
- ix = Composers::SplTokenProgramTransferComposer.new(
221
- amount: amount,
222
- owner: owner,
223
- source: source,
224
- destination: destination
225
- )
226
-
227
- TransactionComposer
228
- .new(connection: connection)
229
- .add_instruction(ix)
230
- end
231
-
232
- # Transfers tokens with decimal precision and validation checks
233
- #
234
- # @param payer [#to_s, PublicKey] The keypair that will pay for fees and rent.
235
- # @param sign [Boolean] Whether to sign the transaction.
236
- # @param execute [Boolean] Whether to execute the transaction.
237
- # @param composer_opts [Hash] Options for calling the compose_transfer_checked method.
238
- # @return [String] The signature of the transaction.
239
- def transfer_checked(
240
- payer:,
241
- sign: true,
242
- execute: true,
243
- **composer_opts
244
- )
245
- composer = compose_transfer_checked(**composer_opts)
246
-
247
- yield composer if block_given?
248
-
249
- tx = composer
250
- .set_fee_payer(payer)
251
- .compose_transaction
252
-
253
- if sign
254
- tx.sign(
255
- payer,
256
- composer_opts[:authority]
257
- )
258
-
259
- connection.send_transaction(tx.serialize) if execute
260
- end
261
-
262
- tx
263
- end
264
-
265
- # Prepares a transfer checked instruction and returns the signed transaction.
266
- #
267
- # @param amount [Integer] The number of tokens to transfer.
268
- # @param decimals [Integer] The number of decimals for the token.
269
- # @param from [#to_s, PublicKey] The source token account address.
270
- # @param to [#to_s, PublicKey] The destination token account address.
271
- # @param mint [#to_s, PublicKey] The mint address
272
- # @param authority [#to_s, PublicKey] The keypair of the owner of the source account.
273
- # @return [TransactionComposer] A composer with required instructions.
274
- def compose_transfer_checked(
275
- to:,
276
- from:,
277
- mint:,
278
- authority:,
279
- amount:,
280
- decimals:
281
- )
282
- ix = Composers::SplTokenProgramTransferCheckedComposer.new(
283
- to: to,
284
- from: from,
285
- mint: mint,
286
- authority: authority,
287
- amount: amount,
288
- decimals: decimals
289
- )
290
-
291
- TransactionComposer
292
- .new(connection: connection)
293
- .add_instruction(ix)
56
+ def transfer_checked_composer_class
57
+ Composers::SplTokenProgramTransferCheckedComposer
294
58
  end
295
59
  end
296
60
  end
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solace
4
+ module Programs
5
+ # Client for interacting with the Token-2022 Program (formerly Token Extensions).
6
+ #
7
+ # Token-2022 is the successor to the legacy SPL Token program
8
+ # (+TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb+). Its base instructions —
9
+ # Transfer, TransferChecked, CloseAccount, MintTo, InitializeMint — are
10
+ # wire-compatible with the legacy program; only the program account they
11
+ # target is different. The shared method shape comes from
12
+ # {TokenProgramInterface}; this class supplies the Token-2022-bound
13
+ # composer classes. Branching between SPL Token and Token-2022 belongs at
14
+ # the call site, where the developer already knows which mint they hold.
15
+ #
16
+ # Important: mints owned by Token-2022 (e.g. PYUSD on Solana) derive
17
+ # their Associated Token Accounts with this program ID in the seed.
18
+ # When working with such a mint, pass
19
+ # +token_program_id: Solace::Constants::TOKEN_2022_PROGRAM_ID+ to
20
+ # {Programs::AssociatedTokenAccount.get_address}. Use
21
+ # {Connection#get_mint_program_id} to discover which token program owns
22
+ # a given mint at runtime.
23
+ #
24
+ # This class does not yet expose the Token-2022 extension instructions
25
+ # (transfer hooks, transfer fees, confidential transfer, etc.); those
26
+ # are out of scope for the base instruction surface.
27
+ #
28
+ # @example Create a Token-2022 mint
29
+ # program = Solace::Programs::Token2022.new(connection: connection)
30
+ #
31
+ # tx = program.create_mint(
32
+ # payer: payer,
33
+ # funder: funder,
34
+ # decimals: 6,
35
+ # mint_account: mint_account,
36
+ # mint_authority: mint_authority
37
+ # )
38
+ #
39
+ # @see Solace::Programs::SplToken
40
+ # @since 0.1.5
41
+ class Token2022 < Base
42
+ include TokenProgramInterface
43
+
44
+ # Initializes a new Token-2022 client.
45
+ #
46
+ # @param connection [Solace::Connection] The connection to the Solana cluster.
47
+ def initialize(connection:)
48
+ super(connection: connection, program_id: Solace::Constants::TOKEN_2022_PROGRAM_ID)
49
+ end
50
+
51
+ private
52
+
53
+ def initialize_mint_composer_class
54
+ Composers::Token2022ProgramInitializeMintComposer
55
+ end
56
+
57
+ def mint_to_composer_class
58
+ Composers::Token2022ProgramMintToComposer
59
+ end
60
+
61
+ def transfer_composer_class
62
+ Composers::Token2022ProgramTransferComposer
63
+ end
64
+
65
+ def transfer_checked_composer_class
66
+ Composers::Token2022ProgramTransferCheckedComposer
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,312 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solace
4
+ module Programs
5
+ # Mixin describing the common surface of a token-program client.
6
+ #
7
+ # The legacy SPL Token program and Token-2022 expose a wire-compatible
8
+ # base instruction set (Transfer, TransferChecked, CloseAccount, MintTo,
9
+ # InitializeMint). This module captures the *shape* of a client that
10
+ # speaks that surface — the public methods +create_mint+, +mint_to+,
11
+ # +transfer+, +transfer_checked+ and their +compose_*+ pairs — without
12
+ # binding to either program.
13
+ #
14
+ # State (connection, program_id) lives on {Programs::Base}; this module
15
+ # is purely behavior. Including classes must implement four private
16
+ # readers that name the composer class for each operation:
17
+ #
18
+ # - {#initialize_mint_composer_class}
19
+ # - {#mint_to_composer_class}
20
+ # - {#transfer_composer_class}
21
+ # - {#transfer_checked_composer_class}
22
+ #
23
+ # Each composer returned by those readers is itself bound to a single
24
+ # on-chain program, which is how this mixin keeps the boundary clean:
25
+ # +SplToken+ and +Token2022+ share *methods* but never share a composer.
26
+ #
27
+ # @see Solace::Programs::SplToken
28
+ # @see Solace::Programs::Token2022
29
+ # @since 0.1.5
30
+ # rubocop:disable Metrics/ModuleLength
31
+ module TokenProgramInterface
32
+ # Creates a new mint, signs it, and (optionally) sends it.
33
+ #
34
+ # @param payer [#to_s, PublicKey] The keypair that will pay for fees and rent.
35
+ # @param sign [Boolean] Whether to sign the transaction.
36
+ # @param execute [Boolean] Whether to execute the transaction.
37
+ # @param composer_opts [Hash] Options for {#compose_create_mint}.
38
+ # @return [Transaction] The created or sent transaction.
39
+ def create_mint(
40
+ payer:,
41
+ sign: true,
42
+ execute: true,
43
+ **composer_opts
44
+ )
45
+ composer = compose_create_mint(**composer_opts)
46
+
47
+ yield composer if block_given?
48
+
49
+ tx = composer
50
+ .set_fee_payer(payer)
51
+ .compose_transaction
52
+
53
+ if sign
54
+ tx.sign(
55
+ payer,
56
+ composer_opts[:funder],
57
+ composer_opts[:mint_account]
58
+ )
59
+
60
+ connection.send_transaction(tx.serialize) if execute
61
+ end
62
+
63
+ tx
64
+ end
65
+
66
+ # Prepares a new mint transaction.
67
+ #
68
+ # @param funder [#to_s, PublicKey] The keypair that will pay for rent of the new mint account.
69
+ # @param decimals [Integer] The number of decimal places for the token.
70
+ # @param mint_authority [#to_s, PublicKey] The base58 public key for the mint authority.
71
+ # @param freeze_authority [#to_s, PublicKey] (Optional) The base58 public key for the freeze authority.
72
+ # @param mint_account [#to_s, PublicKey] (Optional) The keypair for the new mint.
73
+ # @return [TransactionComposer] A composer with required instructions.
74
+ # rubocop:disable Metrics/MethodLength
75
+ def compose_create_mint(
76
+ funder:,
77
+ decimals:,
78
+ mint_authority:,
79
+ freeze_authority: nil,
80
+ mint_account: Solace::Keypair.generate
81
+ )
82
+ # Mint accounts need 82 bytes of space, and we need to fund it with enough lamports to be rent-exempt
83
+ rent_lamports = connection.get_minimum_lamports_for_rent_exemption(82)
84
+
85
+ # Build the account for the mint
86
+ create_account_ix = Composers::SystemProgramCreateAccountComposer.new(
87
+ from: funder,
88
+ new_account: mint_account,
89
+ owner: program_id,
90
+ lamports: rent_lamports,
91
+ space: 82
92
+ )
93
+
94
+ # Build the initialize mint composer (per-program class supplied by includer)
95
+ initialize_mint_ix = initialize_mint_composer_class.new(
96
+ decimals: decimals,
97
+ mint_account: mint_account,
98
+ mint_authority: mint_authority,
99
+ freeze_authority: freeze_authority
100
+ )
101
+
102
+ TransactionComposer
103
+ .new(connection: connection)
104
+ .add_instruction(create_account_ix)
105
+ .add_instruction(initialize_mint_ix)
106
+ end
107
+ # rubocop:enable Metrics/MethodLength
108
+
109
+ # Mints tokens to a token account.
110
+ #
111
+ # @param payer [#to_s, PublicKey] The keypair that will pay for fees and rent.
112
+ # @param sign [Boolean] Whether to sign the transaction.
113
+ # @param execute [Boolean] Whether to execute the transaction.
114
+ # @param composer_opts [Hash] Options for {#compose_mint_to}.
115
+ # @return [Transaction] The created or sent transaction.
116
+ def mint_to(
117
+ payer:,
118
+ sign: true,
119
+ execute: true,
120
+ **composer_opts
121
+ )
122
+ composer = compose_mint_to(**composer_opts)
123
+
124
+ yield composer if block_given?
125
+
126
+ tx = composer
127
+ .set_fee_payer(payer)
128
+ .compose_transaction
129
+
130
+ if sign
131
+ tx.sign(
132
+ payer,
133
+ composer_opts[:mint_authority]
134
+ )
135
+
136
+ connection.send_transaction(tx.serialize) if execute
137
+ end
138
+
139
+ tx
140
+ end
141
+
142
+ # Prepares a mint_to instruction.
143
+ #
144
+ # @param amount [Integer] The amount of tokens to mint.
145
+ # @param mint [#to_s, PublicKey] The mint of the token.
146
+ # @param destination [#to_s, PublicKey] The destination token account.
147
+ # @param mint_authority [#to_s, PublicKey] The mint authority.
148
+ # @return [TransactionComposer] A composer with the mint_to instruction.
149
+ def compose_mint_to(
150
+ mint:,
151
+ amount:,
152
+ destination:,
153
+ mint_authority:
154
+ )
155
+ ix = mint_to_composer_class.new(
156
+ amount: amount,
157
+ mint: mint,
158
+ destination: destination,
159
+ mint_authority: mint_authority
160
+ )
161
+
162
+ TransactionComposer
163
+ .new(connection: connection)
164
+ .add_instruction(ix)
165
+ end
166
+
167
+ # Transfers tokens from one account to another.
168
+ #
169
+ # @param payer [#to_s, PublicKey] The keypair that will pay for fees and rent.
170
+ # @param sign [Boolean] Whether to sign the transaction.
171
+ # @param execute [Boolean] Whether to execute the transaction.
172
+ # @param composer_opts [Hash] Options for {#compose_transfer}.
173
+ # @return [Transaction] The created or sent transaction.
174
+ def transfer(
175
+ payer:,
176
+ sign: true,
177
+ execute: true,
178
+ **composer_opts
179
+ )
180
+ composer = compose_transfer(**composer_opts)
181
+
182
+ yield composer if block_given?
183
+
184
+ tx = composer
185
+ .set_fee_payer(payer)
186
+ .compose_transaction
187
+
188
+ if sign
189
+ tx.sign(
190
+ payer,
191
+ composer_opts[:owner]
192
+ )
193
+
194
+ connection.send_transaction(tx.serialize) if execute
195
+ end
196
+ tx
197
+ end
198
+
199
+ # Prepares a transfer instruction.
200
+ #
201
+ # @param source [#to_s, PublicKey] The source token account address.
202
+ # @param destination [#to_s, PublicKey] The destination token account address.
203
+ # @param amount [Integer] The number of tokens to transfer.
204
+ # @param owner [#to_s, PublicKey] The owner of the source account.
205
+ # @return [TransactionComposer] A composer with the transfer instruction.
206
+ def compose_transfer(
207
+ amount:,
208
+ source:,
209
+ destination:,
210
+ owner:
211
+ )
212
+ ix = transfer_composer_class.new(
213
+ amount: amount,
214
+ owner: owner,
215
+ source: source,
216
+ destination: destination
217
+ )
218
+
219
+ TransactionComposer
220
+ .new(connection: connection)
221
+ .add_instruction(ix)
222
+ end
223
+
224
+ # Transfers tokens with decimal precision and validation checks.
225
+ #
226
+ # @param payer [#to_s, PublicKey] The keypair that will pay for fees and rent.
227
+ # @param sign [Boolean] Whether to sign the transaction.
228
+ # @param execute [Boolean] Whether to execute the transaction.
229
+ # @param composer_opts [Hash] Options for {#compose_transfer_checked}.
230
+ # @return [Transaction] The created or sent transaction.
231
+ def transfer_checked(
232
+ payer:,
233
+ sign: true,
234
+ execute: true,
235
+ **composer_opts
236
+ )
237
+ composer = compose_transfer_checked(**composer_opts)
238
+
239
+ yield composer if block_given?
240
+
241
+ tx = composer
242
+ .set_fee_payer(payer)
243
+ .compose_transaction
244
+
245
+ if sign
246
+ tx.sign(
247
+ payer,
248
+ composer_opts[:authority]
249
+ )
250
+
251
+ connection.send_transaction(tx.serialize) if execute
252
+ end
253
+
254
+ tx
255
+ end
256
+
257
+ # Prepares a transfer_checked instruction.
258
+ #
259
+ # @param amount [Integer] The number of tokens to transfer.
260
+ # @param decimals [Integer] The number of decimals for the token.
261
+ # @param from [#to_s, PublicKey] The source token account address.
262
+ # @param to [#to_s, PublicKey] The destination token account address.
263
+ # @param mint [#to_s, PublicKey] The mint address.
264
+ # @param authority [#to_s, PublicKey] The owner of the source account.
265
+ # @return [TransactionComposer] A composer with the transfer_checked instruction.
266
+ def compose_transfer_checked(
267
+ to:,
268
+ from:,
269
+ mint:,
270
+ authority:,
271
+ amount:,
272
+ decimals:
273
+ )
274
+ ix = transfer_checked_composer_class.new(
275
+ to: to,
276
+ from: from,
277
+ mint: mint,
278
+ authority: authority,
279
+ amount: amount,
280
+ decimals: decimals
281
+ )
282
+
283
+ TransactionComposer
284
+ .new(connection: connection)
285
+ .add_instruction(ix)
286
+ end
287
+
288
+ private
289
+
290
+ # @return [Class] Composer class used by {#compose_create_mint}.
291
+ def initialize_mint_composer_class
292
+ raise NotImplementedError, "#{self.class} must implement #initialize_mint_composer_class"
293
+ end
294
+
295
+ # @return [Class] Composer class used by {#compose_mint_to}.
296
+ def mint_to_composer_class
297
+ raise NotImplementedError, "#{self.class} must implement #mint_to_composer_class"
298
+ end
299
+
300
+ # @return [Class] Composer class used by {#compose_transfer}.
301
+ def transfer_composer_class
302
+ raise NotImplementedError, "#{self.class} must implement #transfer_composer_class"
303
+ end
304
+
305
+ # @return [Class] Composer class used by {#compose_transfer_checked}.
306
+ def transfer_checked_composer_class
307
+ raise NotImplementedError, "#{self.class} must implement #transfer_checked_composer_class"
308
+ end
309
+ end
310
+ # rubocop:enable Metrics/ModuleLength
311
+ end
312
+ end
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Solace
4
4
  # Latest version of the Solace gem.
5
- VERSION = '0.1.4'
5
+ VERSION = '0.1.5'
6
6
  end
data/lib/solace.rb CHANGED
@@ -68,5 +68,7 @@ Dir[File.join(__dir__, 'solace/composers', '**', '*.rb')].each { |file| require
68
68
  Dir[File.join(__dir__, 'solace/instructions', '**', '*.rb')].each { |file| require file }
69
69
 
70
70
  # Programs
71
+ require_relative 'solace/programs/token_program_interface'
71
72
  require_relative 'solace/programs/spl_token'
73
+ require_relative 'solace/programs/token_2022'
72
74
  require_relative 'solace/programs/associated_token_account'