@cloak.dev/sdk 0.2.0 → 0.2.1
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.
- package/LICENSE +202 -0
- package/README.md +189 -51
- package/dist/{chunk-YX5SCAMR.js → chunk-KNM6K5NG.js} +8 -95
- package/dist/index.cjs +3143 -4276
- package/dist/index.d.cts +571 -805
- package/dist/index.d.ts +571 -805
- package/dist/index.js +3065 -4136
- package/dist/{utxo-PFJT3ETR.js → utxo-XPEGGWZ6.js} +3 -3
- package/package.json +50 -20
package/LICENSE
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
|
|
2
|
+
Apache License
|
|
3
|
+
Version 2.0, January 2004
|
|
4
|
+
http://www.apache.org/licenses/
|
|
5
|
+
|
|
6
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
7
|
+
|
|
8
|
+
1. Definitions.
|
|
9
|
+
|
|
10
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
11
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
12
|
+
|
|
13
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
14
|
+
the copyright owner that is granting the License.
|
|
15
|
+
|
|
16
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
17
|
+
other entities that control, are controlled by, or are under common
|
|
18
|
+
control with that entity. For the purposes of this definition,
|
|
19
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
20
|
+
direction or management of such entity, whether by contract or
|
|
21
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
22
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
23
|
+
|
|
24
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
25
|
+
exercising permissions granted by this License.
|
|
26
|
+
|
|
27
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
28
|
+
including but not limited to software source code, documentation
|
|
29
|
+
source, and configuration files.
|
|
30
|
+
|
|
31
|
+
"Object" form shall mean any form resulting from mechanical
|
|
32
|
+
transformation or translation of a Source form, including but
|
|
33
|
+
not limited to compiled object code, generated documentation,
|
|
34
|
+
and conversions to other media types.
|
|
35
|
+
|
|
36
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
37
|
+
Object form, made available under the License, as indicated by a
|
|
38
|
+
copyright notice that is included in or attached to the work
|
|
39
|
+
(an example is provided in the Appendix below).
|
|
40
|
+
|
|
41
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
42
|
+
form, that is based on (or derived from) the Work and for which the
|
|
43
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
44
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
45
|
+
of this License, Derivative Works shall not include works that remain
|
|
46
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
47
|
+
the Work and Derivative Works thereof.
|
|
48
|
+
|
|
49
|
+
"Contribution" shall mean any work of authorship, including
|
|
50
|
+
the original version of the Work and any modifications or additions
|
|
51
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
52
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
53
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
54
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
|
55
|
+
means any form of electronic, verbal, or written communication sent
|
|
56
|
+
to the Licensor or its representatives, including but not limited to
|
|
57
|
+
communication on electronic mailing lists, source code control systems,
|
|
58
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
59
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
60
|
+
excluding communication that is conspicuously marked or otherwise
|
|
61
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
62
|
+
|
|
63
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
64
|
+
on behalf of whom a Contribution has been received by Licensor and
|
|
65
|
+
subsequently incorporated within the Work.
|
|
66
|
+
|
|
67
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
68
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
69
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
70
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
71
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
72
|
+
Work and such Derivative Works in Source or Object form.
|
|
73
|
+
|
|
74
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
75
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
76
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
77
|
+
(except as stated in this section) patent license to make, have made,
|
|
78
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
79
|
+
where such license applies only to those patent claims licensable
|
|
80
|
+
by such Contributor that are necessarily infringed by their
|
|
81
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
82
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
83
|
+
institute patent litigation against any entity (including a
|
|
84
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
85
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
86
|
+
or contributory patent infringement, then any patent licenses
|
|
87
|
+
granted to You under this License for that Work shall terminate
|
|
88
|
+
as of the date such litigation is filed.
|
|
89
|
+
|
|
90
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
91
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
92
|
+
modifications, and in Source or Object form, provided that You
|
|
93
|
+
meet the following conditions:
|
|
94
|
+
|
|
95
|
+
(a) You must give any other recipients of the Work or
|
|
96
|
+
Derivative Works a copy of this License; and
|
|
97
|
+
|
|
98
|
+
(b) You must cause any modified files to carry prominent notices
|
|
99
|
+
stating that You changed the files; and
|
|
100
|
+
|
|
101
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
102
|
+
that You distribute, all copyright, patent, trademark, and
|
|
103
|
+
attribution notices from the Source form of the Work,
|
|
104
|
+
excluding those notices that do not pertain to any part of
|
|
105
|
+
the Derivative Works; and
|
|
106
|
+
|
|
107
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
108
|
+
distribution, then any Derivative Works that You distribute must
|
|
109
|
+
include a readable copy of the attribution notices contained
|
|
110
|
+
within such NOTICE file, excluding those notices that do not
|
|
111
|
+
pertain to any part of the Derivative Works, in at least one
|
|
112
|
+
of the following places: within a NOTICE text file distributed
|
|
113
|
+
as part of the Derivative Works; within the Source form or
|
|
114
|
+
documentation, if provided along with the Derivative Works; or,
|
|
115
|
+
within a display generated by the Derivative Works, if and
|
|
116
|
+
wherever such third-party notices normally appear. The contents
|
|
117
|
+
of the NOTICE file are for informational purposes only and
|
|
118
|
+
do not modify the License. You may add Your own attribution
|
|
119
|
+
notices within Derivative Works that You distribute, alongside
|
|
120
|
+
or as an addendum to the NOTICE text from the Work, provided
|
|
121
|
+
that such additional attribution notices cannot be construed
|
|
122
|
+
as modifying the License.
|
|
123
|
+
|
|
124
|
+
You may add Your own copyright statement to Your modifications and
|
|
125
|
+
may provide additional or different license terms and conditions
|
|
126
|
+
for use, reproduction, or distribution of Your modifications, or
|
|
127
|
+
for any such Derivative Works as a whole, provided Your use,
|
|
128
|
+
reproduction, and distribution of the Work otherwise complies with
|
|
129
|
+
the conditions stated in this License.
|
|
130
|
+
|
|
131
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
132
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
133
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
134
|
+
this License, without any additional terms or conditions.
|
|
135
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
136
|
+
the terms of any separate license agreement you may have executed
|
|
137
|
+
with Licensor regarding such Contributions.
|
|
138
|
+
|
|
139
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
140
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
141
|
+
except as required for reasonable and customary use in describing the
|
|
142
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
143
|
+
|
|
144
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
145
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
146
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
147
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
148
|
+
implied, including, without limitation, any warranties or conditions
|
|
149
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
150
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
151
|
+
appropriateness of using or redistributing the Work and assume any
|
|
152
|
+
risks associated with Your exercise of permissions under this License.
|
|
153
|
+
|
|
154
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
155
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
156
|
+
unless required by applicable law (such as deliberate and grossly
|
|
157
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
158
|
+
liable to You for damages, including any direct, indirect, special,
|
|
159
|
+
incidental, or consequential damages of any character arising as a
|
|
160
|
+
result of this License or out of the use or inability to use the
|
|
161
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
162
|
+
work stoppage, computer failure or malfunction, or any and all
|
|
163
|
+
other commercial damages or losses), even if such Contributor
|
|
164
|
+
has been advised of the possibility of such damages.
|
|
165
|
+
|
|
166
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
167
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
168
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
169
|
+
or other liability obligations and/or rights consistent with this
|
|
170
|
+
License. However, in accepting such obligations, You may act only
|
|
171
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
|
172
|
+
of any other Contributor, and only if You agree to indemnify,
|
|
173
|
+
defend, and hold each Contributor harmless for any liability
|
|
174
|
+
incurred by, or claims asserted against, such Contributor by reason
|
|
175
|
+
of your accepting any such warranty or additional liability.
|
|
176
|
+
|
|
177
|
+
END OF TERMS AND CONDITIONS
|
|
178
|
+
|
|
179
|
+
APPENDIX: How to apply the Apache License to your work.
|
|
180
|
+
|
|
181
|
+
To apply the Apache License to your work, attach the following
|
|
182
|
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
183
|
+
replaced with your own identifying information. (Don't include
|
|
184
|
+
the brackets!) The text should be enclosed in the appropriate
|
|
185
|
+
comment syntax for the file format. We also recommend that a
|
|
186
|
+
file or class name and description of purpose be included on the
|
|
187
|
+
same "printed page" as the copyright notice for easier
|
|
188
|
+
identification within third-party archives.
|
|
189
|
+
|
|
190
|
+
Copyright [yyyy] [name of copyright owner]
|
|
191
|
+
|
|
192
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
193
|
+
you may not use this file except in compliance with the License.
|
|
194
|
+
You may obtain a copy of the License at
|
|
195
|
+
|
|
196
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
197
|
+
|
|
198
|
+
Unless required by applicable law or agreed to in writing, software
|
|
199
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
200
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
201
|
+
See the License for the specific language governing permissions and
|
|
202
|
+
limitations under the License.
|
package/README.md
CHANGED
|
@@ -11,7 +11,7 @@ Version 0.2.0 targets the mainnet program deployed on 2026-08-24 and the ceremon
|
|
|
11
11
|
## Installation
|
|
12
12
|
|
|
13
13
|
```bash
|
|
14
|
-
npm install @cloak.dev/sdk @solana/web3.js
|
|
14
|
+
npm install @cloak.dev/sdk@^0.2.0 @solana/web3.js
|
|
15
15
|
# swaps and SPL pools also need:
|
|
16
16
|
npm install @solana/spl-token
|
|
17
17
|
```
|
|
@@ -26,25 +26,44 @@ Node >= 18. Ships ESM and CJS builds with type declarations. Runs in Node and in
|
|
|
26
26
|
| Setting | Value |
|
|
27
27
|
| --- | --- |
|
|
28
28
|
| Program | `zh1eLd6rSphLejbFfJEneUwzHRfMKxgzrgkfwA6qRkW` (`CLOAK_PROGRAM_ID`) |
|
|
29
|
-
|
|
|
29
|
+
| Cloak endpoint | `https://api.cloak.ag` — pinned into the build, not configurable (see below) |
|
|
30
30
|
| Circuits | `https://storage.googleapis.com/cloak-circuits/circuits/0.2.0` (the SDK default) |
|
|
31
31
|
| Pools | WSOL (`NATIVE_SOL_MINT`), USDC `EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v`, USDT `Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB` |
|
|
32
32
|
| RPC | any mainnet RPC; use `new Connection(url, "confirmed")` |
|
|
33
33
|
|
|
34
|
-
The
|
|
35
|
-
`
|
|
36
|
-
|
|
37
|
-
|
|
34
|
+
The endpoint is fixed when the SDK is built and cannot be changed by a consumer. A published build
|
|
35
|
+
carries `RELAY_ORIGIN_ALLOWLIST` as a compiled-in constant, every request is checked against it
|
|
36
|
+
before it leaves the process, and there is no option, environment variable, or bundler define that
|
|
37
|
+
moves it. Name it by importing the constant rather than typing a host:
|
|
38
38
|
|
|
39
39
|
```ts
|
|
40
|
-
|
|
40
|
+
import { CLOAK_PRODUCTION_RELAY_URL } from "@cloak.dev/sdk";
|
|
41
|
+
|
|
42
|
+
relayUrl: CLOAK_PRODUCTION_RELAY_URL
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
It is still never defaulted: omitting the option throws before anything is signed or sent, so a
|
|
46
|
+
script that forgets it cannot ship its proof anywhere. `relayUrl: ""` means the opposite — no
|
|
47
|
+
endpoint at all, so a deposit is signed and submitted by the caller.
|
|
48
|
+
|
|
49
|
+
A build pinned somewhere else is made by editing source and rebuilding, which is also what makes a
|
|
50
|
+
published build unrepointable:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
# in a checkout of this repo
|
|
54
|
+
$ $EDITOR src/config/relay.ts # replace the RELAY_ORIGIN_ALLOWLIST entry, do not append
|
|
55
|
+
$ npm run build # only needed by consumers that import dist/
|
|
41
56
|
```
|
|
42
57
|
|
|
58
|
+
The same edit unlocks the second half of the lock: a build pinned to a non-local origin refuses to
|
|
59
|
+
run against an RPC served by the local machine, and a build pinned to a local origin does not. One
|
|
60
|
+
constant, both behaviours.
|
|
61
|
+
|
|
43
62
|
Every flow needs it, deposits included: the SDK registers the wallet's viewing key through the relay
|
|
44
63
|
before its first transaction (see [Recovery and discovery](#recovery-and-discovery-viewing-key)),
|
|
45
64
|
deposits fetch the signed risk quote the program requires from `<relayUrl>/range-quote`, and sends,
|
|
46
65
|
withdrawals and swaps are submitted through it. `enforceViewingKeyRegistration: false` skips only the
|
|
47
|
-
registration step (the shipped examples set it on a local fork); it is not a no-relay mode.
|
|
66
|
+
registration step (some of the shipped examples set it on a local fork); it is not a no-relay mode.
|
|
48
67
|
|
|
49
68
|
Do not expose `programId`, the relay URL or the circuits base as end-user input. Wallet adapters are
|
|
50
69
|
the in-app signer; keypair files belong to scripts only.
|
|
@@ -55,10 +74,14 @@ The same SDK runs against a devnet or local deployment by pointing the three coo
|
|
|
55
74
|
|
|
56
75
|
```bash
|
|
57
76
|
SOLANA_RPC_URL=https://api.devnet.solana.com # or http://127.0.0.1:8899 for a local fork
|
|
58
|
-
CLOAK_RELAY_URL=<
|
|
77
|
+
CLOAK_RELAY_URL=<endpoint serving that deployment> # read by examples/ and scripts/, NOT by the SDK
|
|
59
78
|
CLOAK_PROGRAM_ID=<program id of that deployment> # examples read this; pass it as programId in your code
|
|
60
79
|
```
|
|
61
80
|
|
|
81
|
+
`CLOAK_RELAY_URL` configures the shipped examples and scripts, which pass its value as `relayUrl`.
|
|
82
|
+
The SDK itself does not read it: the endpoint a build may talk to comes from `src/config/relay.ts`,
|
|
83
|
+
so pointing at a devnet or local deployment means editing that file in a checkout and building it.
|
|
84
|
+
|
|
62
85
|
The shipped examples default to a local fork (`http://127.0.0.1:8899`) with a local relay
|
|
63
86
|
(`http://127.0.0.1:5500`); see [Examples](#examples).
|
|
64
87
|
|
|
@@ -188,11 +211,104 @@ address lookup tables); deposits use either depending on the path taken. `signMe
|
|
|
188
211
|
unless `enforceViewingKeyRegistration: false` is set; without it the call fails with
|
|
189
212
|
"Viewing key registration is mandatory: signMessage (wallet) or depositorKeypair is required."
|
|
190
213
|
|
|
214
|
+
A deposit is signed by the wallet and goes straight to chain. A private send, a withdrawal and a
|
|
215
|
+
swap are submitted for you, and each one carries an authenticated sender — so those three need
|
|
216
|
+
`signMessage` and `walletPublicKey` even when `enforceViewingKeyRegistration` is off:
|
|
217
|
+
|
|
218
|
+
```ts
|
|
219
|
+
// Private send (externalAmount 0) from a wallet adapter. Same for fullWithdraw / partialWithdraw
|
|
220
|
+
// (externalAmount < 0) and swapUtxo / swapWithChange.
|
|
221
|
+
await transact(
|
|
222
|
+
{ inputUtxos, outputUtxos, externalAmount: BigInt(0) },
|
|
223
|
+
{
|
|
224
|
+
connection,
|
|
225
|
+
programId: CLOAK_PROGRAM_ID,
|
|
226
|
+
relayUrl,
|
|
227
|
+
signMessage: (message) => wallet.signMessage(message),
|
|
228
|
+
walletPublicKey: wallet.publicKey, // becomes the authenticated sender
|
|
229
|
+
chainNoteViewingKeyNk: nk,
|
|
230
|
+
},
|
|
231
|
+
);
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
`signMessage` must return the raw 64-byte ed25519 detached signature over the bytes it is given;
|
|
235
|
+
adapters that re-encode or wrap the result are rejected by name. `walletPublicKey` must be the end
|
|
236
|
+
user's own wallet — it is the identity the transaction is authenticated as. Passing neither a
|
|
237
|
+
`depositorKeypair` nor both of these fails immediately, before any proof is generated.
|
|
238
|
+
|
|
239
|
+
`depositorKeypair`, `walletPublicKey` and `depositorPublicKey` are three names for the SAME end
|
|
240
|
+
user. That one key is the request's authenticated sender, the key screened for sanctions, and the
|
|
241
|
+
wallet a viewing key is registered against, so setting two of the names to two different keys would
|
|
242
|
+
screen one person and authenticate another. Passing two different wallets is refused at the call.
|
|
243
|
+
|
|
244
|
+
### The approval window
|
|
245
|
+
|
|
246
|
+
The request's timestamp is stamped when the bytes are built, because it is part of what the wallet
|
|
247
|
+
signs, and the relay accepts a first-use request for 300 seconds from that moment. An approval left
|
|
248
|
+
sitting in a hardware wallet past that window cannot be rescued by re-stamping it, so the SDK stops
|
|
249
|
+
there and says so instead of shipping a request that can only come back as a 401. Retry the
|
|
250
|
+
operation and approve the prompt when it appears.
|
|
251
|
+
|
|
252
|
+
`auth_issued_at` comes from the machine's own clock, and the relay rejects anything more than 30
|
|
253
|
+
seconds ahead of its own. A user whose clock is fast cannot authenticate at all until it is
|
|
254
|
+
corrected; `explainRelayAuthRejection` turns that rejection, and the rest of the relay's 401s, into
|
|
255
|
+
a sentence that names the cause. The SDK applies it to its own relay errors already.
|
|
256
|
+
|
|
257
|
+
A private send or withdrawal signs exactly ONCE: every network retry re-POSTs the same signed
|
|
258
|
+
bytes, so the user sees one prompt. A swap re-proves on every retry, so each retry needs its own
|
|
259
|
+
approval; `maxWalletApprovals` (default 5) bounds how many times one swap may interrupt the user,
|
|
260
|
+
independently of `maxRootRetries`. A `depositorKeypair` signs silently and is unaffected.
|
|
261
|
+
|
|
262
|
+
### Authenticating a call you build yourself
|
|
263
|
+
|
|
264
|
+
To authenticate a call you build yourself (a swap retry that posts only `retry_request_id`, for
|
|
265
|
+
example), use the exported primitives rather than re-deriving the scheme:
|
|
266
|
+
|
|
267
|
+
```ts
|
|
268
|
+
import { buildRelayAuthPreimage, TRANSACT_SWAP_AUTH_FIELDS } from "@cloak.dev/sdk";
|
|
269
|
+
|
|
270
|
+
const body = { retry_request_id: requestId, slippage_bps: 500 };
|
|
271
|
+
const preimage = buildRelayAuthPreimage(
|
|
272
|
+
"/transact_swap",
|
|
273
|
+
CLOAK_PROGRAM_ID,
|
|
274
|
+
body,
|
|
275
|
+
wallet.publicKey,
|
|
276
|
+
undefined,
|
|
277
|
+
TRANSACT_SWAP_AUTH_FIELDS,
|
|
278
|
+
);
|
|
279
|
+
const signature = await wallet.signMessage(preimage.message);
|
|
280
|
+
|
|
281
|
+
const payload = {
|
|
282
|
+
...body,
|
|
283
|
+
sender: preimage.sender,
|
|
284
|
+
auth_issued_at: preimage.auth_issued_at,
|
|
285
|
+
auth_nonce: preimage.auth_nonce,
|
|
286
|
+
auth_signature: Buffer.from(signature).toString("base64"),
|
|
287
|
+
};
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
Reuse one `preimage` for every retry of the same logical request; rebuilding it produces a new
|
|
291
|
+
nonce and a new request.
|
|
292
|
+
|
|
293
|
+
`slippage_bps` in that snippet is not decoration. Every other field in both lists is optional on
|
|
294
|
+
the relay side, so omitting one and signing it as `null` matches what the relay signs. `slippage_bps`
|
|
295
|
+
is the exception: it is not optional, and a request that omits it is read by the relay as **500**.
|
|
296
|
+
Omit it and you sign `null` while the relay signs `500`, the digests differ, and the answer is a 401
|
|
297
|
+
that points at nothing. Set it explicitly, to the same value the body carries. The SDK's own swap
|
|
298
|
+
path always does; a hand-built body that leaves it out is refused before it is signed.
|
|
299
|
+
|
|
300
|
+
`canonicalJson` is exported for the same reason, and it is the SDK's half of a byte-for-byte
|
|
301
|
+
agreement with one Rust function over one fixed schema: ASCII keys over strings, small unsigned
|
|
302
|
+
integers, booleans, nulls, arrays and plain objects. Amounts travel as decimal strings, not numbers,
|
|
303
|
+
because JavaScript and `serde_json` do not spell every number the same way. Anything outside that
|
|
304
|
+
schema that could serialize differently on the two sides is refused rather than silently signed.
|
|
305
|
+
|
|
191
306
|
## The UTXO model
|
|
192
307
|
|
|
193
308
|
- A shielded balance is a set of notes (`Utxo`): `{ amount, keypair, blinding, mintAddress, index?, commitment? }`.
|
|
194
309
|
Amounts are `bigint` in base units (lamports, or 10^-6 for USDC/USDT).
|
|
195
|
-
- Every transaction is 2-in / 2-out
|
|
310
|
+
- Every transaction is 2-in / 2-out; `transact` pads unused slots with zero notes for you.
|
|
311
|
+
`createZeroUtxo(mint)` is exported if you want to pass them explicitly.
|
|
196
312
|
- `externalAmount > 0` is a deposit (funds enter from `depositor`), `< 0` is a withdrawal to
|
|
197
313
|
`recipient`, `0` is a private send inside the pool.
|
|
198
314
|
- Pools are per mint. All inputs and outputs of one transaction live in the same pool;
|
|
@@ -261,7 +377,7 @@ await transact(
|
|
|
261
377
|
|
|
262
378
|
Minimum SPL deposit is 1.00 token. SOL deposits fit in a single v0 packet with the production
|
|
263
379
|
lookup table; SPL deposits currently still create a small supplemental lookup table
|
|
264
|
-
(about 0.0056 SOL rent, reclaimable by the depositor).
|
|
380
|
+
(about 0.0056 SOL rent, reclaimable by the depositor).
|
|
265
381
|
|
|
266
382
|
### Shielded swap (SOL to USDC/USDT)
|
|
267
383
|
|
|
@@ -343,10 +459,10 @@ notes also derive their secrets from it, which is what makes key-only recovery p
|
|
|
343
459
|
it with the same care as the spend key.
|
|
344
460
|
|
|
345
461
|
Before a wallet's first transaction the SDK registers `nk` with the relay for compliance scanning:
|
|
346
|
-
it
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
`
|
|
462
|
+
it signs a one-time challenge with `signMessage` (wallet) or `depositorKeypair` and submits `nk`
|
|
463
|
+
with that signature. Nothing viewing-key related is written on-chain. The step is on by default;
|
|
464
|
+
`enforceViewingKeyRegistration: false` disables it. `registerViewingKey(relayUrl, userPubkey, nk,
|
|
465
|
+
signMessage)` performs the same registration on its own.
|
|
350
466
|
|
|
351
467
|
```ts
|
|
352
468
|
import { scanTransactions, fetchCommitments, type Utxo } from "@cloak.dev/sdk";
|
|
@@ -365,8 +481,9 @@ scan.deliveredNotes; // notes sent to this wallet (amount + blinding; the
|
|
|
365
481
|
scan.transactions; // history rows for compliance reporting
|
|
366
482
|
```
|
|
367
483
|
|
|
368
|
-
`scanRecipientDeliveryNotes`
|
|
369
|
-
|
|
484
|
+
`scanRecipientDeliveryNotes` does the delivery sweep alone, returning `{ notes, rpcCalls }`
|
|
485
|
+
instead of a full scan result. Deposit recovery applies to deposits built with
|
|
486
|
+
`createRecoverableDepositUtxo` (the default in the examples); a deposit built with
|
|
370
487
|
`createUtxo` has a random blinding that is written nowhere and appears as history only.
|
|
371
488
|
|
|
372
489
|
A recovered or delivered note needs its leaf index before it can be spent. Look it up by commitment.
|
|
@@ -417,14 +534,12 @@ const deliveredNote: Utxo = {
|
|
|
417
534
|
|
|
418
535
|
## Nullifiers and spent checks
|
|
419
536
|
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
- `computeNullifier(skSpend, leafIndex)` is `Poseidon(sk0, sk1, leafIndex)` from the legacy
|
|
425
|
-
`withdraw_regular` circuit. It does not match anything the 0.2.0 program stores.
|
|
537
|
+
The nullifier export is `computeUtxoNullifier(utxo)`, the circuit's scheme:
|
|
538
|
+
`Poseidon(commitment, index, signature)`. This is the value the program records when a note is
|
|
539
|
+
spent, so it is what a spent check compares against. It is async and requires `utxo.index` to be
|
|
540
|
+
set.
|
|
426
541
|
|
|
427
|
-
Prefer the helpers, which
|
|
542
|
+
Prefer the helpers, which derive the nullifier and check the on-chain PDA for you:
|
|
428
543
|
|
|
429
544
|
```ts
|
|
430
545
|
import { verifyUtxos, preflightNullifiers } from "@cloak.dev/sdk";
|
|
@@ -450,7 +565,7 @@ Deposits and private sends carry no protocol fee.
|
|
|
450
565
|
A withdrawal or swap must exceed its fee or the program rejects it; deposits below the minimum are
|
|
451
566
|
rejected with `DepositTooSmall`.
|
|
452
567
|
|
|
453
|
-
`
|
|
568
|
+
`shared/fees.ts` mirrors the SOL pool for estimates in the UI:
|
|
454
569
|
|
|
455
570
|
```ts
|
|
456
571
|
import { calculateFeeBigint, getDistributableAmount, isWithdrawAmountSufficient } from "@cloak.dev/sdk";
|
|
@@ -468,31 +583,43 @@ lookup-table rent are separate.
|
|
|
468
583
|
|
|
469
584
|
Proving uses the `transaction` circuit from bundle `cloak-transaction-0.2.0` (multi-party ceremony,
|
|
470
585
|
6 contributors plus a public final beacon; 42,672 constraints, 9 public inputs). The verifying key is
|
|
471
|
-
embedded in the program
|
|
586
|
+
embedded in the program, so the SDK never fetches it; for the record, the exported
|
|
587
|
+
`transaction.vkey.json` from the same ceremony is SHA-256
|
|
588
|
+
`deb40e7b94eae17db2975d23dcf26c26db2a36a4f02d14a25830dee3e88fb93c`.
|
|
472
589
|
|
|
473
590
|
| Artifact | SHA-256 |
|
|
474
591
|
| --- | --- |
|
|
475
592
|
| `transaction_js/transaction.wasm` | `02ec02e954ae3932827ad9de51afa597ca95569aa97fec8410879c937a58aa2b` |
|
|
476
593
|
| `transaction_final.zkey` | `9da7db8cb1370fc497d36a0365f1f107ab0b0c13ca66fa9f0287e5f96ee68d25` |
|
|
477
|
-
| `transaction.vkey.json` | `deb40e7b94eae17db2975d23dcf26c26db2a36a4f02d14a25830dee3e88fb93c` |
|
|
478
594
|
|
|
479
|
-
The SDK downloads
|
|
595
|
+
The SDK downloads both artifacts once per process from
|
|
480
596
|
`DEFAULT_TRANSACTION_CIRCUITS_URL` (`https://storage.googleapis.com/cloak-circuits/circuits/0.2.0`),
|
|
481
597
|
hashes them, and refuses to prove if any digest differs from the pinned values. No configuration is
|
|
482
598
|
needed for mainnet.
|
|
483
599
|
|
|
484
|
-
To
|
|
485
|
-
`transaction_js/transaction.wasm` and
|
|
600
|
+
To load the artifacts from a local directory instead (an air-gapped machine, a React Native bundle,
|
|
601
|
+
or the ceremony output — the directory must contain `transaction_js/transaction.wasm` and
|
|
602
|
+
`transaction_final.zkey` with the same digests):
|
|
486
603
|
|
|
487
604
|
```ts
|
|
488
605
|
import { resolveCircuitsBase, setCircuitsPath } from "@cloak.dev/sdk";
|
|
489
606
|
|
|
490
|
-
// explicit argument, else
|
|
607
|
+
// explicit argument, else the pinned default; no environment variable is consulted
|
|
491
608
|
setCircuitsPath(resolveCircuitsBase());
|
|
609
|
+
setCircuitsPath("/opt/cloak/ceremony-0.2.0"); // or a local directory you control
|
|
492
610
|
```
|
|
493
611
|
|
|
494
612
|
Never write the artifact URL out by hand: the version segment and the digests are declared together
|
|
495
|
-
in `src/
|
|
613
|
+
in `src/proving/circuits.ts` so they cannot drift.
|
|
614
|
+
|
|
615
|
+
Where the artifacts may be read from is fixed when the SDK is built. `transaction.wasm` is the
|
|
616
|
+
witness generator, so it is handed your spend key, your note secrets, the amounts and the recipient
|
|
617
|
+
— a mirror on another host is therefore not accepted, and the SHA-256 check over the bytes cannot be
|
|
618
|
+
switched off by any option or environment variable. A local directory is accepted (nothing leaves
|
|
619
|
+
the machine, and the digest check still decides whether the bytes are usable); an `http(s)` base
|
|
620
|
+
must be the bundle base this build pins. To point a build somewhere else, edit
|
|
621
|
+
`RELAY_ORIGIN_ALLOWLIST` in `src/config/relay.ts` and rebuild — the one edit that also unlocks the
|
|
622
|
+
relay endpoint and the localhost-RPC check.
|
|
496
623
|
|
|
497
624
|
## Version and compatibility
|
|
498
625
|
|
|
@@ -502,38 +629,49 @@ in `src/config/circuit-release.ts` so they cannot drift.
|
|
|
502
629
|
USDC and USDT; viewing-key discovery followed by a spend; keypair-only deposit recovery.
|
|
503
630
|
- Proofs generated with the 0.1.x circuits are rejected by the mainnet program. SDK 0.1.x builds
|
|
504
631
|
(which ship the 0.1.0 bundle) are not usable against it; upgrade to 0.2.0.
|
|
505
|
-
- The note-based `CloakSDK` class
|
|
506
|
-
|
|
507
|
-
|
|
632
|
+
- The note-based `CloakSDK` class is removed in 0.2.0. It targeted the pre-0.2.0 instruction layout
|
|
633
|
+
and the unpublished 0.1.0 `withdraw_*` circuits, so it could not work against the current program.
|
|
634
|
+
Use the UTXO API above: `transact`, `transfer`, `partialWithdraw`, `fullWithdraw`, `swapUtxo`.
|
|
508
635
|
|
|
509
636
|
## Examples
|
|
510
637
|
|
|
511
638
|
```bash
|
|
512
|
-
|
|
513
|
-
npm run example:
|
|
514
|
-
npm run example:
|
|
515
|
-
npm run example:
|
|
516
|
-
npm run example:swap # SOL
|
|
517
|
-
|
|
639
|
+
# SOL pool
|
|
640
|
+
npm run example:deposit # move lamports into the shielded SOL pool
|
|
641
|
+
npm run example:private-send # shield-to-shield send the recipient can discover
|
|
642
|
+
npm run example:withdraw # partial withdraw, then full withdraw of the change
|
|
643
|
+
npm run example:swap # SOL to USDC through Jupiter
|
|
644
|
+
|
|
645
|
+
# SPL pools (USDC, USDT). There is no SPL swap: swap input is wSOL-locked.
|
|
646
|
+
npm run example:spl-deposit
|
|
647
|
+
npm run example:spl-private-send
|
|
648
|
+
npm run example:spl-withdraw
|
|
649
|
+
|
|
650
|
+
# Not pool specific
|
|
651
|
+
npm run example:viewing-keys # derive a viewing key, register it, read your history
|
|
652
|
+
|
|
653
|
+
# Swap variants
|
|
654
|
+
npm run example:swap-usdc # same swap, with the canonical swap markers
|
|
518
655
|
npm run example:swap-brz # BRZ with automatic USDC fallback
|
|
519
|
-
|
|
520
|
-
npm run
|
|
521
|
-
npm run test:examples # dry-run all of the above (no wallet, no RPC)
|
|
656
|
+
|
|
657
|
+
npm run test:examples # dry-run all eight (no wallet, no RPC)
|
|
522
658
|
```
|
|
523
659
|
|
|
660
|
+
Examples log by default. Set `CLOAK_DEBUG=0` to silence them.
|
|
661
|
+
|
|
524
662
|
Environment read by the examples:
|
|
525
663
|
|
|
526
664
|
| Variable | Default |
|
|
527
665
|
| --- | --- |
|
|
528
666
|
| `SOLANA_RPC_URL` | `http://127.0.0.1:8899` (local fork) |
|
|
529
|
-
| `CLOAK_RELAY_URL` | `http://127.0.0.1:5500` (local
|
|
667
|
+
| `CLOAK_RELAY_URL` | `http://127.0.0.1:5500` (local endpoint) — read by the examples, not by the SDK; it must name an origin the SDK build is pinned to |
|
|
530
668
|
| `CLOAK_PROGRAM_ID` | `CLOAK_PROGRAM_ID` |
|
|
531
|
-
| `CLOAK_CIRCUITS_PATH` | the pinned 0.2.0 bundle |
|
|
532
669
|
| `CLOAK_ALT_ADDRESSES` | unset; the production lookup tables are resolved automatically |
|
|
533
670
|
|
|
534
671
|
The examples fund throwaway keypairs from `~/.config/solana/id.json` and print stable
|
|
535
|
-
`FULL_SIG|<example>|<step>|<signature>` markers. They import `@cloak.
|
|
536
|
-
`tsconfig.json` maps to `src/index.ts
|
|
672
|
+
`FULL_SIG|<example>|<step>|<signature>` markers. They import `@cloak.dev/sdk`, the published
|
|
673
|
+
package name; inside this repo `tsconfig.json` maps that specifier to `src/index.ts` so the
|
|
674
|
+
examples run against source.
|
|
537
675
|
|
|
538
676
|
## Error handling
|
|
539
677
|
|
|
@@ -573,14 +711,14 @@ npm run verify:dist # dist is byte-identical to a fresh build
|
|
|
573
711
|
npm run test:examples # dry-run the examples
|
|
574
712
|
```
|
|
575
713
|
|
|
576
|
-
Notes:
|
|
577
|
-
|
|
714
|
+
Notes: `docs/DEPOSIT-SIZE-NOTES.md` (deposit transaction size, confirmed-tree reads,
|
|
715
|
+
supplemental lookup tables), `docs/transact-split.md` (how `flows/transact.ts` is split),
|
|
716
|
+
`docs/cleanup-plan.md` (the root/scripts/examples cleanup this repo is executing).
|
|
578
717
|
|
|
579
718
|
## Links
|
|
580
719
|
|
|
581
720
|
- Website: [https://cloak.ag](https://cloak.ag)
|
|
582
721
|
- Documentation: [https://docs.cloak.ag](https://docs.cloak.ag)
|
|
583
|
-
- GitHub: [https://github.com/cloak-ag/sdk](https://github.com/cloak-ag/sdk)
|
|
584
722
|
|
|
585
723
|
## License
|
|
586
724
|
|