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
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: cdaf827139b0191b39f2e86adf1e2bb5a714ceca4809e0ce35fd912662e90878
4
+ data.tar.gz: 7b4c7dbf1a9544a78f2bdbce3c14965caa75c96d15bd2380aeffed6e8f4acc70
5
+ SHA512:
6
+ metadata.gz: 0dcbcd5f20e0d349eed662845453561788d0c4a32a16edea05117d64d2621e6a51508bd7449370f15f7abf3e0d40e9b3e266a3bce3203e123f4dbac9a4514235
7
+ data.tar.gz: d3acc72bf804af39aadb54e0ff78f857f8c26ad87e51fdb924e5370eac60161f8c3105243e611b268df079bb94e7c978a3276eeab09ce0d0ca31719f083c10ec
@@ -0,0 +1,101 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solace
4
+ module Utils
5
+ # Extensions to Solace::Utils::Codecs for the Borsh/Anchor types used by the
6
+ # ZAR Trustless Escrow program that the base solace gem does not provide.
7
+ #
8
+ # The base gem (>= 0.1.5) already provides encode_le_u64 / decode_le_u64 and
9
+ # the base58 helpers as module (self.) methods; this module reopens Codecs and
10
+ # uses `extend self` so the helpers below are callable both as instance methods
11
+ # (within composed encoders) and as Solace::Utils::Codecs.<method>.
12
+ module Codecs
13
+ extend self
14
+
15
+ # Encodes an i64 as 8 little-endian bytes (two's complement).
16
+ #
17
+ # @param i64 [Integer] Value in range -2**63..2**63-1.
18
+ # @return [String] 8-byte little-endian binary string.
19
+ def encode_le_i64(i64)
20
+ [i64].pack('q<')
21
+ end
22
+
23
+ # Encodes a public key as 32 bytes. Accepts any representation that resolves
24
+ # to a base58 string via #to_s (String, Keypair, PublicKey).
25
+ #
26
+ # @param pubkey [#to_s] The public key in any representation.
27
+ # @return [Array<Integer>] 32 bytes.
28
+ def encode_pubkey(pubkey)
29
+ Solace::Utils::Codecs.base58_to_bytes(pubkey.to_s)
30
+ end
31
+
32
+ # Encodes an Option<publicKey> in Borsh format.
33
+ # None → [0], Some(key) → [1] + 32 bytes.
34
+ #
35
+ # @param pubkey [#to_s, nil] Base58 public key or nil.
36
+ # @return [Array<Integer>]
37
+ def encode_option_pubkey(pubkey)
38
+ return [0] if pubkey.nil?
39
+
40
+ [1] + encode_pubkey(pubkey)
41
+ end
42
+
43
+ # Encodes an Option<i64> in Borsh format.
44
+ # None → [0], Some(i64) → [1] + 8 little-endian bytes.
45
+ #
46
+ # @param i64 [Integer, nil]
47
+ # @return [Array<Integer>]
48
+ def encode_option_i64(i64)
49
+ return [0] if i64.nil?
50
+
51
+ [1] + encode_le_i64(i64).bytes
52
+ end
53
+
54
+ # Decodes a u8 from 1 byte.
55
+ #
56
+ # @param stream [IO, StringIO] The stream to read from.
57
+ # @return [Integer] Value in range 0..255.
58
+ def decode_u8(stream)
59
+ stream.read(1).unpack1('C')
60
+ end
61
+
62
+ # Decodes an i64 from 8 little-endian bytes (two's complement).
63
+ #
64
+ # @param stream [IO, StringIO] The stream to read from.
65
+ # @return [Integer] Value in range -2**63..2**63-1.
66
+ def decode_le_i64(stream)
67
+ stream.read(8).unpack1('q<')
68
+ end
69
+
70
+ # Decodes a public key from 32 bytes.
71
+ #
72
+ # @param stream [IO, StringIO] The stream to read from.
73
+ # @return [String] Base58 public key.
74
+ def decode_pubkey(stream)
75
+ Solace::Utils::Codecs.bytes_to_base58(stream.read(32).bytes)
76
+ end
77
+
78
+ # Decodes an Option<publicKey> in Borsh format.
79
+ # None → nil, Some(key) → base58 pubkey.
80
+ #
81
+ # @param stream [IO, StringIO] The stream to read from.
82
+ # @return [String, nil] Base58 public key or nil.
83
+ def decode_option_pubkey(stream)
84
+ return nil if decode_u8(stream).zero?
85
+
86
+ decode_pubkey(stream)
87
+ end
88
+
89
+ # Decodes an Option<i64> in Borsh format.
90
+ # None → nil, Some(i64) → integer.
91
+ #
92
+ # @param stream [IO, StringIO] The stream to read from.
93
+ # @return [Integer, nil]
94
+ def decode_option_i64(stream)
95
+ return nil if decode_u8(stream).zero?
96
+
97
+ decode_le_i64(stream)
98
+ end
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,136 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solace
4
+ module Composers
5
+ # Composes a `claim` instruction for the ZAR Trustless Escrow program.
6
+ #
7
+ # The claim authority releases an EscrowDeposit to the claimant and closes the
8
+ # deposit account (rent returns to the fee payer).
9
+ #
10
+ # Required params:
11
+ # :mint [#to_s] Mint of the escrowed tokens.
12
+ # :claim_authority [#to_s, Keypair] Claim authority (readonly signer).
13
+ # :claimant [#to_s] Recipient of the released tokens.
14
+ # :claimant_token_account [#to_s] Claimant's destination token account (ATA).
15
+ # :escrow_deposit [#to_s] EscrowDeposit PDA.
16
+ # :program_token_account [#to_s] Per-mint program vault PDA.
17
+ # :fee_payer [#to_s, Keypair] Fee payer (writable signer).
18
+ #
19
+ # Optional params:
20
+ # :program_id [#to_s] Escrow program id (default: PROGRAM_ID, mainnet).
21
+ # :token_program_id [#to_s] Token program (default: legacy SPL Token).
22
+ class ZarTrustlessEscrowClaimComposer < Base
23
+ # Extracts the mint address from the params
24
+ #
25
+ # @return [String] The mint address
26
+ def mint
27
+ params[:mint].to_s
28
+ end
29
+
30
+ # Extracts the claim authority from the params
31
+ #
32
+ # @return [String] The claim authority address
33
+ def claim_authority
34
+ params[:claim_authority].to_s
35
+ end
36
+
37
+ # Extracts the claimant address from the params
38
+ #
39
+ # @return [String] The claimant address
40
+ def claimant
41
+ params[:claimant].to_s
42
+ end
43
+
44
+ # Extracts the claimant's destination token account from the params
45
+ #
46
+ # @return [String] The claimant token account address
47
+ def claimant_token_account
48
+ params[:claimant_token_account].to_s
49
+ end
50
+
51
+ # Extracts the EscrowDeposit PDA address from the params
52
+ #
53
+ # @return [String] The escrow deposit address
54
+ def escrow_deposit
55
+ params[:escrow_deposit].to_s
56
+ end
57
+
58
+ # Extracts the per-mint program vault address from the params
59
+ #
60
+ # @return [String] The program token account address
61
+ def program_token_account
62
+ params[:program_token_account].to_s
63
+ end
64
+
65
+ # Extracts the fee payer address from the params
66
+ #
67
+ # @return [String] The fee payer address
68
+ def fee_payer
69
+ params[:fee_payer].to_s
70
+ end
71
+
72
+ # Returns the escrow program id (defaults to the mainnet PROGRAM_ID)
73
+ #
74
+ # @return [String] The escrow program id
75
+ def program_id
76
+ (params[:program_id] || Solace::ZarTrustlessEscrow::PROGRAM_ID).to_s
77
+ end
78
+
79
+ # Returns the token program id (defaults to the legacy SPL Token program)
80
+ #
81
+ # @return [String] The token program id
82
+ def token_program_id
83
+ (params[:token_program_id] || Solace::Constants::TOKEN_PROGRAM_ID).to_s
84
+ end
85
+
86
+ # Returns the System Program id
87
+ #
88
+ # @return [String] The System Program id
89
+ def system_program
90
+ Solace::Constants::SYSTEM_PROGRAM_ID
91
+ end
92
+
93
+ # Returns the Associated Token Account Program id
94
+ #
95
+ # @return [String] The Associated Token Account Program id
96
+ def associated_token_program
97
+ Solace::Constants::ASSOCIATED_TOKEN_ACCOUNT_PROGRAM_ID
98
+ end
99
+
100
+ # Declares all accounts required by this instruction.
101
+ def setup_accounts
102
+ account_context.add_readonly_nonsigner(mint)
103
+ account_context.add_readonly_signer(claim_authority)
104
+ account_context.add_readonly_nonsigner(claimant)
105
+ account_context.add_writable_nonsigner(claimant_token_account)
106
+ account_context.add_writable_nonsigner(escrow_deposit)
107
+ account_context.add_writable_nonsigner(program_token_account)
108
+ account_context.add_writable_signer(fee_payer)
109
+ account_context.add_readonly_nonsigner(system_program)
110
+ account_context.add_readonly_nonsigner(token_program_id)
111
+ account_context.add_readonly_nonsigner(associated_token_program)
112
+ account_context.add_readonly_nonsigner(program_id)
113
+ end
114
+
115
+ # Builds the instruction with resolved account indices.
116
+ #
117
+ # @param context [Solace::Utils::AccountContext] Merged context from TransactionComposer.
118
+ # @return [Solace::Instruction]
119
+ def build_instruction(context)
120
+ Solace::ZarTrustlessEscrow::Instructions::ClaimInstruction.build(
121
+ mint_index: context.index_of(mint),
122
+ claim_authority_index: context.index_of(claim_authority),
123
+ claimant_index: context.index_of(claimant),
124
+ claimant_token_account_index: context.index_of(claimant_token_account),
125
+ escrow_deposit_index: context.index_of(escrow_deposit),
126
+ program_token_account_index: context.index_of(program_token_account),
127
+ fee_payer_index: context.index_of(fee_payer),
128
+ system_program_index: context.index_of(system_program),
129
+ token_program_index: context.index_of(token_program_id),
130
+ associated_token_program_index: context.index_of(associated_token_program),
131
+ program_index: context.index_of(program_id)
132
+ )
133
+ end
134
+ end
135
+ end
136
+ end
@@ -0,0 +1,145 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solace
4
+ module Composers
5
+ # Composes a `deposit` instruction for the ZAR Trustless Escrow program.
6
+ #
7
+ # Locks `amount` tokens from the depositor into a per-claim-authority
8
+ # EscrowDeposit PDA and the per-mint program vault. When a sponsor pays, the
9
+ # fee payer is the sponsor; otherwise the depositor pays.
10
+ #
11
+ # Required params:
12
+ # :mint [#to_s] Mint of the escrowed tokens.
13
+ # :depositor [#to_s, Keypair] Depositor (writable signer).
14
+ # :depositor_token_account [#to_s] Depositor's source token account.
15
+ # :escrow_deposit [#to_s] EscrowDeposit PDA.
16
+ # :program_token_account [#to_s] Per-mint program vault PDA.
17
+ # :fee_payer [#to_s, Keypair] Fee payer (writable signer).
18
+ # :amount [Integer] u64 amount to deposit.
19
+ # :claim_authority [#to_s] Authority that can claim the deposit.
20
+ #
21
+ # Optional params:
22
+ # :sponsor [#to_s] Optional fee sponsor (default: nil).
23
+ # :program_id [#to_s] Escrow program id (default: PROGRAM_ID, mainnet).
24
+ # :token_program_id [#to_s] Token program (default: legacy SPL Token).
25
+ class ZarTrustlessEscrowDepositComposer < Base
26
+ # Extracts the mint address from the params
27
+ #
28
+ # @return [String] The mint address
29
+ def mint
30
+ params[:mint].to_s
31
+ end
32
+
33
+ # Extracts the depositor address from the params
34
+ #
35
+ # @return [String] The depositor address
36
+ def depositor
37
+ params[:depositor].to_s
38
+ end
39
+
40
+ # Extracts the depositor's source token account address from the params
41
+ #
42
+ # @return [String] The depositor token account address
43
+ def depositor_token_account
44
+ params[:depositor_token_account].to_s
45
+ end
46
+
47
+ # Extracts the EscrowDeposit PDA address from the params
48
+ #
49
+ # @return [String] The escrow deposit address
50
+ def escrow_deposit
51
+ params[:escrow_deposit].to_s
52
+ end
53
+
54
+ # Extracts the per-mint program vault address from the params
55
+ #
56
+ # @return [String] The program token account address
57
+ def program_token_account
58
+ params[:program_token_account].to_s
59
+ end
60
+
61
+ # Extracts the fee payer address from the params
62
+ #
63
+ # @return [String] The fee payer address
64
+ def fee_payer
65
+ params[:fee_payer].to_s
66
+ end
67
+
68
+ # Extracts the deposit amount from the params
69
+ #
70
+ # @return [Integer] The u64 amount to deposit
71
+ def amount
72
+ params[:amount]
73
+ end
74
+
75
+ # Extracts the claim authority from the params
76
+ #
77
+ # @return [String] The claim authority address
78
+ def claim_authority
79
+ params[:claim_authority].to_s
80
+ end
81
+
82
+ # Extracts the optional fee sponsor from the params
83
+ #
84
+ # @return [String, nil] The sponsor address, or nil
85
+ def sponsor
86
+ params[:sponsor]&.to_s
87
+ end
88
+
89
+ # Returns the escrow program id (defaults to the mainnet PROGRAM_ID)
90
+ #
91
+ # @return [String] The escrow program id
92
+ def program_id
93
+ (params[:program_id] || Solace::ZarTrustlessEscrow::PROGRAM_ID).to_s
94
+ end
95
+
96
+ # Returns the token program id (defaults to the legacy SPL Token program)
97
+ #
98
+ # @return [String] The token program id
99
+ def token_program_id
100
+ (params[:token_program_id] || Solace::Constants::TOKEN_PROGRAM_ID).to_s
101
+ end
102
+
103
+ # Returns the System Program id
104
+ #
105
+ # @return [String] The System Program id
106
+ def system_program
107
+ Solace::Constants::SYSTEM_PROGRAM_ID
108
+ end
109
+
110
+ # Declares all accounts required by this instruction.
111
+ def setup_accounts
112
+ account_context.add_readonly_nonsigner(mint)
113
+ account_context.add_writable_signer(depositor)
114
+ account_context.add_writable_nonsigner(depositor_token_account)
115
+ account_context.add_writable_nonsigner(escrow_deposit)
116
+ account_context.add_writable_nonsigner(program_token_account)
117
+ account_context.add_writable_signer(fee_payer)
118
+ account_context.add_readonly_nonsigner(system_program)
119
+ account_context.add_readonly_nonsigner(token_program_id)
120
+ account_context.add_readonly_nonsigner(program_id)
121
+ end
122
+
123
+ # Builds the instruction with resolved account indices.
124
+ #
125
+ # @param context [Solace::Utils::AccountContext] Merged context from TransactionComposer.
126
+ # @return [Solace::Instruction]
127
+ def build_instruction(context)
128
+ Solace::ZarTrustlessEscrow::Instructions::DepositInstruction.build(
129
+ amount:,
130
+ claim_authority:,
131
+ sponsor:,
132
+ mint_index: context.index_of(mint),
133
+ depositor_index: context.index_of(depositor),
134
+ depositor_token_account_index: context.index_of(depositor_token_account),
135
+ escrow_deposit_index: context.index_of(escrow_deposit),
136
+ program_token_account_index: context.index_of(program_token_account),
137
+ fee_payer_index: context.index_of(fee_payer),
138
+ system_program_index: context.index_of(system_program),
139
+ token_program_index: context.index_of(token_program_id),
140
+ program_index: context.index_of(program_id)
141
+ )
142
+ end
143
+ end
144
+ end
145
+ end
@@ -0,0 +1,173 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solace
4
+ module Composers
5
+ # Composes a `mediated_deposit` instruction for the ZAR Trustless Escrow
6
+ # program.
7
+ #
8
+ # Locks `amount` tokens into a three-party MediatedEscrowDeposit PDA (keyed by
9
+ # `id`) and the per-mint program vault. The mediator decides the outcome; an
10
+ # optional expiry lets the depositor reclaim after the timestamp passes.
11
+ #
12
+ # Required params:
13
+ # :mint [#to_s] Mint of the escrowed tokens.
14
+ # :depositor [#to_s, Keypair] Depositor (writable signer).
15
+ # :depositor_token_account [#to_s] Depositor's source token account.
16
+ # :mediated_escrow_deposit [#to_s] MediatedEscrowDeposit PDA.
17
+ # :program_token_account [#to_s] Per-mint program vault PDA.
18
+ # :fee_payer [#to_s, Keypair] Fee payer (writable signer).
19
+ # :amount [Integer] u64 amount to deposit.
20
+ # :id [#to_s] Unique id used to derive the escrow PDA.
21
+ # :mediator [#to_s] Mediator who decides the outcome.
22
+ # :beneficiary [#to_s] Beneficiary the mediator may release to.
23
+ #
24
+ # Optional params:
25
+ # :rent_collector [#to_s] Optional rent collector on close (default: nil).
26
+ # :expires_at [Integer] Optional unix timestamp for reclaim (default: nil).
27
+ # :program_id [#to_s] Escrow program id (default: PROGRAM_ID, mainnet).
28
+ # :token_program_id [#to_s] Token program (default: legacy SPL Token).
29
+ class ZarTrustlessEscrowMediatedDepositComposer < Base
30
+ # Extracts the mint address from the params
31
+ #
32
+ # @return [String] The mint address
33
+ def mint
34
+ params[:mint].to_s
35
+ end
36
+
37
+ # Extracts the depositor address from the params
38
+ #
39
+ # @return [String] The depositor address
40
+ def depositor
41
+ params[:depositor].to_s
42
+ end
43
+
44
+ # Extracts the depositor's source token account from the params
45
+ #
46
+ # @return [String] The depositor token account address
47
+ def depositor_token_account
48
+ params[:depositor_token_account].to_s
49
+ end
50
+
51
+ # Extracts the MediatedEscrowDeposit PDA address from the params
52
+ #
53
+ # @return [String] The mediated escrow deposit address
54
+ def mediated_escrow_deposit
55
+ params[:mediated_escrow_deposit].to_s
56
+ end
57
+
58
+ # Extracts the per-mint program vault address from the params
59
+ #
60
+ # @return [String] The program token account address
61
+ def program_token_account
62
+ params[:program_token_account].to_s
63
+ end
64
+
65
+ # Extracts the fee payer address from the params
66
+ #
67
+ # @return [String] The fee payer address
68
+ def fee_payer
69
+ params[:fee_payer].to_s
70
+ end
71
+
72
+ # Extracts the deposit amount from the params
73
+ #
74
+ # @return [Integer] The u64 amount to deposit
75
+ def amount
76
+ params[:amount]
77
+ end
78
+
79
+ # Extracts the unique escrow id from the params
80
+ #
81
+ # @return [String] The escrow id
82
+ def id
83
+ params[:id].to_s
84
+ end
85
+
86
+ # Extracts the mediator from the params
87
+ #
88
+ # @return [String] The mediator address
89
+ def mediator
90
+ params[:mediator].to_s
91
+ end
92
+
93
+ # Extracts the beneficiary from the params
94
+ #
95
+ # @return [String] The beneficiary address
96
+ def beneficiary
97
+ params[:beneficiary].to_s
98
+ end
99
+
100
+ # Extracts the optional rent collector from the params
101
+ #
102
+ # @return [String, nil] The rent collector address, or nil
103
+ def rent_collector
104
+ params[:rent_collector]&.to_s
105
+ end
106
+
107
+ # Extracts the optional expiry timestamp from the params
108
+ #
109
+ # @return [Integer, nil] The unix expiry timestamp, or nil
110
+ def expires_at
111
+ params[:expires_at]
112
+ end
113
+
114
+ # Returns the escrow program id (defaults to the mainnet PROGRAM_ID)
115
+ #
116
+ # @return [String] The escrow program id
117
+ def program_id
118
+ (params[:program_id] || Solace::ZarTrustlessEscrow::PROGRAM_ID).to_s
119
+ end
120
+
121
+ # Returns the token program id (defaults to the legacy SPL Token program)
122
+ #
123
+ # @return [String] The token program id
124
+ def token_program_id
125
+ (params[:token_program_id] || Solace::Constants::TOKEN_PROGRAM_ID).to_s
126
+ end
127
+
128
+ # Returns the System Program id
129
+ #
130
+ # @return [String] The System Program id
131
+ def system_program
132
+ Solace::Constants::SYSTEM_PROGRAM_ID
133
+ end
134
+
135
+ # Declares all accounts required by this instruction.
136
+ def setup_accounts
137
+ account_context.add_readonly_nonsigner(mint)
138
+ account_context.add_writable_signer(depositor)
139
+ account_context.add_writable_nonsigner(depositor_token_account)
140
+ account_context.add_writable_nonsigner(mediated_escrow_deposit)
141
+ account_context.add_writable_nonsigner(program_token_account)
142
+ account_context.add_writable_signer(fee_payer)
143
+ account_context.add_readonly_nonsigner(system_program)
144
+ account_context.add_readonly_nonsigner(token_program_id)
145
+ account_context.add_readonly_nonsigner(program_id)
146
+ end
147
+
148
+ # Builds the instruction with resolved account indices.
149
+ #
150
+ # @param context [Solace::Utils::AccountContext] Merged context from TransactionComposer.
151
+ # @return [Solace::Instruction]
152
+ def build_instruction(context)
153
+ Solace::ZarTrustlessEscrow::Instructions::MediatedDepositInstruction.build(
154
+ amount:,
155
+ id:,
156
+ mediator:,
157
+ beneficiary:,
158
+ rent_collector:,
159
+ expires_at:,
160
+ mint_index: context.index_of(mint),
161
+ depositor_index: context.index_of(depositor),
162
+ depositor_token_account_index: context.index_of(depositor_token_account),
163
+ mediated_escrow_deposit_index: context.index_of(mediated_escrow_deposit),
164
+ program_token_account_index: context.index_of(program_token_account),
165
+ fee_payer_index: context.index_of(fee_payer),
166
+ system_program_index: context.index_of(system_program),
167
+ token_program_index: context.index_of(token_program_id),
168
+ program_index: context.index_of(program_id)
169
+ )
170
+ end
171
+ end
172
+ end
173
+ end
@@ -0,0 +1,137 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solace
4
+ module Composers
5
+ # Composes a `mediated_reclaim` instruction for the ZAR Trustless Escrow
6
+ # program.
7
+ #
8
+ # After the escrow's expiry passes, the original depositor reclaims a
9
+ # MediatedEscrowDeposit and closes the deposit account (rent returns to the
10
+ # depositor). Requires the escrow to have been created with an expiry.
11
+ #
12
+ # Required params:
13
+ # :mint [#to_s] Mint of the escrowed tokens.
14
+ # :depositor [#to_s, Keypair] Depositor (writable signer, receives rent).
15
+ # :depositor_token_account [#to_s] Depositor's destination token account (ATA).
16
+ # :mediated_escrow_deposit [#to_s] MediatedEscrowDeposit PDA.
17
+ # :program_token_account [#to_s] Per-mint program vault PDA.
18
+ # :fee_payer [#to_s, Keypair] Fee payer (writable signer).
19
+ # :id [#to_s] Unique id used to derive the escrow PDA.
20
+ #
21
+ # Optional params:
22
+ # :program_id [#to_s] Escrow program id (default: PROGRAM_ID, mainnet).
23
+ # :token_program_id [#to_s] Token program (default: legacy SPL Token).
24
+ class ZarTrustlessEscrowMediatedReclaimComposer < 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 depositor address from the params
33
+ #
34
+ # @return [String] The depositor address
35
+ def depositor
36
+ params[:depositor].to_s
37
+ end
38
+
39
+ # Extracts the depositor's destination token account from the params
40
+ #
41
+ # @return [String] The depositor token account address
42
+ def depositor_token_account
43
+ params[:depositor_token_account].to_s
44
+ end
45
+
46
+ # Extracts the MediatedEscrowDeposit PDA address from the params
47
+ #
48
+ # @return [String] The mediated escrow deposit address
49
+ def mediated_escrow_deposit
50
+ params[:mediated_escrow_deposit].to_s
51
+ end
52
+
53
+ # Extracts the per-mint program vault address from the params
54
+ #
55
+ # @return [String] The program token account address
56
+ def program_token_account
57
+ params[:program_token_account].to_s
58
+ end
59
+
60
+ # Extracts the fee payer address from the params
61
+ #
62
+ # @return [String] The fee payer address
63
+ def fee_payer
64
+ params[:fee_payer].to_s
65
+ end
66
+
67
+ # Extracts the unique escrow id from the params
68
+ #
69
+ # @return [String] The escrow id
70
+ def id
71
+ params[:id].to_s
72
+ end
73
+
74
+ # Returns the escrow program id (defaults to the mainnet PROGRAM_ID)
75
+ #
76
+ # @return [String] The escrow program id
77
+ def program_id
78
+ (params[:program_id] || Solace::ZarTrustlessEscrow::PROGRAM_ID).to_s
79
+ end
80
+
81
+ # Returns the token program id (defaults to the legacy SPL Token program)
82
+ #
83
+ # @return [String] The token program id
84
+ def token_program_id
85
+ (params[:token_program_id] || Solace::Constants::TOKEN_PROGRAM_ID).to_s
86
+ end
87
+
88
+ # Returns the System Program id
89
+ #
90
+ # @return [String] The System Program id
91
+ def system_program
92
+ Solace::Constants::SYSTEM_PROGRAM_ID
93
+ end
94
+
95
+ # Returns the Associated Token Account Program id
96
+ #
97
+ # @return [String] The Associated Token Account Program id
98
+ def associated_token_program
99
+ Solace::Constants::ASSOCIATED_TOKEN_ACCOUNT_PROGRAM_ID
100
+ end
101
+
102
+ # Declares all accounts required by this instruction.
103
+ def setup_accounts
104
+ account_context.add_readonly_nonsigner(mint)
105
+ account_context.add_writable_signer(depositor)
106
+ account_context.add_writable_nonsigner(depositor_token_account)
107
+ account_context.add_writable_nonsigner(mediated_escrow_deposit)
108
+ account_context.add_writable_nonsigner(program_token_account)
109
+ account_context.add_writable_signer(fee_payer)
110
+ account_context.add_readonly_nonsigner(system_program)
111
+ account_context.add_readonly_nonsigner(token_program_id)
112
+ account_context.add_readonly_nonsigner(associated_token_program)
113
+ account_context.add_readonly_nonsigner(program_id)
114
+ end
115
+
116
+ # Builds the instruction with resolved account indices.
117
+ #
118
+ # @param context [Solace::Utils::AccountContext] Merged context from TransactionComposer.
119
+ # @return [Solace::Instruction]
120
+ def build_instruction(context)
121
+ Solace::ZarTrustlessEscrow::Instructions::MediatedReclaimInstruction.build(
122
+ id:,
123
+ mint_index: context.index_of(mint),
124
+ depositor_index: context.index_of(depositor),
125
+ depositor_token_account_index: context.index_of(depositor_token_account),
126
+ mediated_escrow_deposit_index: context.index_of(mediated_escrow_deposit),
127
+ program_token_account_index: context.index_of(program_token_account),
128
+ fee_payer_index: context.index_of(fee_payer),
129
+ system_program_index: context.index_of(system_program),
130
+ token_program_index: context.index_of(token_program_id),
131
+ associated_token_program_index: context.index_of(associated_token_program),
132
+ program_index: context.index_of(program_id)
133
+ )
134
+ end
135
+ end
136
+ end
137
+ end