solace-zar-trustless-escrow 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 (27) hide show
  1. checksums.yaml +7 -0
  2. data/lib/solace/zar_trustless_escrow/codecs_extensions.rb +101 -0
  3. data/lib/solace/zar_trustless_escrow/composers/claim_composer.rb +136 -0
  4. data/lib/solace/zar_trustless_escrow/composers/deposit_composer.rb +145 -0
  5. data/lib/solace/zar_trustless_escrow/composers/mediated_deposit_composer.rb +173 -0
  6. data/lib/solace/zar_trustless_escrow/composers/mediated_reclaim_composer.rb +137 -0
  7. data/lib/solace/zar_trustless_escrow/composers/mediated_release_composer.rb +157 -0
  8. data/lib/solace/zar_trustless_escrow/composers/reclaim_composer.rb +135 -0
  9. data/lib/solace/zar_trustless_escrow/composers/token_account_init_composer.rb +88 -0
  10. data/lib/solace/zar_trustless_escrow/constants.rb +47 -0
  11. data/lib/solace/zar_trustless_escrow/errors/program_error.rb +30 -0
  12. data/lib/solace/zar_trustless_escrow/errors.rb +104 -0
  13. data/lib/solace/zar_trustless_escrow/instructions/claim_instruction.rb +60 -0
  14. data/lib/solace/zar_trustless_escrow/instructions/deposit_instruction.rb +65 -0
  15. data/lib/solace/zar_trustless_escrow/instructions/mediated_deposit_instruction.rb +74 -0
  16. data/lib/solace/zar_trustless_escrow/instructions/mediated_reclaim_instruction.rb +60 -0
  17. data/lib/solace/zar_trustless_escrow/instructions/mediated_release_instruction.rb +65 -0
  18. data/lib/solace/zar_trustless_escrow/instructions/reclaim_instruction.rb +60 -0
  19. data/lib/solace/zar_trustless_escrow/instructions/token_account_init_instruction.rb +48 -0
  20. data/lib/solace/zar_trustless_escrow/programs/zar_trustless_escrow/escrow_deposit_operations.rb +243 -0
  21. data/lib/solace/zar_trustless_escrow/programs/zar_trustless_escrow/mediated_escrow_deposit_operations.rb +259 -0
  22. data/lib/solace/zar_trustless_escrow/programs/zar_trustless_escrow.rb +148 -0
  23. data/lib/solace/zar_trustless_escrow/types/escrow_deposit.rb +44 -0
  24. data/lib/solace/zar_trustless_escrow/types/mediated_escrow_deposit.rb +50 -0
  25. data/lib/solace/zar_trustless_escrow/version.rb +7 -0
  26. data/lib/solace/zar_trustless_escrow.rb +38 -0
  27. metadata +171 -0
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solace
4
+ module ZarTrustlessEscrow
5
+ module Instructions
6
+ # Encoder for the `mediated_deposit` instruction: locks `amount` tokens into
7
+ # a three-party MediatedEscrowDeposit PDA (keyed by `id`) and the per-mint
8
+ # program vault.
9
+ class MediatedDepositInstruction
10
+ # 8-byte Anchor discriminator: SHA256("global:mediated_deposit")[0..7].
11
+ DISCRIMINATOR = [138, 97, 90, 177, 112, 255, 208, 193].freeze
12
+
13
+ # Builds a Solace::Instruction for `mediated_deposit`.
14
+ #
15
+ # Account indices are in the on-chain order:
16
+ # mint, depositor, depositor_token_account, mediated_escrow_deposit,
17
+ # program_token_account, fee_payer, system_program, token_program.
18
+ #
19
+ # @return [Solace::Instruction]
20
+ def self.build(
21
+ amount:,
22
+ id:,
23
+ mediator:,
24
+ beneficiary:,
25
+ rent_collector:,
26
+ expires_at:,
27
+ mint_index:,
28
+ depositor_index:,
29
+ depositor_token_account_index:,
30
+ mediated_escrow_deposit_index:,
31
+ program_token_account_index:,
32
+ fee_payer_index:,
33
+ system_program_index:,
34
+ token_program_index:,
35
+ program_index:
36
+ )
37
+ Solace::Instruction.new.tap do |ix|
38
+ ix.program_index = program_index
39
+ ix.accounts = [
40
+ mint_index,
41
+ depositor_index,
42
+ depositor_token_account_index,
43
+ mediated_escrow_deposit_index,
44
+ program_token_account_index,
45
+ fee_payer_index,
46
+ system_program_index,
47
+ token_program_index
48
+ ]
49
+ ix.data = data(amount:, id:, mediator:, beneficiary:, rent_collector:, expires_at:)
50
+ end
51
+ end
52
+
53
+ # Encodes the MediatedDepositCreateArgs struct in Borsh format.
54
+ #
55
+ # @param amount [Integer] u64 amount to deposit.
56
+ # @param id [#to_s] base58 unique id used to derive the mediated escrow PDA.
57
+ # @param mediator [#to_s] base58 mediator who decides the outcome.
58
+ # @param beneficiary [#to_s] base58 beneficiary the mediator may release to.
59
+ # @param rent_collector [#to_s, nil] optional base58 rent collector on close.
60
+ # @param expires_at [Integer, nil] optional unix timestamp for depositor reclaim.
61
+ # @return [Array<Integer>]
62
+ def self.data(amount:, id:, mediator:, beneficiary:, rent_collector:, expires_at:)
63
+ DISCRIMINATOR +
64
+ Solace::Utils::Codecs.encode_le_u64(amount).bytes +
65
+ Solace::Utils::Codecs.encode_pubkey(id) +
66
+ Solace::Utils::Codecs.encode_pubkey(mediator) +
67
+ Solace::Utils::Codecs.encode_pubkey(beneficiary) +
68
+ Solace::Utils::Codecs.encode_option_pubkey(rent_collector) +
69
+ Solace::Utils::Codecs.encode_option_i64(expires_at)
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solace
4
+ module ZarTrustlessEscrow
5
+ module Instructions
6
+ # Encoder for the `mediated_reclaim` instruction: after expiry, the original
7
+ # depositor reclaims a MediatedEscrowDeposit and closes the deposit account.
8
+ class MediatedReclaimInstruction
9
+ # 8-byte Anchor discriminator: SHA256("global:mediated_reclaim")[0..7].
10
+ DISCRIMINATOR = [192, 255, 211, 122, 12, 11, 191, 146].freeze
11
+
12
+ # Builds a Solace::Instruction for `mediated_reclaim`.
13
+ #
14
+ # Account indices are in the on-chain order:
15
+ # mint, depositor, depositor_token_account, mediated_escrow_deposit,
16
+ # program_token_account, fee_payer, system_program, token_program,
17
+ # associated_token_program.
18
+ #
19
+ # @return [Solace::Instruction]
20
+ def self.build(
21
+ id:,
22
+ mint_index:,
23
+ depositor_index:,
24
+ depositor_token_account_index:,
25
+ mediated_escrow_deposit_index:,
26
+ program_token_account_index:,
27
+ fee_payer_index:,
28
+ system_program_index:,
29
+ token_program_index:,
30
+ associated_token_program_index:,
31
+ program_index:
32
+ )
33
+ Solace::Instruction.new.tap do |ix|
34
+ ix.program_index = program_index
35
+ ix.accounts = [
36
+ mint_index,
37
+ depositor_index,
38
+ depositor_token_account_index,
39
+ mediated_escrow_deposit_index,
40
+ program_token_account_index,
41
+ fee_payer_index,
42
+ system_program_index,
43
+ token_program_index,
44
+ associated_token_program_index
45
+ ]
46
+ ix.data = data(id:)
47
+ end
48
+ end
49
+
50
+ # Encodes the MediatedReclaimCreateArgs struct in Borsh format.
51
+ #
52
+ # @param id [#to_s] base58 unique id used to derive the mediated escrow PDA.
53
+ # @return [Array<Integer>]
54
+ def self.data(id:)
55
+ DISCRIMINATOR + Solace::Utils::Codecs.encode_pubkey(id)
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solace
4
+ module ZarTrustlessEscrow
5
+ module Instructions
6
+ # Encoder for the `mediated_release` instruction: the mediator releases a
7
+ # MediatedEscrowDeposit to the recipient (depositor or beneficiary) and
8
+ # closes the deposit, sending rent to the rent collector.
9
+ class MediatedReleaseInstruction
10
+ # 8-byte Anchor discriminator: SHA256("global:mediated_release")[0..7].
11
+ DISCRIMINATOR = [154, 204, 22, 195, 162, 179, 197, 181].freeze
12
+
13
+ # Builds a Solace::Instruction for `mediated_release`.
14
+ #
15
+ # Account indices are in the on-chain order:
16
+ # mint, mediator, recipient, recipient_token_account,
17
+ # mediated_escrow_deposit, program_token_account, rent_collector,
18
+ # fee_payer, system_program, token_program, associated_token_program.
19
+ #
20
+ # @return [Solace::Instruction]
21
+ def self.build(
22
+ id:,
23
+ mint_index:,
24
+ mediator_index:,
25
+ recipient_index:,
26
+ recipient_token_account_index:,
27
+ mediated_escrow_deposit_index:,
28
+ program_token_account_index:,
29
+ rent_collector_index:,
30
+ fee_payer_index:,
31
+ system_program_index:,
32
+ token_program_index:,
33
+ associated_token_program_index:,
34
+ program_index:
35
+ )
36
+ Solace::Instruction.new.tap do |ix|
37
+ ix.program_index = program_index
38
+ ix.accounts = [
39
+ mint_index,
40
+ mediator_index,
41
+ recipient_index,
42
+ recipient_token_account_index,
43
+ mediated_escrow_deposit_index,
44
+ program_token_account_index,
45
+ rent_collector_index,
46
+ fee_payer_index,
47
+ system_program_index,
48
+ token_program_index,
49
+ associated_token_program_index
50
+ ]
51
+ ix.data = data(id:)
52
+ end
53
+ end
54
+
55
+ # Encodes the MediatedReleaseArgs struct in Borsh format.
56
+ #
57
+ # @param id [#to_s] base58 unique id used to derive the mediated escrow PDA.
58
+ # @return [Array<Integer>]
59
+ def self.data(id:)
60
+ DISCRIMINATOR + Solace::Utils::Codecs.encode_pubkey(id)
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solace
4
+ module ZarTrustlessEscrow
5
+ module Instructions
6
+ # Encoder for the `re_claim` instruction: the original depositor (or sponsor)
7
+ # reclaims an unclaimed EscrowDeposit and closes the deposit account.
8
+ class ReclaimInstruction
9
+ # 8-byte Anchor discriminator: SHA256("global:re_claim")[0..7].
10
+ DISCRIMINATOR = [105, 179, 220, 94, 121, 140, 144, 24].freeze
11
+
12
+ # Builds a Solace::Instruction for `re_claim`.
13
+ #
14
+ # Account indices are in the on-chain order:
15
+ # mint, depositor, depositor_token_account, escrow_deposit,
16
+ # program_token_account, fee_payer, system_program, token_program,
17
+ # associated_token_program.
18
+ #
19
+ # @return [Solace::Instruction]
20
+ def self.build(
21
+ claim_authority:,
22
+ mint_index:,
23
+ depositor_index:,
24
+ depositor_token_account_index:,
25
+ escrow_deposit_index:,
26
+ program_token_account_index:,
27
+ fee_payer_index:,
28
+ system_program_index:,
29
+ token_program_index:,
30
+ associated_token_program_index:,
31
+ program_index:
32
+ )
33
+ Solace::Instruction.new.tap do |ix|
34
+ ix.program_index = program_index
35
+ ix.accounts = [
36
+ mint_index,
37
+ depositor_index,
38
+ depositor_token_account_index,
39
+ escrow_deposit_index,
40
+ program_token_account_index,
41
+ fee_payer_index,
42
+ system_program_index,
43
+ token_program_index,
44
+ associated_token_program_index
45
+ ]
46
+ ix.data = data(claim_authority:)
47
+ end
48
+ end
49
+
50
+ # Encodes the ReclaimCreateArgs struct in Borsh format.
51
+ #
52
+ # @param claim_authority [#to_s] base58 authority used to derive the escrow PDA.
53
+ # @return [Array<Integer>]
54
+ def self.data(claim_authority:)
55
+ DISCRIMINATOR + Solace::Utils::Codecs.encode_pubkey(claim_authority)
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solace
4
+ module ZarTrustlessEscrow
5
+ module Instructions
6
+ # Encoder for the `token_account_init` instruction: initializes the per-mint
7
+ # program vault token account if it does not already exist.
8
+ class TokenAccountInitInstruction
9
+ # 8-byte Anchor discriminator: SHA256("global:token_account_init")[0..7].
10
+ DISCRIMINATOR = [124, 4, 173, 7, 212, 208, 18, 239].freeze
11
+
12
+ # Builds a Solace::Instruction for `token_account_init`.
13
+ #
14
+ # Account indices are in the on-chain order:
15
+ # mint, program_token_account, fee_payer, system_program, token_program.
16
+ #
17
+ # @return [Solace::Instruction]
18
+ def self.build(
19
+ mint_index:,
20
+ program_token_account_index:,
21
+ fee_payer_index:,
22
+ system_program_index:,
23
+ token_program_index:,
24
+ program_index:
25
+ )
26
+ Solace::Instruction.new.tap do |ix|
27
+ ix.program_index = program_index
28
+ ix.accounts = [
29
+ mint_index,
30
+ program_token_account_index,
31
+ fee_payer_index,
32
+ system_program_index,
33
+ token_program_index
34
+ ]
35
+ ix.data = data
36
+ end
37
+ end
38
+
39
+ # Encodes the `token_account_init` instruction data (discriminator only — no args).
40
+ #
41
+ # @return [Array<Integer>]
42
+ def self.data
43
+ DISCRIMINATOR.dup
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,243 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solace
4
+ module Programs
5
+ class ZarTrustlessEscrow < Base
6
+ # Two-party escrow operations for {Solace::Programs::ZarTrustlessEscrow}:
7
+ # deposit, claim, and reclaim against the EscrowDeposit account. Mixed into
8
+ # the program client; methods run in the client's instance context
9
+ # (connection, program_id, and the get_*_address derivations are available).
10
+ # The per-mint vault setup (token_account_init) is shared across escrow types
11
+ # and lives on the client itself, not here.
12
+ module EscrowDepositOperations
13
+ # Fetches and deserializes the EscrowDeposit account at the given address.
14
+ # Derive the address first with {#get_escrow_deposit_address}.
15
+ #
16
+ # @param address [#to_s] Base58 address of the EscrowDeposit account.
17
+ # @return [Solace::ZarTrustlessEscrow::EscrowDeposit] The deserialized deposit.
18
+ # @raise [RuntimeError] If no account exists at the address.
19
+ def fetch_escrow_deposit(address:)
20
+ account = connection.get_account_info(address.to_s)
21
+ raise "EscrowDeposit account not found at #{address}" unless account
22
+
23
+ Solace::ZarTrustlessEscrow::EscrowDeposit.deserialize(
24
+ Solace::Utils::Codecs.base64_to_bytestream(account['data'][0])
25
+ )
26
+ end
27
+
28
+ # Returns whether an EscrowDeposit account exists at the given address.
29
+ # Derive the address first with {#get_escrow_deposit_address}.
30
+ #
31
+ # @param address [#to_s] Base58 address of the EscrowDeposit account.
32
+ # @return [Boolean] True if an account exists at the address.
33
+ def escrow_deposit_exists?(address:)
34
+ !connection.get_account_info(address.to_s).nil?
35
+ end
36
+
37
+ # Deposits funds into a two-party escrow, signs, and (optionally) sends it.
38
+ # The depositor and fee payer sign; when a sponsor pays, pass the sponsor
39
+ # keypair as payer and its address as sponsor.
40
+ #
41
+ # @param payer [Solace::Keypair] The fee payer (the depositor or the sponsor).
42
+ # @param depositor [Solace::Keypair] The depositor (signs).
43
+ # @param sign [Boolean] Whether to sign the transaction.
44
+ # @param execute [Boolean] Whether to send the transaction.
45
+ # @param composer_opts [Hash] Options for {#compose_deposit}.
46
+ # @return [Solace::Transaction] The created or sent transaction.
47
+ def deposit(payer:, depositor:, sign: true, execute: true, **composer_opts)
48
+ composer = compose_deposit(fee_payer: payer, depositor:, **composer_opts)
49
+
50
+ yield composer if block_given?
51
+
52
+ tx = composer
53
+ .set_fee_payer(payer)
54
+ .compose_transaction
55
+
56
+ if sign
57
+ tx.sign(payer, depositor)
58
+
59
+ connection.send_transaction(tx.serialize) if execute
60
+ end
61
+
62
+ tx
63
+ end
64
+
65
+ # Prepares a deposit transaction. Derives the EscrowDeposit PDA, the program
66
+ # vault, and the depositor's associated token account.
67
+ #
68
+ # @param mint [#to_s] Mint of the escrowed tokens.
69
+ # @param depositor [#to_s, Keypair] The depositor.
70
+ # @param claim_authority [#to_s] Authority that can claim the deposit.
71
+ # @param amount [Integer] u64 amount to deposit.
72
+ # @param fee_payer [#to_s, Keypair] The fee payer (writable signer).
73
+ # @param sponsor [#to_s] (Optional) Fee sponsor recorded on the deposit (default: nil).
74
+ # @param token_program_id [String] Token program that owns the mint (default: legacy SPL Token).
75
+ # @return [Solace::TransactionComposer] A composer with the deposit instruction.
76
+ def compose_deposit(
77
+ mint:,
78
+ depositor:,
79
+ claim_authority:,
80
+ amount:,
81
+ fee_payer:,
82
+ sponsor: nil,
83
+ token_program_id: Solace::Constants::TOKEN_PROGRAM_ID
84
+ )
85
+ escrow_deposit, = get_escrow_deposit_address(claim_authority:)
86
+ program_token_account, = get_vault_address(mint:)
87
+ depositor_token_account, = Solace::Programs::AssociatedTokenAccount.get_address(
88
+ owner: depositor,
89
+ mint:,
90
+ token_program_id:
91
+ )
92
+
93
+ ix = Composers::ZarTrustlessEscrowDepositComposer.new(
94
+ mint:,
95
+ depositor:,
96
+ depositor_token_account:,
97
+ escrow_deposit:,
98
+ program_token_account:,
99
+ fee_payer:,
100
+ amount:,
101
+ claim_authority:,
102
+ sponsor:,
103
+ program_id:,
104
+ token_program_id:
105
+ )
106
+
107
+ TransactionComposer.new(connection:).add_instruction(ix)
108
+ end
109
+
110
+ # Claims a two-party escrow on behalf of the claim authority, signs, and
111
+ # (optionally) sends it. The claim authority and fee payer sign.
112
+ #
113
+ # @param payer [Solace::Keypair] The fee payer (signs).
114
+ # @param claim_authority [Solace::Keypair] The claim authority (signs).
115
+ # @param sign [Boolean] Whether to sign the transaction.
116
+ # @param execute [Boolean] Whether to send the transaction.
117
+ # @param composer_opts [Hash] Options for {#compose_claim}.
118
+ # @return [Solace::Transaction] The created or sent transaction.
119
+ def claim(payer:, claim_authority:, sign: true, execute: true, **composer_opts)
120
+ composer = compose_claim(fee_payer: payer, claim_authority:, **composer_opts)
121
+
122
+ yield composer if block_given?
123
+
124
+ tx = composer
125
+ .set_fee_payer(payer)
126
+ .compose_transaction
127
+
128
+ if sign
129
+ tx.sign(payer, claim_authority)
130
+
131
+ connection.send_transaction(tx.serialize) if execute
132
+ end
133
+
134
+ tx
135
+ end
136
+
137
+ # Prepares a claim transaction. Derives the EscrowDeposit PDA, the program
138
+ # vault, and the claimant's associated token account.
139
+ #
140
+ # @param mint [#to_s] Mint of the escrowed tokens.
141
+ # @param claim_authority [#to_s, Keypair] Authority that can claim the deposit.
142
+ # @param claimant [#to_s] Recipient of the released tokens.
143
+ # @param fee_payer [#to_s, Keypair] The fee payer (writable signer).
144
+ # @param token_program_id [String] Token program that owns the mint (default: legacy SPL Token).
145
+ # @return [Solace::TransactionComposer] A composer with the claim instruction.
146
+ def compose_claim(
147
+ mint:,
148
+ claim_authority:,
149
+ claimant:,
150
+ fee_payer:,
151
+ token_program_id: Solace::Constants::TOKEN_PROGRAM_ID
152
+ )
153
+ escrow_deposit, = get_escrow_deposit_address(claim_authority:)
154
+ program_token_account, = get_vault_address(mint:)
155
+ claimant_token_account, = Solace::Programs::AssociatedTokenAccount.get_address(
156
+ owner: claimant,
157
+ mint:,
158
+ token_program_id:
159
+ )
160
+
161
+ ix = Composers::ZarTrustlessEscrowClaimComposer.new(
162
+ mint:,
163
+ claim_authority:,
164
+ claimant:,
165
+ claimant_token_account:,
166
+ escrow_deposit:,
167
+ program_token_account:,
168
+ fee_payer:,
169
+ program_id:,
170
+ token_program_id:
171
+ )
172
+
173
+ TransactionComposer.new(connection:).add_instruction(ix)
174
+ end
175
+
176
+ # Reclaims an unclaimed two-party escrow, signs, and (optionally) sends it.
177
+ # The fee payer (the depositor or the sponsor) is the only signer.
178
+ #
179
+ # @param payer [Solace::Keypair] The fee payer (the depositor or the sponsor).
180
+ # @param sign [Boolean] Whether to sign the transaction.
181
+ # @param execute [Boolean] Whether to send the transaction.
182
+ # @param composer_opts [Hash] Options for {#compose_reclaim}.
183
+ # @return [Solace::Transaction] The created or sent transaction.
184
+ def reclaim(payer:, sign: true, execute: true, **composer_opts)
185
+ composer = compose_reclaim(fee_payer: payer, **composer_opts)
186
+
187
+ yield composer if block_given?
188
+
189
+ tx = composer
190
+ .set_fee_payer(payer)
191
+ .compose_transaction
192
+
193
+ if sign
194
+ tx.sign(payer)
195
+
196
+ connection.send_transaction(tx.serialize) if execute
197
+ end
198
+
199
+ tx
200
+ end
201
+
202
+ # Prepares a reclaim transaction. Derives the EscrowDeposit PDA, the program
203
+ # vault, and the depositor's associated token account.
204
+ #
205
+ # @param mint [#to_s] Mint of the escrowed tokens.
206
+ # @param depositor [#to_s] Original depositor (receives the tokens).
207
+ # @param claim_authority [#to_s] Authority used to derive the escrow PDA.
208
+ # @param fee_payer [#to_s, Keypair] The fee payer (the depositor or the sponsor).
209
+ # @param token_program_id [String] Token program that owns the mint (default: legacy SPL Token).
210
+ # @return [Solace::TransactionComposer] A composer with the reclaim instruction.
211
+ def compose_reclaim(
212
+ mint:,
213
+ depositor:,
214
+ claim_authority:,
215
+ fee_payer:,
216
+ token_program_id: Solace::Constants::TOKEN_PROGRAM_ID
217
+ )
218
+ escrow_deposit, = get_escrow_deposit_address(claim_authority:)
219
+ program_token_account, = get_vault_address(mint:)
220
+ depositor_token_account, = Solace::Programs::AssociatedTokenAccount.get_address(
221
+ owner: depositor,
222
+ mint:,
223
+ token_program_id:
224
+ )
225
+
226
+ ix = Composers::ZarTrustlessEscrowReclaimComposer.new(
227
+ mint:,
228
+ depositor:,
229
+ depositor_token_account:,
230
+ escrow_deposit:,
231
+ program_token_account:,
232
+ fee_payer:,
233
+ claim_authority:,
234
+ program_id:,
235
+ token_program_id:
236
+ )
237
+
238
+ TransactionComposer.new(connection:).add_instruction(ix)
239
+ end
240
+ end
241
+ end
242
+ end
243
+ end