solace 0.1.4 → 0.1.6

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 (58) hide show
  1. checksums.yaml +4 -4
  2. data/lib/solace/composers/associated_token_account_program_create_account_composer.rb +11 -10
  3. data/lib/solace/composers/associated_token_account_program_create_idempotent_account_composer.rb +2 -1
  4. data/lib/solace/composers/base.rb +1 -1
  5. data/lib/solace/composers/spl_token_program_close_account_composer.rb +3 -3
  6. data/lib/solace/composers/spl_token_program_initialize_mint_composer.rb +5 -5
  7. data/lib/solace/composers/spl_token_program_mint_to_composer.rb +4 -4
  8. data/lib/solace/composers/spl_token_program_transfer_checked_composer.rb +6 -6
  9. data/lib/solace/composers/spl_token_program_transfer_composer.rb +4 -4
  10. data/lib/solace/composers/system_program_create_account_composer.rb +5 -5
  11. data/lib/solace/composers/system_program_transfer_composer.rb +3 -3
  12. data/lib/solace/composers/token_2022_program_close_account_composer.rb +75 -0
  13. data/lib/solace/composers/token_2022_program_initialize_mint_composer.rb +93 -0
  14. data/lib/solace/composers/token_2022_program_mint_to_composer.rb +84 -0
  15. data/lib/solace/composers/token_2022_program_transfer_checked_composer.rb +109 -0
  16. data/lib/solace/composers/token_2022_program_transfer_composer.rb +86 -0
  17. data/lib/solace/connection.rb +29 -9
  18. data/lib/solace/constants.rb +8 -2
  19. data/lib/solace/errors/confirmation_timeout.rb +4 -4
  20. data/lib/solace/errors/rpc_error.rb +4 -4
  21. data/lib/solace/instructions/associated_token_account/create_account_instruction.rb +2 -1
  22. data/lib/solace/instructions/spl_token/close_account_instruction.rb +2 -2
  23. data/lib/solace/instructions/spl_token/initialize_account_instruction.rb +2 -2
  24. data/lib/solace/instructions/spl_token/initialize_mint_instruction.rb +2 -2
  25. data/lib/solace/instructions/spl_token/mint_to_instruction.rb +2 -2
  26. data/lib/solace/instructions/spl_token/transfer_checked_instruction.rb +3 -3
  27. data/lib/solace/instructions/spl_token/transfer_instruction.rb +2 -2
  28. data/lib/solace/instructions/system_program/create_account_instruction.rb +2 -2
  29. data/lib/solace/instructions/system_program/transfer_instruction.rb +2 -2
  30. data/lib/solace/instructions/token_2022/close_account_instruction.rb +50 -0
  31. data/lib/solace/instructions/token_2022/initialize_account_instruction.rb +62 -0
  32. data/lib/solace/instructions/token_2022/initialize_mint_instruction.rb +75 -0
  33. data/lib/solace/instructions/token_2022/mint_to_instruction.rb +59 -0
  34. data/lib/solace/instructions/token_2022/transfer_checked_instruction.rb +68 -0
  35. data/lib/solace/instructions/token_2022/transfer_instruction.rb +71 -0
  36. data/lib/solace/message.rb +5 -5
  37. data/lib/solace/programs/associated_token_account.rb +35 -17
  38. data/lib/solace/programs/spl_token.rb +18 -254
  39. data/lib/solace/programs/token_2022.rb +70 -0
  40. data/lib/solace/programs/token_program_interface.rb +312 -0
  41. data/lib/solace/serializers/address_lookup_table_deserializer.rb +2 -2
  42. data/lib/solace/serializers/base_deserializer.rb +1 -1
  43. data/lib/solace/serializers/instruction_deserializer.rb +2 -2
  44. data/lib/solace/serializers/message_deserializer.rb +3 -3
  45. data/lib/solace/serializers/transaction_deserializer.rb +1 -1
  46. data/lib/solace/tokens/token.rb +1 -1
  47. data/lib/solace/tokens.rb +2 -2
  48. data/lib/solace/transaction.rb +1 -1
  49. data/lib/solace/transaction_composer.rb +5 -5
  50. data/lib/solace/utils/account_context.rb +9 -9
  51. data/lib/solace/utils/codecs.rb +309 -49
  52. data/lib/solace/utils/rpc_client.rb +9 -9
  53. data/lib/solace/version.rb +1 -1
  54. data/lib/solace.rb +2 -0
  55. metadata +124 -9
  56. data/CHANGELOG +0 -226
  57. data/LICENSE +0 -21
  58. data/README.md +0 -518
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 18aca49d63b09deffe93ba871b65d6b816a7c81863b0b0e2b2c2bd29ce709ce6
4
- data.tar.gz: 810a45b1324aa282684e4a5d62ea48738ac2b33a6eb87538e2e0458ca2f54593
3
+ metadata.gz: 378cd7a1cb5958d12bfbe371485f60c12c72e04141bb557a7ef61dde617b0dfe
4
+ data.tar.gz: e36f6aa0189ff832b3ca440a1a38690984d69081dcde8b9613d632320d481cf5
5
5
  SHA512:
6
- metadata.gz: 50eeac609077e873b361fdb8ed34459ccbed1b4e44d52ad911803350ea0d2f0e669fcfcb30bcddd6d20e9f54dade972a50907532a108dae7142ecca8475f42fb
7
- data.tar.gz: 5fba491757746aa8fad865bae93941f3469148c6a5fc8cb5c984ebccb79934f1b1c3425184ab37ff2342f6215a1d5b1147a9d04f6d9225a96e7c6b34c38d8b0d
6
+ metadata.gz: 9c15791a7b1967d19f676e594556f19fb29ea1b431c97e9a5f6ddb0c8344b87b4301e402116bd8896da7c14ba50a5f5de1eb5a5791b41df7c4134ee89f397926
7
+ data.tar.gz: cb1add67763169e8bb498987f3f760def67a5c92e647852f8e5e4308a5a1a41cb046df0aa8a720202d32b7c82bbe6541e945815e6e45738fd63215b23080e2bc
@@ -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
@@ -97,13 +98,13 @@ module Solace
97
98
  # @return [Solace::Instruction] The instruction
98
99
  def build_instruction(account_context)
99
100
  Instructions::AssociatedTokenAccount::CreateAccountInstruction.build(
100
- funder_index: account_context.index_of(funder),
101
- owner_index: account_context.index_of(owner),
102
- mint_index: account_context.index_of(mint),
101
+ funder_index: account_context.index_of(funder),
102
+ owner_index: account_context.index_of(owner),
103
+ mint_index: account_context.index_of(mint),
103
104
  associated_token_account_index: account_context.index_of(ata_address),
104
- system_program_index: account_context.index_of(system_program_id),
105
- token_program_index: account_context.index_of(token_program_id),
106
- program_index: account_context.index_of(associated_token_account_program_id)
105
+ system_program_index: account_context.index_of(system_program_id),
106
+ token_program_index: account_context.index_of(token_program_id),
107
+ program_index: account_context.index_of(associated_token_account_program_id)
107
108
  )
108
109
  end
109
110
  end
@@ -4,7 +4,8 @@ module Solace
4
4
  module Composers
5
5
  # Composer for creating an associated token account program create account instruction with idempotency
6
6
  #
7
- # This composer resolves and orders the required accounts for a `CreateIdempotentAssociatedTokenAccount` instruction,
7
+ # This composer resolves and orders the required accounts for a
8
+ # `CreateIdempotentAssociatedTokenAccount` instruction,
8
9
  # sets up their access permissions, and delegates construction to the appropriate
9
10
  # instruction builder (`Instructions::AssociatedTokenAccount::CreateIdempotentAssociatedTokenAccountInstruction`).
10
11
  #
@@ -57,7 +57,7 @@ module Solace
57
57
  #
58
58
  # @param params [Hash] Parameters to pass to the composer constructor
59
59
  def initialize(params)
60
- @params = params
60
+ @params = params
61
61
  @account_context = Utils::AccountContext.new
62
62
  setup_accounts
63
63
  end
@@ -70,10 +70,10 @@ module Solace
70
70
  # @return [Solace::Instruction]
71
71
  def build_instruction(account_context)
72
72
  Instructions::SplToken::CloseAccountInstruction.build(
73
- account_index: account_context.index_of(account),
74
- authority_index: account_context.index_of(authority),
73
+ account_index: account_context.index_of(account),
74
+ authority_index: account_context.index_of(authority),
75
75
  destination_index: account_context.index_of(destination),
76
- program_index: account_context.index_of(spl_token_program)
76
+ program_index: account_context.index_of(spl_token_program)
77
77
  )
78
78
  end
79
79
  end
@@ -83,11 +83,11 @@ module Solace
83
83
  def build_instruction(account_context)
84
84
  Instructions::SplToken::InitializeMintInstruction.build(
85
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
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
91
  )
92
92
  end
93
93
  end
@@ -74,11 +74,11 @@ module Solace
74
74
  # @return [Solace::Instruction]
75
75
  def build_instruction(account_context)
76
76
  Instructions::SplToken::MintToInstruction.build(
77
- amount: amount,
78
- mint_index: account_context.index_of(mint),
79
- destination_index: account_context.index_of(destination),
77
+ amount: amount,
78
+ mint_index: account_context.index_of(mint),
79
+ destination_index: account_context.index_of(destination),
80
80
  mint_authority_index: account_context.index_of(mint_authority),
81
- program_index: account_context.index_of(spl_token_program)
81
+ program_index: account_context.index_of(spl_token_program)
82
82
  )
83
83
  end
84
84
  end
@@ -99,13 +99,13 @@ module Solace
99
99
  # @return [Solace::Instruction]
100
100
  def build_instruction(account_context)
101
101
  Instructions::SplToken::TransferCheckedInstruction.build(
102
- amount: amount,
103
- decimals: decimals,
104
- to_index: account_context.index_of(to),
105
- from_index: account_context.index_of(from),
106
- mint_index: account_context.index_of(mint),
102
+ amount: amount,
103
+ decimals: decimals,
104
+ to_index: account_context.index_of(to),
105
+ from_index: account_context.index_of(from),
106
+ mint_index: account_context.index_of(mint),
107
107
  authority_index: account_context.index_of(authority),
108
- program_index: account_context.index_of(spl_token_program)
108
+ program_index: account_context.index_of(spl_token_program)
109
109
  )
110
110
  end
111
111
  end
@@ -78,11 +78,11 @@ module Solace
78
78
  # @return [Solace::Instruction]
79
79
  def build_instruction(account_context)
80
80
  Instructions::SplToken::TransferInstruction.build(
81
- amount: amount,
82
- owner_index: account_context.index_of(owner),
83
- source_index: account_context.index_of(source),
81
+ amount: amount,
82
+ owner_index: account_context.index_of(owner),
83
+ source_index: account_context.index_of(source),
84
84
  destination_index: account_context.index_of(destination),
85
- program_index: account_context.index_of(spl_token_program)
85
+ program_index: account_context.index_of(spl_token_program)
86
86
  )
87
87
  end
88
88
  end
@@ -85,11 +85,11 @@ module Solace
85
85
  # @return [Solace::Instruction]
86
86
  def build_instruction(account_context)
87
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),
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
93
  system_program_index: account_context.index_of(system_program)
94
94
  )
95
95
  end
@@ -69,9 +69,9 @@ module Solace
69
69
  # @return [Solace::Instruction]
70
70
  def build_instruction(account_context)
71
71
  Instructions::SystemProgram::TransferInstruction.build(
72
- lamports: lamports,
73
- to_index: account_context.index_of(to),
74
- from_index: account_context.index_of(from),
72
+ lamports: lamports,
73
+ to_index: account_context.index_of(to),
74
+ from_index: account_context.index_of(from),
75
75
  program_index: account_context.index_of(system_program)
76
76
  )
77
77
  end
@@ -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