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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 18aca49d63b09deffe93ba871b65d6b816a7c81863b0b0e2b2c2bd29ce709ce6
4
- data.tar.gz: 810a45b1324aa282684e4a5d62ea48738ac2b33a6eb87538e2e0458ca2f54593
3
+ metadata.gz: b2d850b2d501a6bf777043a53e320a2bef57fee4ea47e9a2a08e3331e4695c8f
4
+ data.tar.gz: 80139c66611fb213d966db7f6ea7468a46fec9b8b6418917995c424627f2998b
5
5
  SHA512:
6
- metadata.gz: 50eeac609077e873b361fdb8ed34459ccbed1b4e44d52ad911803350ea0d2f0e669fcfcb30bcddd6d20e9f54dade972a50907532a108dae7142ecca8475f42fb
7
- data.tar.gz: 5fba491757746aa8fad865bae93941f3469148c6a5fc8cb5c984ebccb79934f1b1c3425184ab37ff2342f6215a1d5b1147a9d04f6d9225a96e7c6b34c38d8b0d
6
+ metadata.gz: 659cfcfef1750281cb209a0ef13398af0c56c77f0ebe2479380c09d1764cf83eb39c74a08a3fa6234ceb7e9fbd1e97b5abbdd281bee653c39e00c177fea4aa27
7
+ data.tar.gz: 9d79ebd0a3c418fca8933b533bd5588605a01338327aeb6b8ed5db831497ea5acd5597d5f82a63ed563ae2e857d84a78745a39c2e1b2750b9b5eb0d5d2e2da09
data/CHANGELOG CHANGED
@@ -20,6 +20,23 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
20
20
 
21
21
  ---
22
22
 
23
+ ## 0.1.5 - 2026-06-13
24
+
25
+ ### Added
26
+
27
+ 1. Added Token-2022 program support
28
+ 2. Added integration tests for the Token-2022 composers
29
+
30
+ ### Changed
31
+
32
+ 1. Decoupled Token-2022 from the SPL composers via a shared mixin
33
+
34
+ ### Fixed
35
+
36
+ 1. Fixed `TransferChecked` instruction layout documentation
37
+
38
+ ---
39
+
23
40
  ## 0.1.3 - 2025-06-11
24
41
 
25
42
  ### Added
data/README.md CHANGED
@@ -450,6 +450,66 @@ response = connection.send_transaction(transaction.serialize)
450
450
  connection.wait_for_confirmed_signature { response['result'] }
451
451
  ```
452
452
 
453
+ ## Development
454
+
455
+ ### Prerequisites
456
+
457
+ - **Ruby** (matching `.ruby-version` / `Gemfile.lock`) and **Bundler**
458
+ - **Solana CLI**, which provides `solana-test-validator` and `solana-keygen`. Install with:
459
+ ```bash
460
+ sh -c "$(curl -sSfL https://release.anza.xyz/stable/install)"
461
+ ```
462
+ Then add the installer's PATH line to your shell profile (the installer prints the exact `export PATH=...` to use).
463
+
464
+ ### One-time setup
465
+
466
+ ```bash
467
+ # Install Ruby dependencies
468
+ bundle install
469
+
470
+ # Generate the seven keypair fixtures the test suite expects.
471
+ # test/fixtures/ is gitignored — each developer generates their own.
472
+ mkdir -p test/fixtures
473
+ for name in bob anna payer mint mint-2022 mint-authority fee-collector; do
474
+ solana-keygen new --no-bip39-passphrase --silent --force -o "test/fixtures/${name}.json"
475
+ done
476
+
477
+ # Bootstrap the local validator: airdrops SOL to the fixture accounts,
478
+ # creates their ATAs, and creates the test mint. Spins up a
479
+ # solana-test-validator on the side; ledger state persists in ./test-ledger.
480
+ bundle exec rake bootstrap
481
+ ```
482
+
483
+ If you ever need a clean slate, delete `test-ledger/` and re-run `rake bootstrap`.
484
+
485
+ ### Running the tests
486
+
487
+ ```bash
488
+ bundle exec rake test
489
+ ```
490
+
491
+ `rake test` spawns `solana-test-validator` automatically (re-using `./test-ledger`) and tears it down on exit. You can also run a single file:
492
+
493
+ ```bash
494
+ bundle exec rake test test/solace/programs/spl_token_test.rb
495
+ ```
496
+
497
+ To exercise the longer end-to-end flows in `test/usecases/`:
498
+
499
+ ```bash
500
+ bundle exec rake usecases # all usecases
501
+ bundle exec rake usecases token_mint # a specific one
502
+ ```
503
+
504
+ ### Building & installing the gem locally
505
+
506
+ ```bash
507
+ bundle exec rake build # produces builds/solace-<version>.gem
508
+ bundle exec rake install # builds and `gem install`s it locally
509
+ ```
510
+
511
+ The native curve25519 library is shipped pre-compiled in `lib/solace/utils/`. You only need `rake compile` (which invokes `cargo`) if you're modifying `ext/curve25519_dalek` — that target cross-builds for every supported platform and requires the corresponding Rust toolchains.
512
+
453
513
  ## Dependencies
454
514
 
455
515
  - **base58**: Base58 encoding/decoding
@@ -63,11 +63,12 @@ module Solace
63
63
  Constants::SYSTEM_PROGRAM_ID.to_s
64
64
  end
65
65
 
66
- # Extracts the token program id from the constants
67
- #
68
- # @return [String] The token program id
66
+ # @return [String] The token program id baked into the ATA's create-account
67
+ # instruction (defaults to legacy SPL Token; pass +params[:token_program_id]+
68
+ # to create a Token-2022 ATA note the derived ATA address differs too,
69
+ # see {Programs::AssociatedTokenAccount.get_address}).
69
70
  def token_program_id
70
- Constants::TOKEN_PROGRAM_ID.to_s
71
+ (params[:token_program_id] || Constants::TOKEN_PROGRAM_ID).to_s
71
72
  end
72
73
 
73
74
  # Extracts the associated token account program id from the constants
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solace
4
+ module Composers
5
+ # Composer for creating a Token-2022 Program CloseAccount instruction.
6
+ #
7
+ # The CloseAccount instruction closes a token account and transfers remaining
8
+ # lamports to a destination account. The account must have a balance of zero tokens.
9
+ #
10
+ # Required accounts:
11
+ # - **Account**: token account to close (writable, non-signer)
12
+ # - **Destination**: account to receive lamports (writable, non-signer)
13
+ # - **Authority**: account authority (non-writable, signer)
14
+ #
15
+ # @example Compose and build a close account instruction
16
+ # composer = Token2022ProgramCloseAccountComposer.new(
17
+ # account: token_account_address,
18
+ # destination: destination_address,
19
+ # authority: authority_address
20
+ # )
21
+ #
22
+ # @since 0.1.5
23
+ class Token2022ProgramCloseAccountComposer < Base
24
+ # Extracts the token account address from the params
25
+ #
26
+ # @return [String] The token account address
27
+ def account
28
+ params[:account].to_s
29
+ end
30
+
31
+ # Extracts the destination address from the params
32
+ #
33
+ # @return [String] The destination address
34
+ def destination
35
+ params[:destination].to_s
36
+ end
37
+
38
+ # Extracts the authority address from the params
39
+ #
40
+ # @return [String] The authority address
41
+ def authority
42
+ params[:authority].to_s
43
+ end
44
+
45
+ # @return [String] The Token-2022 program id.
46
+ def token_2022_program
47
+ Constants::TOKEN_2022_PROGRAM_ID.to_s
48
+ end
49
+
50
+ # Setup accounts required for close account instruction
51
+ # Called automatically during initialization
52
+ #
53
+ # @return [void]
54
+ def setup_accounts
55
+ account_context.add_writable_nonsigner(account)
56
+ account_context.add_writable_nonsigner(destination)
57
+ account_context.add_readonly_signer(authority)
58
+ account_context.add_readonly_nonsigner(token_2022_program)
59
+ end
60
+
61
+ # Build instruction with resolved account indices
62
+ #
63
+ # @param account_context [Utils::AccountContext] The account context
64
+ # @return [Solace::Instruction]
65
+ def build_instruction(account_context)
66
+ Instructions::Token2022::CloseAccountInstruction.build(
67
+ account_index: account_context.index_of(account),
68
+ authority_index: account_context.index_of(authority),
69
+ destination_index: account_context.index_of(destination),
70
+ program_index: account_context.index_of(token_2022_program)
71
+ )
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,93 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solace
4
+ module Composers
5
+ # Composer for initializing a mint via the Token-2022 Program.
6
+ #
7
+ # This composer resolves and orders the required accounts for an `InitializeMint`
8
+ # instruction, sets up their access permissions, and delegates construction to the
9
+ # appropriate instruction builder (`Instructions::Token2022::InitializeMintInstruction`).
10
+ #
11
+ # Required accounts:
12
+ # - **Mint Account**: the mint account to initialize (writable, non-signer)
13
+ # - **Rent Sysvar**: the rent sysvar (readonly, non-signer)
14
+ # - **Program**: Token-2022 program (readonly, non-signer)
15
+ #
16
+ # @example Compose and build an initialize_mint instruction
17
+ # composer = Token2022ProgramInitializeMintComposer.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::Token2022::InitializeMintInstruction
25
+ # @since 0.1.5
26
+ class Token2022ProgramInitializeMintComposer < 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
+ # @return [String] The Token-2022 program id.
42
+ def token_2022_program
43
+ Constants::TOKEN_2022_PROGRAM_ID.to_s
44
+ end
45
+
46
+ # Extracts the mint authority address from the params
47
+ #
48
+ # @return [String] The mint authority address
49
+ def mint_authority
50
+ params[:mint_authority].to_s
51
+ end
52
+
53
+ # Extracts the freeze authority address from the params
54
+ #
55
+ # @return [String] The freeze authority address
56
+ def freeze_authority
57
+ params[:freeze_authority]&.to_s
58
+ end
59
+
60
+ # Returns the decimals for the mint
61
+ #
62
+ # @return [Integer] The decimals for the mint
63
+ def decimals
64
+ params[:decimals]
65
+ end
66
+
67
+ # Setup accounts required for the InitializeMint instruction
68
+ # Called automatically during initialization
69
+ #
70
+ # @return [void]
71
+ def setup_accounts
72
+ account_context.add_writable_nonsigner(mint_account)
73
+ account_context.add_readonly_nonsigner(rent_sysvar)
74
+ account_context.add_readonly_nonsigner(token_2022_program)
75
+ end
76
+
77
+ # Build instruction with resolved account indices
78
+ #
79
+ # @param account_context [Utils::AccountContext] The account context
80
+ # @return [Solace::Instruction]
81
+ def build_instruction(account_context)
82
+ Instructions::Token2022::InitializeMintInstruction.build(
83
+ mint_account_index: account_context.index_of(mint_account),
84
+ rent_sysvar_index: account_context.index_of(rent_sysvar),
85
+ program_index: account_context.index_of(token_2022_program),
86
+ decimals: decimals,
87
+ mint_authority: mint_authority,
88
+ freeze_authority: freeze_authority
89
+ )
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solace
4
+ module Composers
5
+ # Composer for creating a MintTo instruction for the Token-2022 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.
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::Token2022ProgramMintToComposer.new(
17
+ # mint: mint,
18
+ # destination: destination,
19
+ # mint_authority: mint_authority,
20
+ # amount: 100
21
+ # )
22
+ #
23
+ # @since 0.1.5
24
+ class Token2022ProgramMintToComposer < 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
+ # @return [String] The Token-2022 program id.
47
+ def token_2022_program
48
+ Constants::TOKEN_2022_PROGRAM_ID.to_s
49
+ end
50
+
51
+ # Extracts the amount from the params
52
+ #
53
+ # @return [Integer] The amount
54
+ def amount
55
+ params[:amount].to_i
56
+ end
57
+
58
+ # Setup accounts required for MintTo instruction
59
+ # Called automatically during initialization
60
+ #
61
+ # @return [void]
62
+ def setup_accounts
63
+ account_context.add_writable_nonsigner(mint)
64
+ account_context.add_writable_nonsigner(destination)
65
+ account_context.add_readonly_signer(mint_authority)
66
+ account_context.add_readonly_nonsigner(token_2022_program)
67
+ end
68
+
69
+ # Build instruction with resolved account indices
70
+ #
71
+ # @param account_context [Utils::AccountContext] The account context
72
+ # @return [Solace::Instruction]
73
+ def build_instruction(account_context)
74
+ Instructions::Token2022::MintToInstruction.build(
75
+ amount: amount,
76
+ mint_index: account_context.index_of(mint),
77
+ destination_index: account_context.index_of(destination),
78
+ mint_authority_index: account_context.index_of(mint_authority),
79
+ program_index: account_context.index_of(token_2022_program)
80
+ )
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,109 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solace
4
+ module Composers
5
+ # Composer for creating a Token-2022 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::Token2022::TransferCheckedInstruction`).
10
+ #
11
+ # Required accounts:
12
+ # - **From**: source token account (writable, non-signer)
13
+ # - **To**: destination token account (writable, non-signer)
14
+ # - **Mint**: mint address (readonly, non-signer)
15
+ # - **Authority**: token owner (writable, signer)
16
+ # - **Program**: Token-2022 program (readonly, non-signer)
17
+ #
18
+ # @example Compose and build a transfer_checked instruction
19
+ # composer = Token2022ProgramTransferCheckedComposer.new(
20
+ # from: from_address,
21
+ # to: to_address,
22
+ # mint: mint_address,
23
+ # authority: authority_pubkey,
24
+ # amount: 1_000_000,
25
+ # decimals: 6
26
+ # )
27
+ #
28
+ # @see Instructions::Token2022::TransferCheckedInstruction
29
+ # @since 0.1.5
30
+ class Token2022ProgramTransferCheckedComposer < Base
31
+ # Extracts the to address from the params
32
+ #
33
+ # @return [String] The to address
34
+ def to
35
+ params[:to].to_s
36
+ end
37
+
38
+ # Extracts the from address from the params
39
+ #
40
+ # @return [String] The from address
41
+ def from
42
+ params[:from].to_s
43
+ end
44
+
45
+ # Extracts the authority address from the params
46
+ #
47
+ # The authority is the owner of the token account
48
+ #
49
+ # @return [String] The authority address
50
+ def authority
51
+ params[:authority].to_s
52
+ end
53
+
54
+ # Extracts the mint address from the params
55
+ #
56
+ # @return [String] The mint address
57
+ def mint
58
+ params[:mint].to_s
59
+ end
60
+
61
+ # @return [String] The Token-2022 program id.
62
+ def token_2022_program
63
+ Constants::TOKEN_2022_PROGRAM_ID.to_s
64
+ end
65
+
66
+ # Returns the amount to transfer
67
+ #
68
+ # @return [Integer] The amount to transfer
69
+ def amount
70
+ params[:amount]
71
+ end
72
+
73
+ # Returns the decimals for the mint of the token
74
+ #
75
+ # @return [Integer] The decimals for the mint
76
+ def decimals
77
+ params[:decimals]
78
+ end
79
+
80
+ # Setup accounts required for transfer instruction
81
+ # Called automatically during initialization
82
+ #
83
+ # @return [void]
84
+ def setup_accounts
85
+ account_context.add_writable_signer(authority)
86
+ account_context.add_writable_nonsigner(to)
87
+ account_context.add_writable_nonsigner(from)
88
+ account_context.add_readonly_nonsigner(mint)
89
+ account_context.add_readonly_nonsigner(token_2022_program)
90
+ end
91
+
92
+ # Build instruction with resolved account indices
93
+ #
94
+ # @param account_context [Utils::AccountContext] The account context
95
+ # @return [Solace::Instruction]
96
+ def build_instruction(account_context)
97
+ Instructions::Token2022::TransferCheckedInstruction.build(
98
+ amount: amount,
99
+ decimals: decimals,
100
+ to_index: account_context.index_of(to),
101
+ from_index: account_context.index_of(from),
102
+ mint_index: account_context.index_of(mint),
103
+ authority_index: account_context.index_of(authority),
104
+ program_index: account_context.index_of(token_2022_program)
105
+ )
106
+ end
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solace
4
+ module Composers
5
+ # Composer for creating a Token-2022 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::Token2022::TransferInstruction`).
10
+ #
11
+ # Required accounts:
12
+ # - **Owner**: token account owner (writable, signer)
13
+ # - **Source**: source token account (writable, non-signer)
14
+ # - **Destination**: destination token account (writable, non-signer)
15
+ #
16
+ # @example Compose and build a transfer instruction
17
+ # composer = Token2022ProgramTransferComposer.new(
18
+ # amount: 1_000_000,
19
+ # owner: owner_address,
20
+ # source: source_address,
21
+ # destination: destination_address,
22
+ # )
23
+ #
24
+ # @see Instructions::Token2022::TransferInstruction
25
+ # @since 0.1.5
26
+ class Token2022ProgramTransferComposer < Base
27
+ # Extracts the owner address from the params
28
+ #
29
+ # @return [String] The owner address
30
+ def owner
31
+ params[:owner].to_s
32
+ end
33
+
34
+ # Extracts the source associated token address from the params
35
+ #
36
+ # @return [String] The source associated token address
37
+ def source
38
+ params[:source].to_s
39
+ end
40
+
41
+ # Extracts the destination associated token address from the params
42
+ #
43
+ # @return [String] The destination associated token address
44
+ def destination
45
+ params[:destination].to_s
46
+ end
47
+
48
+ # @return [String] The Token-2022 program id.
49
+ def token_2022_program
50
+ Constants::TOKEN_2022_PROGRAM_ID.to_s
51
+ end
52
+
53
+ # Returns the lamports to transfer
54
+ #
55
+ # @return [Integer] The lamports to transfer
56
+ def amount
57
+ params[:amount]
58
+ end
59
+
60
+ # Setup accounts required for transfer instruction
61
+ # Called automatically during initialization
62
+ #
63
+ # @return [void]
64
+ def setup_accounts
65
+ account_context.add_writable_signer(owner)
66
+ account_context.add_writable_nonsigner(source)
67
+ account_context.add_writable_nonsigner(destination)
68
+ account_context.add_readonly_nonsigner(token_2022_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::Token2022::TransferInstruction.build(
77
+ amount: amount,
78
+ owner_index: account_context.index_of(owner),
79
+ source_index: account_context.index_of(source),
80
+ destination_index: account_context.index_of(destination),
81
+ program_index: account_context.index_of(token_2022_program)
82
+ )
83
+ end
84
+ end
85
+ end
86
+ end
@@ -33,6 +33,7 @@ module Solace
33
33
  # Solace::Errors::ConfirmationTimeout
34
34
  # ]
35
35
  # @since 0.0.1
36
+ # rubocop:disable Metrics/ClassLength
36
37
  class Connection
37
38
  # @!attribute [r] rpc_url
38
39
  # The URL of the Solana RPC node
@@ -196,15 +197,33 @@ module Solace
196
197
  @rpc_client.rpc_request('getTokenAccountBalance', [token_account, default_options]).dig('result', 'value')
197
198
  end
198
199
 
199
- # Gets the token accounts by owner
200
+ # Gets the token accounts by owner.
201
+ #
202
+ # Defaults to the legacy SPL Token program; pass
203
+ # +token_program_id: Solace::Constants::TOKEN_2022_PROGRAM_ID+ for Token-2022.
200
204
  #
201
205
  # @param owner [String] The public key of the owner
202
- # @return [Array<Hash>] The token accounts owned by the owner for the specified mint
203
- def get_token_accounts_by_owner(owner)
204
- params = [owner, { programId: Constants::TOKEN_PROGRAM_ID }, default_options]
206
+ # @param token_program_id [String] The token program to filter by (defaults to legacy SPL Token)
207
+ # @return [Array<Hash>] The token accounts owned by the owner under the given token program
208
+ def get_token_accounts_by_owner(owner, token_program_id: Constants::TOKEN_PROGRAM_ID)
209
+ params = [owner, { programId: token_program_id }, default_options]
205
210
  @rpc_client.rpc_request('getTokenAccountsByOwner', params).dig('result', 'value')
206
211
  end
207
212
 
213
+ # Discovery-only helper: returns the program ID that owns a given mint.
214
+ #
215
+ # Use this to dispatch between {Constants::TOKEN_PROGRAM_ID} and
216
+ # {Constants::TOKEN_2022_PROGRAM_ID} when the mint's program is not known
217
+ # ahead of time. If you also need the rest of the mint's account data
218
+ # (decimals, supply, ...), call {#get_account_info} directly and read
219
+ # +'owner'+ yourself — calling both would cost two RPC roundtrips.
220
+ #
221
+ # @param mint [String] The mint address
222
+ # @return [String, nil] The program ID that owns the mint, or +nil+ if the account does not exist
223
+ def get_mint_program_id(mint)
224
+ get_account_info(mint)&.dig('owner')
225
+ end
226
+
208
227
  # Get the transaction by signature
209
228
  #
210
229
  # @param signature [String] The signature of the transaction
@@ -335,4 +354,5 @@ module Solace
335
354
  Process.clock_gettime(Process::CLOCK_MONOTONIC) + seconds
336
355
  end
337
356
  end
357
+ # rubocop:enable Metrics/ClassLength
338
358
  end
@@ -23,10 +23,16 @@ module Solace
23
23
  COMPUTE_BUDGET_PROGRAM_ID = 'ComputeBudget111111111111111111111111111111'
24
24
 
25
25
  # @!attribute TOKEN_PROGRAM_ID
26
- # The public key of the SPL Token Program
27
- # This is the same across all Solana clusters
26
+ # The public key of the SPL Token Program (legacy).
27
+ # This is the same across all Solana clusters.
28
28
  TOKEN_PROGRAM_ID = 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA'
29
29
 
30
+ # @!attribute TOKEN_2022_PROGRAM_ID
31
+ # The public key of the Token-2022 Program (formerly Token Extensions).
32
+ # This is the same across all Solana clusters. See {Programs::Token2022}
33
+ # for the full description of how it relates to the legacy program.
34
+ TOKEN_2022_PROGRAM_ID = 'TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb'
35
+
30
36
  # @!attribute ASSOCIATED_TOKEN_ACCOUNT_PROGRAM_ID
31
37
  # The public key of the Associated Token Account Program
32
38
  # This is the same across all Solana clusters
@@ -29,7 +29,7 @@ module Solace
29
29
  # SPL Token Program transfer instruction layout:
30
30
  # - 1 byte: instruction index (12 for transfer checked)
31
31
  # - 8 bytes: amount (u64, little-endian)
32
- # - 8 bytes: decimals (u64, little-endian)
32
+ # - 1 byte: decimals (u8)
33
33
  #
34
34
  # @param amount [Integer] Amount to transfer (in tokens, according to mint's decimals)
35
35
  # @param decimals [Integer] Number of decimals for the token