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.
- checksums.yaml +7 -0
- data/lib/solace/zar_trustless_escrow/codecs_extensions.rb +101 -0
- data/lib/solace/zar_trustless_escrow/composers/claim_composer.rb +136 -0
- data/lib/solace/zar_trustless_escrow/composers/deposit_composer.rb +145 -0
- data/lib/solace/zar_trustless_escrow/composers/mediated_deposit_composer.rb +173 -0
- data/lib/solace/zar_trustless_escrow/composers/mediated_reclaim_composer.rb +137 -0
- data/lib/solace/zar_trustless_escrow/composers/mediated_release_composer.rb +157 -0
- data/lib/solace/zar_trustless_escrow/composers/reclaim_composer.rb +135 -0
- data/lib/solace/zar_trustless_escrow/composers/token_account_init_composer.rb +88 -0
- data/lib/solace/zar_trustless_escrow/constants.rb +47 -0
- data/lib/solace/zar_trustless_escrow/errors/program_error.rb +30 -0
- data/lib/solace/zar_trustless_escrow/errors.rb +104 -0
- data/lib/solace/zar_trustless_escrow/instructions/claim_instruction.rb +60 -0
- data/lib/solace/zar_trustless_escrow/instructions/deposit_instruction.rb +65 -0
- data/lib/solace/zar_trustless_escrow/instructions/mediated_deposit_instruction.rb +74 -0
- data/lib/solace/zar_trustless_escrow/instructions/mediated_reclaim_instruction.rb +60 -0
- data/lib/solace/zar_trustless_escrow/instructions/mediated_release_instruction.rb +65 -0
- data/lib/solace/zar_trustless_escrow/instructions/reclaim_instruction.rb +60 -0
- data/lib/solace/zar_trustless_escrow/instructions/token_account_init_instruction.rb +48 -0
- data/lib/solace/zar_trustless_escrow/programs/zar_trustless_escrow/escrow_deposit_operations.rb +243 -0
- data/lib/solace/zar_trustless_escrow/programs/zar_trustless_escrow/mediated_escrow_deposit_operations.rb +259 -0
- data/lib/solace/zar_trustless_escrow/programs/zar_trustless_escrow.rb +148 -0
- data/lib/solace/zar_trustless_escrow/types/escrow_deposit.rb +44 -0
- data/lib/solace/zar_trustless_escrow/types/mediated_escrow_deposit.rb +50 -0
- data/lib/solace/zar_trustless_escrow/version.rb +7 -0
- data/lib/solace/zar_trustless_escrow.rb +38 -0
- metadata +171 -0
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Solace
|
|
4
|
+
module Composers
|
|
5
|
+
# Composes a `mediated_release` instruction for the ZAR Trustless Escrow
|
|
6
|
+
# program.
|
|
7
|
+
#
|
|
8
|
+
# The mediator releases a MediatedEscrowDeposit to the recipient (the depositor
|
|
9
|
+
# or the beneficiary) and closes the deposit, sending rent to the rent
|
|
10
|
+
# collector (which defaults to the mediator when none was set at deposit time).
|
|
11
|
+
#
|
|
12
|
+
# Required params:
|
|
13
|
+
# :mint [#to_s] Mint of the escrowed tokens.
|
|
14
|
+
# :mediator [#to_s, Keypair] Mediator (readonly signer).
|
|
15
|
+
# :recipient [#to_s] Depositor or beneficiary receiving tokens.
|
|
16
|
+
# :recipient_token_account [#to_s] Recipient's destination token account (ATA).
|
|
17
|
+
# :mediated_escrow_deposit [#to_s] MediatedEscrowDeposit PDA.
|
|
18
|
+
# :program_token_account [#to_s] Per-mint program vault PDA.
|
|
19
|
+
# :rent_collector [#to_s] Account that receives the closed-account rent.
|
|
20
|
+
# :fee_payer [#to_s, Keypair] Fee payer (writable signer).
|
|
21
|
+
# :id [#to_s] Unique id used to derive the escrow PDA.
|
|
22
|
+
#
|
|
23
|
+
# Optional params:
|
|
24
|
+
# :program_id [#to_s] Escrow program id (default: PROGRAM_ID, mainnet).
|
|
25
|
+
# :token_program_id [#to_s] Token program (default: legacy SPL Token).
|
|
26
|
+
class ZarTrustlessEscrowMediatedReleaseComposer < Base
|
|
27
|
+
# Extracts the mint address from the params
|
|
28
|
+
#
|
|
29
|
+
# @return [String] The mint address
|
|
30
|
+
def mint
|
|
31
|
+
params[:mint].to_s
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Extracts the mediator from the params
|
|
35
|
+
#
|
|
36
|
+
# @return [String] The mediator address
|
|
37
|
+
def mediator
|
|
38
|
+
params[:mediator].to_s
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Extracts the recipient from the params
|
|
42
|
+
#
|
|
43
|
+
# @return [String] The recipient address
|
|
44
|
+
def recipient
|
|
45
|
+
params[:recipient].to_s
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Extracts the recipient's destination token account from the params
|
|
49
|
+
#
|
|
50
|
+
# @return [String] The recipient token account address
|
|
51
|
+
def recipient_token_account
|
|
52
|
+
params[:recipient_token_account].to_s
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Extracts the MediatedEscrowDeposit PDA address from the params
|
|
56
|
+
#
|
|
57
|
+
# @return [String] The mediated escrow deposit address
|
|
58
|
+
def mediated_escrow_deposit
|
|
59
|
+
params[:mediated_escrow_deposit].to_s
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Extracts the per-mint program vault address from the params
|
|
63
|
+
#
|
|
64
|
+
# @return [String] The program token account address
|
|
65
|
+
def program_token_account
|
|
66
|
+
params[:program_token_account].to_s
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Extracts the rent collector from the params
|
|
70
|
+
#
|
|
71
|
+
# @return [String] The rent collector address
|
|
72
|
+
def rent_collector
|
|
73
|
+
params[:rent_collector].to_s
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Extracts the fee payer address from the params
|
|
77
|
+
#
|
|
78
|
+
# @return [String] The fee payer address
|
|
79
|
+
def fee_payer
|
|
80
|
+
params[:fee_payer].to_s
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Extracts the unique escrow id from the params
|
|
84
|
+
#
|
|
85
|
+
# @return [String] The escrow id
|
|
86
|
+
def id
|
|
87
|
+
params[:id].to_s
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# Returns the escrow program id (defaults to the mainnet PROGRAM_ID)
|
|
91
|
+
#
|
|
92
|
+
# @return [String] The escrow program id
|
|
93
|
+
def program_id
|
|
94
|
+
(params[:program_id] || Solace::ZarTrustlessEscrow::PROGRAM_ID).to_s
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# Returns the token program id (defaults to the legacy SPL Token program)
|
|
98
|
+
#
|
|
99
|
+
# @return [String] The token program id
|
|
100
|
+
def token_program_id
|
|
101
|
+
(params[:token_program_id] || Solace::Constants::TOKEN_PROGRAM_ID).to_s
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# Returns the System Program id
|
|
105
|
+
#
|
|
106
|
+
# @return [String] The System Program id
|
|
107
|
+
def system_program
|
|
108
|
+
Solace::Constants::SYSTEM_PROGRAM_ID
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# Returns the Associated Token Account Program id
|
|
112
|
+
#
|
|
113
|
+
# @return [String] The Associated Token Account Program id
|
|
114
|
+
def associated_token_program
|
|
115
|
+
Solace::Constants::ASSOCIATED_TOKEN_ACCOUNT_PROGRAM_ID
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# Declares all accounts required by this instruction.
|
|
119
|
+
def setup_accounts
|
|
120
|
+
account_context.add_readonly_nonsigner(mint)
|
|
121
|
+
account_context.add_readonly_signer(mediator)
|
|
122
|
+
account_context.add_readonly_nonsigner(recipient)
|
|
123
|
+
account_context.add_writable_nonsigner(recipient_token_account)
|
|
124
|
+
account_context.add_writable_nonsigner(mediated_escrow_deposit)
|
|
125
|
+
account_context.add_writable_nonsigner(program_token_account)
|
|
126
|
+
account_context.add_writable_nonsigner(rent_collector)
|
|
127
|
+
account_context.add_writable_signer(fee_payer)
|
|
128
|
+
account_context.add_readonly_nonsigner(system_program)
|
|
129
|
+
account_context.add_readonly_nonsigner(token_program_id)
|
|
130
|
+
account_context.add_readonly_nonsigner(associated_token_program)
|
|
131
|
+
account_context.add_readonly_nonsigner(program_id)
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# Builds the instruction with resolved account indices.
|
|
135
|
+
#
|
|
136
|
+
# @param context [Solace::Utils::AccountContext] Merged context from TransactionComposer.
|
|
137
|
+
# @return [Solace::Instruction]
|
|
138
|
+
def build_instruction(context)
|
|
139
|
+
Solace::ZarTrustlessEscrow::Instructions::MediatedReleaseInstruction.build(
|
|
140
|
+
id:,
|
|
141
|
+
mint_index: context.index_of(mint),
|
|
142
|
+
mediator_index: context.index_of(mediator),
|
|
143
|
+
recipient_index: context.index_of(recipient),
|
|
144
|
+
recipient_token_account_index: context.index_of(recipient_token_account),
|
|
145
|
+
mediated_escrow_deposit_index: context.index_of(mediated_escrow_deposit),
|
|
146
|
+
program_token_account_index: context.index_of(program_token_account),
|
|
147
|
+
rent_collector_index: context.index_of(rent_collector),
|
|
148
|
+
fee_payer_index: context.index_of(fee_payer),
|
|
149
|
+
system_program_index: context.index_of(system_program),
|
|
150
|
+
token_program_index: context.index_of(token_program_id),
|
|
151
|
+
associated_token_program_index: context.index_of(associated_token_program),
|
|
152
|
+
program_index: context.index_of(program_id)
|
|
153
|
+
)
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
end
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Solace
|
|
4
|
+
module Composers
|
|
5
|
+
# Composes a `re_claim` instruction for the ZAR Trustless Escrow program.
|
|
6
|
+
#
|
|
7
|
+
# The original depositor (or sponsor, as fee payer) reclaims an unclaimed
|
|
8
|
+
# EscrowDeposit and closes the deposit account.
|
|
9
|
+
#
|
|
10
|
+
# Required params:
|
|
11
|
+
# :mint [#to_s] Mint of the escrowed tokens.
|
|
12
|
+
# :depositor [#to_s] Original depositor (receives the tokens).
|
|
13
|
+
# :depositor_token_account [#to_s] Depositor's destination token account (ATA).
|
|
14
|
+
# :escrow_deposit [#to_s] EscrowDeposit PDA.
|
|
15
|
+
# :program_token_account [#to_s] Per-mint program vault PDA.
|
|
16
|
+
# :fee_payer [#to_s, Keypair] Fee payer (writable signer).
|
|
17
|
+
# :claim_authority [#to_s] Authority used to derive the escrow PDA.
|
|
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 ZarTrustlessEscrowReclaimComposer < 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 depositor address from the params
|
|
31
|
+
#
|
|
32
|
+
# @return [String] The depositor address
|
|
33
|
+
def depositor
|
|
34
|
+
params[:depositor].to_s
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Extracts the depositor's destination token account from the params
|
|
38
|
+
#
|
|
39
|
+
# @return [String] The depositor token account address
|
|
40
|
+
def depositor_token_account
|
|
41
|
+
params[:depositor_token_account].to_s
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Extracts the EscrowDeposit PDA address from the params
|
|
45
|
+
#
|
|
46
|
+
# @return [String] The escrow deposit address
|
|
47
|
+
def escrow_deposit
|
|
48
|
+
params[:escrow_deposit].to_s
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Extracts the per-mint program vault address from the params
|
|
52
|
+
#
|
|
53
|
+
# @return [String] The program token account address
|
|
54
|
+
def program_token_account
|
|
55
|
+
params[:program_token_account].to_s
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Extracts the fee payer address from the params
|
|
59
|
+
#
|
|
60
|
+
# @return [String] The fee payer address
|
|
61
|
+
def fee_payer
|
|
62
|
+
params[:fee_payer].to_s
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Extracts the claim authority from the params
|
|
66
|
+
#
|
|
67
|
+
# @return [String] The claim authority address
|
|
68
|
+
def claim_authority
|
|
69
|
+
params[:claim_authority].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_nonsigner(depositor)
|
|
104
|
+
account_context.add_writable_nonsigner(depositor_token_account)
|
|
105
|
+
account_context.add_writable_nonsigner(escrow_deposit)
|
|
106
|
+
account_context.add_writable_nonsigner(program_token_account)
|
|
107
|
+
account_context.add_writable_signer(fee_payer)
|
|
108
|
+
account_context.add_readonly_nonsigner(system_program)
|
|
109
|
+
account_context.add_readonly_nonsigner(token_program_id)
|
|
110
|
+
account_context.add_readonly_nonsigner(associated_token_program)
|
|
111
|
+
account_context.add_readonly_nonsigner(program_id)
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# Builds the instruction with resolved account indices.
|
|
115
|
+
#
|
|
116
|
+
# @param context [Solace::Utils::AccountContext] Merged context from TransactionComposer.
|
|
117
|
+
# @return [Solace::Instruction]
|
|
118
|
+
def build_instruction(context)
|
|
119
|
+
Solace::ZarTrustlessEscrow::Instructions::ReclaimInstruction.build(
|
|
120
|
+
claim_authority:,
|
|
121
|
+
mint_index: context.index_of(mint),
|
|
122
|
+
depositor_index: context.index_of(depositor),
|
|
123
|
+
depositor_token_account_index: context.index_of(depositor_token_account),
|
|
124
|
+
escrow_deposit_index: context.index_of(escrow_deposit),
|
|
125
|
+
program_token_account_index: context.index_of(program_token_account),
|
|
126
|
+
fee_payer_index: context.index_of(fee_payer),
|
|
127
|
+
system_program_index: context.index_of(system_program),
|
|
128
|
+
token_program_index: context.index_of(token_program_id),
|
|
129
|
+
associated_token_program_index: context.index_of(associated_token_program),
|
|
130
|
+
program_index: context.index_of(program_id)
|
|
131
|
+
)
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Solace
|
|
4
|
+
module Composers
|
|
5
|
+
# Composes a `token_account_init` instruction for the ZAR Trustless Escrow
|
|
6
|
+
# program.
|
|
7
|
+
#
|
|
8
|
+
# Initializes the per-mint program vault token account if it does not already
|
|
9
|
+
# exist. A single vault is shared across all deposits for a given mint.
|
|
10
|
+
#
|
|
11
|
+
# Required params:
|
|
12
|
+
# :mint [#to_s] Mint the vault holds.
|
|
13
|
+
# :program_token_account [#to_s] Per-mint program vault PDA.
|
|
14
|
+
# :fee_payer [#to_s, Keypair] Fee payer (writable signer).
|
|
15
|
+
#
|
|
16
|
+
# Optional params:
|
|
17
|
+
# :program_id [#to_s] Escrow program id (default: PROGRAM_ID, mainnet).
|
|
18
|
+
# :token_program_id [#to_s] Token program (default: legacy SPL Token).
|
|
19
|
+
class ZarTrustlessEscrowTokenAccountInitComposer < Base
|
|
20
|
+
# Extracts the mint address from the params
|
|
21
|
+
#
|
|
22
|
+
# @return [String] The mint address
|
|
23
|
+
def mint
|
|
24
|
+
params[:mint].to_s
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Extracts the per-mint program vault address from the params
|
|
28
|
+
#
|
|
29
|
+
# @return [String] The program token account address
|
|
30
|
+
def program_token_account
|
|
31
|
+
params[:program_token_account].to_s
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Extracts the fee payer address from the params
|
|
35
|
+
#
|
|
36
|
+
# @return [String] The fee payer address
|
|
37
|
+
def fee_payer
|
|
38
|
+
params[:fee_payer].to_s
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Returns the escrow program id (defaults to the mainnet PROGRAM_ID)
|
|
42
|
+
#
|
|
43
|
+
# @return [String] The escrow program id
|
|
44
|
+
def program_id
|
|
45
|
+
(params[:program_id] || Solace::ZarTrustlessEscrow::PROGRAM_ID).to_s
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Returns the token program id (defaults to the legacy SPL Token program)
|
|
49
|
+
#
|
|
50
|
+
# @return [String] The token program id
|
|
51
|
+
def token_program_id
|
|
52
|
+
(params[:token_program_id] || Solace::Constants::TOKEN_PROGRAM_ID).to_s
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Returns the System Program id
|
|
56
|
+
#
|
|
57
|
+
# @return [String] The System Program id
|
|
58
|
+
def system_program
|
|
59
|
+
Solace::Constants::SYSTEM_PROGRAM_ID
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Declares all accounts required by this instruction.
|
|
63
|
+
def setup_accounts
|
|
64
|
+
account_context.add_writable_nonsigner(mint)
|
|
65
|
+
account_context.add_writable_nonsigner(program_token_account)
|
|
66
|
+
account_context.add_writable_signer(fee_payer)
|
|
67
|
+
account_context.add_readonly_nonsigner(system_program)
|
|
68
|
+
account_context.add_readonly_nonsigner(token_program_id)
|
|
69
|
+
account_context.add_readonly_nonsigner(program_id)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Builds the instruction with resolved account indices.
|
|
73
|
+
#
|
|
74
|
+
# @param context [Solace::Utils::AccountContext] Merged context from TransactionComposer.
|
|
75
|
+
# @return [Solace::Instruction]
|
|
76
|
+
def build_instruction(context)
|
|
77
|
+
Solace::ZarTrustlessEscrow::Instructions::TokenAccountInitInstruction.build(
|
|
78
|
+
mint_index: context.index_of(mint),
|
|
79
|
+
program_token_account_index: context.index_of(program_token_account),
|
|
80
|
+
fee_payer_index: context.index_of(fee_payer),
|
|
81
|
+
system_program_index: context.index_of(system_program),
|
|
82
|
+
token_program_index: context.index_of(token_program_id),
|
|
83
|
+
program_index: context.index_of(program_id)
|
|
84
|
+
)
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Solace
|
|
4
|
+
# Program IDs, PDA seeds, and cluster helpers for the ZAR Trustless Escrow
|
|
5
|
+
# program. The values mirror the [programs.*] entries in Anchor.toml and the
|
|
6
|
+
# constants exported by the TypeScript SDK.
|
|
7
|
+
module ZarTrustlessEscrow
|
|
8
|
+
# Per-cluster on-chain program IDs for the ZAR Trustless Escrow program.
|
|
9
|
+
# These mirror the [programs.*] entries in Anchor.toml and the PROGRAM_ID
|
|
10
|
+
# constants exported by the TypeScript SDK.
|
|
11
|
+
MAINNET_PROGRAM_ID = 'ZARxRie8kHmJ3V3GSRFS6CUDjCMm5pEoZyhEddq6FSu'
|
|
12
|
+
DEVNET_PROGRAM_ID = 'ZARTiAgmDYUcqbx35KF4cfJYudyQAeM4iagCXs5AR9V'
|
|
13
|
+
TESTNET_PROGRAM_ID = 'ZARJV7Y9nLeJYPFdcd9xdXBxGWN84jDR1TdiiyZhKSo'
|
|
14
|
+
LOCALNET_PROGRAM_ID = 'HKzzmBQk3uat5Vak8RyPyDe3f6Fi9boR1vDV6qMrSXmH'
|
|
15
|
+
|
|
16
|
+
# Default program ID used when a cluster is not specified. Defaults to mainnet.
|
|
17
|
+
PROGRAM_ID = MAINNET_PROGRAM_ID
|
|
18
|
+
|
|
19
|
+
# PDA seed prefix for an EscrowDeposit account, derived from
|
|
20
|
+
# ["escrow_deposit", claim_authority].
|
|
21
|
+
ESCROW_DEPOSIT_SEED = 'escrow_deposit'
|
|
22
|
+
|
|
23
|
+
# PDA seed prefix for a MediatedEscrowDeposit account, derived from
|
|
24
|
+
# ["mediated_escrow_deposit", id].
|
|
25
|
+
MEDIATED_ESCROW_DEPOSIT_SEED = 'mediated_escrow_deposit'
|
|
26
|
+
|
|
27
|
+
# PDA seed prefix for the per-mint program vault token account, derived from
|
|
28
|
+
# ["vault", mint]. A single vault is shared across all deposits for a mint.
|
|
29
|
+
VAULT_SEED = 'vault'
|
|
30
|
+
|
|
31
|
+
# Maps a cluster symbol/string to its program ID.
|
|
32
|
+
#
|
|
33
|
+
# @param cluster [Symbol, String] One of :mainnet, :devnet, :testnet, :localnet.
|
|
34
|
+
# @return [String] The base58 program ID for the cluster.
|
|
35
|
+
# @raise [ArgumentError] If the cluster is unknown.
|
|
36
|
+
def self.program_id_for(cluster)
|
|
37
|
+
case cluster.to_sym
|
|
38
|
+
when :mainnet then MAINNET_PROGRAM_ID
|
|
39
|
+
when :devnet then DEVNET_PROGRAM_ID
|
|
40
|
+
when :testnet then TESTNET_PROGRAM_ID
|
|
41
|
+
when :localnet then LOCALNET_PROGRAM_ID
|
|
42
|
+
else
|
|
43
|
+
raise ArgumentError, "Unknown cluster: #{cluster.inspect} (use :mainnet, :devnet, :testnet, :localnet)"
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Solace
|
|
4
|
+
module ZarTrustlessEscrow
|
|
5
|
+
module Errors
|
|
6
|
+
# A resolved on-chain TrustlessEscrowError, carrying its custom error code,
|
|
7
|
+
# variant name, and message. Returned by {Errors.from_code} and
|
|
8
|
+
# {Errors.from_name} so callers can translate a failed transaction's custom
|
|
9
|
+
# error code into a meaningful, rescuable Ruby error.
|
|
10
|
+
class ProgramError < Solace::ZarTrustlessEscrow::Error
|
|
11
|
+
# @!attribute [r] code
|
|
12
|
+
# @return [Integer] The on-chain custom error code (6000-based).
|
|
13
|
+
attr_reader :code
|
|
14
|
+
|
|
15
|
+
# @!attribute [r] error_name
|
|
16
|
+
# @return [String] The TrustlessEscrowError variant name.
|
|
17
|
+
attr_reader :error_name
|
|
18
|
+
|
|
19
|
+
# @param code [Integer] The on-chain custom error code.
|
|
20
|
+
# @param error_name [String] The TrustlessEscrowError variant name.
|
|
21
|
+
# @param message [String] The variant's on-chain #[msg] text.
|
|
22
|
+
def initialize(code:, error_name:, message:)
|
|
23
|
+
@code = code
|
|
24
|
+
@error_name = error_name
|
|
25
|
+
super(message)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'errors/program_error'
|
|
4
|
+
|
|
5
|
+
module Solace
|
|
6
|
+
module ZarTrustlessEscrow
|
|
7
|
+
# Lookup for the on-chain TrustlessEscrowError codes, translating a custom
|
|
8
|
+
# program error code (e.g. from a failed transaction) into a {ProgramError}.
|
|
9
|
+
#
|
|
10
|
+
# The mapping is ported from the program's source of truth,
|
|
11
|
+
# programs/trustless_escrow/src/errors.rs — NOT the TypeScript SDK's errors
|
|
12
|
+
# file, which is stale (it omits DepositAmountInvalid, shifting every later
|
|
13
|
+
# code, and is missing all mediated-escrow errors). Anchor assigns each variant
|
|
14
|
+
# a code of {FIRST_ERROR_CODE} + its declaration index.
|
|
15
|
+
#
|
|
16
|
+
# @example
|
|
17
|
+
# Solace::ZarTrustlessEscrow::Errors.from_code(6019)
|
|
18
|
+
# # => #<ProgramError code=6019 error_name="MediatedExpiryMustBeInFuture" ...>
|
|
19
|
+
module Errors
|
|
20
|
+
extend self
|
|
21
|
+
|
|
22
|
+
# First on-chain custom error code (Anchor's default offset); maps to the
|
|
23
|
+
# first TrustlessEscrowError variant.
|
|
24
|
+
FIRST_ERROR_CODE = 6000
|
|
25
|
+
|
|
26
|
+
# TrustlessEscrowError variants in declaration order — index N is code
|
|
27
|
+
# FIRST_ERROR_CODE + N. Each entry is [variant name, on-chain #[msg] text].
|
|
28
|
+
DEFINITIONS = [
|
|
29
|
+
['MintInvalid',
|
|
30
|
+
"MintInvalid: The mint provided does not match the escrow deposit's mint."],
|
|
31
|
+
['DepositorInvalid',
|
|
32
|
+
'Depositor invalid'],
|
|
33
|
+
['DepositAmountInvalid',
|
|
34
|
+
'DepositAmountInvalid: The deposit amount must be greater than 0.'],
|
|
35
|
+
['SubsidyMismatch',
|
|
36
|
+
'Subsidy mismatch'],
|
|
37
|
+
['InvalidAuthority',
|
|
38
|
+
'Either fee payer should be sponsor or depositor should be signer'],
|
|
39
|
+
['InvalidCloseAuthority',
|
|
40
|
+
'InvalidCloseAuthority: When a sponsor is present, the fee payer must be the sponsor.'],
|
|
41
|
+
['ClaimAuthorityMustBeASigner',
|
|
42
|
+
'ClaimAuthorityMustBeASigner: The claim authority must be a signer.'],
|
|
43
|
+
['ClaimAuthorityIsInvalid',
|
|
44
|
+
"ClaimAuthorityIsInvalid: The claim authority provided does not match the escrow deposit's claim authority."],
|
|
45
|
+
['DepositorCannotBeClaimant',
|
|
46
|
+
'DepositorCannotBeClaimant: The depositor cannot be the claimant (use reclaim instruction instead).'],
|
|
47
|
+
['ReclaimerMustBeDepositor',
|
|
48
|
+
'ReclaimerMustBeDepositor: The reclaimer must be the depositor.'],
|
|
49
|
+
['InvalidReclaimSigner',
|
|
50
|
+
'InvalidReclaimSigner: The reclaimer signer must be the depositor or the sponsor.'],
|
|
51
|
+
['MediatorCannotBeDepositorOrBeneficiary',
|
|
52
|
+
'MediatorCannotBeDepositorOrBeneficiary: The mediator cannot be the depositor or the beneficiary.'],
|
|
53
|
+
['InvalidMediator',
|
|
54
|
+
'InvalidMediator: The signer is not the mediator of the mediated escrow deposit.'],
|
|
55
|
+
['MediatedDepositorCannotBeBeneficiary',
|
|
56
|
+
'MediatedDepositorCannotBeBeneficiary: The depositor and beneficiary cannot be the same account.'],
|
|
57
|
+
['InvalidReleaseRecipient',
|
|
58
|
+
'InvalidReleaseRecipient: The recipient must be either the depositor or the beneficiary.'],
|
|
59
|
+
['MediatedReclaimNotExpirable',
|
|
60
|
+
'MediatedReclaimNotExpirable: No expiry is set, so only the mediator can distribute the funds.'],
|
|
61
|
+
['MediatedReclaimNotYetExpired',
|
|
62
|
+
'MediatedReclaimNotYetExpired: The mediated escrow deposit cannot be reclaimed before its expiry timestamp.'],
|
|
63
|
+
['MediatedReclaimerMustBeDepositor',
|
|
64
|
+
'MediatedReclaimerMustBeDepositor: Only the depositor can reclaim the deposit after the expiry date.'],
|
|
65
|
+
['InvalidRentCollector',
|
|
66
|
+
'InvalidRentCollector: The rent collector provided does not match the mediated escrow ' \
|
|
67
|
+
"deposit's rent collector."],
|
|
68
|
+
['MediatedExpiryMustBeInFuture',
|
|
69
|
+
'MediatedExpiryMustBeInFuture: The expiry timestamp, when provided, must be in the future.']
|
|
70
|
+
].freeze
|
|
71
|
+
|
|
72
|
+
# code => [name, message], derived by offsetting each declaration index with
|
|
73
|
+
# FIRST_ERROR_CODE.
|
|
74
|
+
BY_CODE = DEFINITIONS.each_with_index.to_h do |(name, message), index|
|
|
75
|
+
[FIRST_ERROR_CODE + index, [name, message]]
|
|
76
|
+
end.freeze
|
|
77
|
+
|
|
78
|
+
# name => code, for resolving an error by its variant name.
|
|
79
|
+
CODE_BY_NAME = BY_CODE.to_h { |code, (name, _message)| [name, code] }.freeze
|
|
80
|
+
|
|
81
|
+
# Resolves a {ProgramError} from an on-chain custom error code.
|
|
82
|
+
#
|
|
83
|
+
# @param code [Integer] The custom program error code (e.g. 6019).
|
|
84
|
+
# @return [ProgramError, nil] The typed error, or nil if the code is unknown.
|
|
85
|
+
def from_code(code)
|
|
86
|
+
name, message = BY_CODE[code]
|
|
87
|
+
return nil unless name
|
|
88
|
+
|
|
89
|
+
ProgramError.new(code:, error_name: name, message:)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Resolves a {ProgramError} from a TrustlessEscrowError variant name.
|
|
93
|
+
#
|
|
94
|
+
# @param name [String] The variant name (e.g. "InvalidMediator").
|
|
95
|
+
# @return [ProgramError, nil] The typed error, or nil if the name is unknown.
|
|
96
|
+
def from_name(name)
|
|
97
|
+
code = CODE_BY_NAME[name]
|
|
98
|
+
return nil unless code
|
|
99
|
+
|
|
100
|
+
from_code(code)
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Solace
|
|
4
|
+
module ZarTrustlessEscrow
|
|
5
|
+
module Instructions
|
|
6
|
+
# Encoder for the `claim` instruction: the claim authority releases an
|
|
7
|
+
# EscrowDeposit to the claimant and closes the deposit account.
|
|
8
|
+
class ClaimInstruction
|
|
9
|
+
# 8-byte Anchor discriminator: SHA256("global:claim")[0..7].
|
|
10
|
+
DISCRIMINATOR = [62, 198, 214, 193, 213, 159, 108, 210].freeze
|
|
11
|
+
|
|
12
|
+
# Builds a Solace::Instruction for `claim`.
|
|
13
|
+
#
|
|
14
|
+
# Account indices are in the on-chain order:
|
|
15
|
+
# mint, claim_authority, claimant, claimant_token_account,
|
|
16
|
+
# escrow_deposit, program_token_account, fee_payer, system_program,
|
|
17
|
+
# token_program, associated_token_program.
|
|
18
|
+
#
|
|
19
|
+
# @return [Solace::Instruction]
|
|
20
|
+
def self.build(
|
|
21
|
+
mint_index:,
|
|
22
|
+
claim_authority_index:,
|
|
23
|
+
claimant_index:,
|
|
24
|
+
claimant_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
|
+
claim_authority_index,
|
|
38
|
+
claimant_index,
|
|
39
|
+
claimant_token_account_index,
|
|
40
|
+
escrow_deposit_index,
|
|
41
|
+
program_token_account_index,
|
|
42
|
+
fee_payer_index,
|
|
43
|
+
system_program_index,
|
|
44
|
+
token_program_index,
|
|
45
|
+
associated_token_program_index
|
|
46
|
+
]
|
|
47
|
+
ix.data = data
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Encodes the `claim` instruction data (discriminator only — no args).
|
|
52
|
+
#
|
|
53
|
+
# @return [Array<Integer>]
|
|
54
|
+
def self.data
|
|
55
|
+
DISCRIMINATOR.dup
|
|
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 `deposit` instruction: locks `amount` tokens from the
|
|
7
|
+
# depositor into a per-claim-authority EscrowDeposit PDA and the per-mint
|
|
8
|
+
# program vault.
|
|
9
|
+
class DepositInstruction
|
|
10
|
+
# 8-byte Anchor discriminator: SHA256("global:deposit")[0..7].
|
|
11
|
+
DISCRIMINATOR = [242, 35, 198, 137, 82, 225, 242, 182].freeze
|
|
12
|
+
|
|
13
|
+
# Builds a Solace::Instruction for `deposit`.
|
|
14
|
+
#
|
|
15
|
+
# Account indices are in the on-chain order:
|
|
16
|
+
# mint, depositor, depositor_token_account, escrow_deposit,
|
|
17
|
+
# program_token_account, fee_payer, system_program, token_program.
|
|
18
|
+
#
|
|
19
|
+
# @return [Solace::Instruction]
|
|
20
|
+
def self.build(
|
|
21
|
+
amount:,
|
|
22
|
+
claim_authority:,
|
|
23
|
+
sponsor:,
|
|
24
|
+
mint_index:,
|
|
25
|
+
depositor_index:,
|
|
26
|
+
depositor_token_account_index:,
|
|
27
|
+
escrow_deposit_index:,
|
|
28
|
+
program_token_account_index:,
|
|
29
|
+
fee_payer_index:,
|
|
30
|
+
system_program_index:,
|
|
31
|
+
token_program_index:,
|
|
32
|
+
program_index:
|
|
33
|
+
)
|
|
34
|
+
Solace::Instruction.new.tap do |ix|
|
|
35
|
+
ix.program_index = program_index
|
|
36
|
+
ix.accounts = [
|
|
37
|
+
mint_index,
|
|
38
|
+
depositor_index,
|
|
39
|
+
depositor_token_account_index,
|
|
40
|
+
escrow_deposit_index,
|
|
41
|
+
program_token_account_index,
|
|
42
|
+
fee_payer_index,
|
|
43
|
+
system_program_index,
|
|
44
|
+
token_program_index
|
|
45
|
+
]
|
|
46
|
+
ix.data = data(amount:, claim_authority:, sponsor:)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Encodes the DepositCreateArgs struct in Borsh format.
|
|
51
|
+
#
|
|
52
|
+
# @param amount [Integer] u64 amount to deposit.
|
|
53
|
+
# @param claim_authority [#to_s] base58 authority that can claim the deposit.
|
|
54
|
+
# @param sponsor [#to_s, nil] optional base58 fee sponsor.
|
|
55
|
+
# @return [Array<Integer>]
|
|
56
|
+
def self.data(amount:, claim_authority:, sponsor:)
|
|
57
|
+
DISCRIMINATOR +
|
|
58
|
+
Solace::Utils::Codecs.encode_le_u64(amount).bytes +
|
|
59
|
+
Solace::Utils::Codecs.encode_pubkey(claim_authority) +
|
|
60
|
+
Solace::Utils::Codecs.encode_option_pubkey(sponsor)
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|