@umbra-privacy/sdk 1.0.0 → 2.0.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.
- package/README.md +104 -25
- package/dist/{addresses-Brzgurv_.d.ts → addresses-B7HybtbJ.d.ts} +2 -1
- package/dist/{addresses-D_0YAS6B.d.cts → addresses-CTVY1oi7.d.cts} +2 -1
- package/dist/arcium-BXXlryfe.d.cts +20 -0
- package/dist/arcium-BXXlryfe.d.ts +20 -0
- package/dist/chunk-4RHXVBNI.js +203 -0
- package/dist/chunk-4RHXVBNI.js.map +1 -0
- package/dist/chunk-4TZVXB5G.js +324 -0
- package/dist/chunk-4TZVXB5G.js.map +1 -0
- package/dist/chunk-5GUSMQ74.cjs +549 -0
- package/dist/chunk-5GUSMQ74.cjs.map +1 -0
- package/dist/chunk-5KPQXPQM.js +36 -0
- package/dist/chunk-5KPQXPQM.js.map +1 -0
- package/dist/chunk-AXD7LXYY.cjs +405 -0
- package/dist/chunk-AXD7LXYY.cjs.map +1 -0
- package/dist/{chunk-HOEXDXRC.cjs → chunk-BL6WXLPV.cjs} +32 -360
- package/dist/chunk-BL6WXLPV.cjs.map +1 -0
- package/dist/chunk-CFFLOE7D.cjs +598 -0
- package/dist/chunk-CFFLOE7D.cjs.map +1 -0
- package/dist/{chunk-BM7N6N7E.js → chunk-CFTW5WNG.js} +3 -325
- package/dist/chunk-CFTW5WNG.js.map +1 -0
- package/dist/chunk-DD2WCK4C.js +327 -0
- package/dist/chunk-DD2WCK4C.js.map +1 -0
- package/dist/chunk-DMPMQ74B.cjs +246 -0
- package/dist/chunk-DMPMQ74B.cjs.map +1 -0
- package/dist/{chunk-2Q75CQQJ.js → chunk-EEKF4553.js} +2 -2
- package/dist/chunk-EEKF4553.js.map +1 -0
- package/dist/chunk-ENVYYEM4.cjs +113 -0
- package/dist/chunk-ENVYYEM4.cjs.map +1 -0
- package/dist/chunk-FQX6ZYGJ.js +500 -0
- package/dist/chunk-FQX6ZYGJ.js.map +1 -0
- package/dist/chunk-FSK2ICMB.cjs +39 -0
- package/dist/chunk-FSK2ICMB.cjs.map +1 -0
- package/dist/chunk-FZYWLQAF.cjs +355 -0
- package/dist/chunk-FZYWLQAF.cjs.map +1 -0
- package/dist/chunk-GP26R377.js +436 -0
- package/dist/chunk-GP26R377.js.map +1 -0
- package/dist/chunk-HA5FLM63.js +393 -0
- package/dist/chunk-HA5FLM63.js.map +1 -0
- package/dist/chunk-INJ73LXQ.js +1107 -0
- package/dist/chunk-INJ73LXQ.js.map +1 -0
- package/dist/chunk-JPDF7BIT.cjs +10892 -0
- package/dist/chunk-JPDF7BIT.cjs.map +1 -0
- package/dist/{chunk-MDFSBU5W.cjs → chunk-LTCKPTZC.cjs} +2 -351
- package/dist/chunk-LTCKPTZC.cjs.map +1 -0
- package/dist/chunk-MKNCBUFA.js +564 -0
- package/dist/chunk-MKNCBUFA.js.map +1 -0
- package/dist/chunk-NKVMSABR.cjs +207 -0
- package/dist/chunk-NKVMSABR.cjs.map +1 -0
- package/dist/chunk-OFDWNWCL.js +70 -0
- package/dist/chunk-OFDWNWCL.js.map +1 -0
- package/dist/chunk-QJAUUYZU.cjs +331 -0
- package/dist/chunk-QJAUUYZU.cjs.map +1 -0
- package/dist/chunk-RVUYPKKD.js +10750 -0
- package/dist/chunk-RVUYPKKD.js.map +1 -0
- package/dist/chunk-TLR7A64G.js +103 -0
- package/dist/chunk-TLR7A64G.js.map +1 -0
- package/dist/{chunk-MVKTV3FT.cjs → chunk-TQQZGNOI.cjs} +2 -2
- package/dist/chunk-TQQZGNOI.cjs.map +1 -0
- package/dist/chunk-UOFYS6M3.js +219 -0
- package/dist/chunk-UOFYS6M3.js.map +1 -0
- package/dist/chunk-UXMQI6B7.js +2406 -0
- package/dist/chunk-UXMQI6B7.js.map +1 -0
- package/dist/chunk-WN75ORDT.js +571 -0
- package/dist/chunk-WN75ORDT.js.map +1 -0
- package/dist/chunk-Y55PYKXH.cjs +595 -0
- package/dist/chunk-Y55PYKXH.cjs.map +1 -0
- package/dist/chunk-YEZBTYCP.cjs +77 -0
- package/dist/chunk-YEZBTYCP.cjs.map +1 -0
- package/dist/chunk-ZQOIYCGA.cjs +1126 -0
- package/dist/chunk-ZQOIYCGA.cjs.map +1 -0
- package/dist/chunk-ZY3TSHMJ.cjs +2665 -0
- package/dist/chunk-ZY3TSHMJ.cjs.map +1 -0
- package/dist/client-DkVBHMWb.d.cts +2613 -0
- package/dist/client-V4AF6Bz9.d.ts +2613 -0
- package/dist/common/pda/index.cjs +145 -0
- package/dist/common/pda/index.cjs.map +1 -0
- package/dist/common/pda/index.d.cts +1250 -0
- package/dist/common/pda/index.d.ts +1250 -0
- package/dist/common/pda/index.js +8 -0
- package/dist/common/pda/index.js.map +1 -0
- package/dist/constants/index.cjs +38 -164
- package/dist/constants/index.cjs.map +1 -1
- package/dist/constants/index.d.cts +8 -425
- package/dist/constants/index.d.ts +8 -425
- package/dist/constants/index.js +15 -124
- package/dist/constants/index.js.map +1 -1
- package/dist/crypto/index.cjs +583 -0
- package/dist/crypto/index.cjs.map +1 -0
- package/dist/crypto/index.d.cts +6731 -0
- package/dist/crypto/index.d.ts +6731 -0
- package/dist/crypto/index.js +14 -0
- package/dist/crypto/index.js.map +1 -0
- package/dist/{cryptography-BTGC72u-.d.ts → cryptography-BFSJcvi6.d.ts} +3 -2465
- package/dist/{cryptography-BTGC72u-.d.cts → cryptography-D6tPDh-Y.d.cts} +3 -2465
- package/dist/errors/index.cjs +64 -54
- package/dist/errors/index.d.cts +7 -797
- package/dist/errors/index.d.ts +7 -797
- package/dist/errors/index.js +3 -1
- package/dist/errors-B9EoPeWV.d.cts +593 -0
- package/dist/errors-B9EoPeWV.d.ts +593 -0
- package/dist/errors-DAIrstEL.d.cts +300 -0
- package/dist/errors-DPNMfyh0.d.ts +300 -0
- package/dist/index-BG0yjL7C.d.cts +6006 -0
- package/dist/index-ByynoyBO.d.ts +6006 -0
- package/dist/index.cjs +5126 -16118
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1031 -7685
- package/dist/index.d.ts +1031 -7685
- package/dist/index.js +3219 -14905
- package/dist/index.js.map +1 -1
- package/dist/interfaces/index.d.cts +14 -6
- package/dist/interfaces/index.d.ts +14 -6
- package/dist/interfaces-43cReBcS.d.cts +3346 -0
- package/dist/interfaces-B8xKNl_6.d.ts +997 -0
- package/dist/interfaces-D2NO6kDD.d.cts +997 -0
- package/dist/interfaces-z_xYJlgV.d.ts +3346 -0
- package/dist/math/index.cjs +115 -0
- package/dist/math/index.cjs.map +1 -0
- package/dist/math/index.d.cts +1327 -0
- package/dist/math/index.d.ts +1327 -0
- package/dist/math/index.js +10 -0
- package/dist/math/index.js.map +1 -0
- package/dist/networks-RMd3abPE.d.ts +44 -0
- package/dist/networks-yAoO8peQ.d.cts +44 -0
- package/dist/relayer-NRRMSMNB.js +4 -0
- package/dist/relayer-NRRMSMNB.js.map +1 -0
- package/dist/relayer-RJHEIXJG.cjs +21 -0
- package/dist/relayer-RJHEIXJG.cjs.map +1 -0
- package/dist/solana/index.cjs +56 -0
- package/dist/solana/index.cjs.map +1 -0
- package/dist/solana/index.d.cts +105 -0
- package/dist/solana/index.d.ts +105 -0
- package/dist/solana/index.js +7 -0
- package/dist/solana/index.js.map +1 -0
- package/dist/{index-CLj_zWSD.d.ts → temporal-BbRaEPoO.d.ts} +1 -1
- package/dist/{index-CX6_pIRS.d.cts → temporal-oUj7iCaq.d.cts} +1 -1
- package/dist/transaction-forwarder-5mAMTjw6.d.ts +1155 -0
- package/dist/transaction-forwarder-C6gMUG7a.d.cts +1155 -0
- package/dist/types/index.cjs +232 -231
- package/dist/types/index.d.cts +15 -1485
- package/dist/types/index.d.ts +15 -1485
- package/dist/types/index.js +2 -1
- package/dist/types-BohhvPth.d.cts +87 -0
- package/dist/types-CW0oTT0j.d.ts +87 -0
- package/dist/types-C_V_CaKK.d.cts +2468 -0
- package/dist/types-C_V_CaKK.d.ts +2468 -0
- package/dist/types-Ca7frykr.d.ts +793 -0
- package/dist/types-CuKeoI19.d.cts +1296 -0
- package/dist/types-CxfTIpN9.d.ts +1052 -0
- package/dist/{types-n-sHFcgr.d.ts → types-D1jDUjfN.d.ts} +2 -2
- package/dist/types-DKEDUlH9.d.ts +1296 -0
- package/dist/types-EKuIfxTz.d.cts +1052 -0
- package/dist/{types-BBuELtY8.d.cts → types-IMGYmlv-.d.cts} +2 -2
- package/dist/types-PwNLi_2k.d.cts +793 -0
- package/dist/utils/index.cjs +823 -525
- package/dist/utils/index.d.cts +1711 -4021
- package/dist/utils/index.d.ts +1711 -4021
- package/dist/utils/index.js +9 -3
- package/dist/{versions-D9PqsEvj.d.cts → versions-BRlR36EA.d.cts} +1 -0
- package/dist/{versions-D9PqsEvj.d.ts → versions-BRlR36EA.d.ts} +1 -0
- package/package.json +79 -18
- package/dist/chunk-2Q75CQQJ.js.map +0 -1
- package/dist/chunk-BM7N6N7E.js.map +0 -1
- package/dist/chunk-GXKSUB2U.cjs +0 -4416
- package/dist/chunk-GXKSUB2U.cjs.map +0 -1
- package/dist/chunk-HOEXDXRC.cjs.map +0 -1
- package/dist/chunk-MDFSBU5W.cjs.map +0 -1
- package/dist/chunk-MQY7HDIA.js +0 -600
- package/dist/chunk-MQY7HDIA.js.map +0 -1
- package/dist/chunk-MVKTV3FT.cjs.map +0 -1
- package/dist/chunk-PG2J6V6Y.js +0 -4094
- package/dist/chunk-PG2J6V6Y.js.map +0 -1
- package/dist/chunk-VEGLTTYQ.cjs +0 -621
- package/dist/chunk-VEGLTTYQ.cjs.map +0 -1
- package/dist/chunk-WVHQ46DD.js +0 -758
- package/dist/chunk-WVHQ46DD.js.map +0 -1
- package/dist/index-B9pDY73x.d.ts +0 -12933
- package/dist/index-D33yo0qB.d.cts +0 -12933
- package/dist/networks-C-orpSFW.d.ts +0 -65
- package/dist/networks-FxYERGD1.d.cts +0 -65
package/README.md
CHANGED
|
@@ -12,23 +12,23 @@ pnpm add @umbra-privacy/sdk
|
|
|
12
12
|
|
|
13
13
|
```typescript
|
|
14
14
|
import {
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
getInMemorySigner,
|
|
16
|
+
getUmbraClient,
|
|
17
17
|
getUserRegistrationFunction,
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
getPublicBalanceToEncryptedBalanceDirectDepositorFunction,
|
|
19
|
+
getEncryptedBalanceToPublicBalanceDirectWithdrawerFunction,
|
|
20
20
|
} from "@umbra-privacy/sdk";
|
|
21
21
|
|
|
22
22
|
// 1. Create a signer (use a wallet adapter in production)
|
|
23
|
-
const signer = await
|
|
23
|
+
const signer = await getInMemorySigner();
|
|
24
24
|
|
|
25
25
|
// 2. Create the Umbra client
|
|
26
|
-
const client = await
|
|
26
|
+
const client = await getUmbraClient({
|
|
27
27
|
signer,
|
|
28
28
|
network: "mainnet",
|
|
29
29
|
rpcUrl: "https://api.mainnet-beta.solana.com",
|
|
30
30
|
rpcSubscriptionsUrl: "wss://api.mainnet-beta.solana.com",
|
|
31
|
-
indexerApiEndpoint: "https://
|
|
31
|
+
indexerApiEndpoint: "https://indexer.umbraprivacy.com",
|
|
32
32
|
});
|
|
33
33
|
|
|
34
34
|
// 3. Register (idempotent — safe to call even if already registered)
|
|
@@ -36,13 +36,13 @@ const register = getUserRegistrationFunction({ client });
|
|
|
36
36
|
await register({ confidential: true, anonymous: true });
|
|
37
37
|
|
|
38
38
|
// 4. Deposit tokens into an encrypted balance
|
|
39
|
-
const deposit =
|
|
40
|
-
const
|
|
41
|
-
await deposit(signer.address,
|
|
39
|
+
const deposit = getPublicBalanceToEncryptedBalanceDirectDepositorFunction({ client });
|
|
40
|
+
const USDC = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v";
|
|
41
|
+
await deposit(signer.address, USDC, 1_000_000n);
|
|
42
42
|
|
|
43
43
|
// 5. Withdraw back to public wallet
|
|
44
|
-
const withdraw =
|
|
45
|
-
await withdraw(signer.address,
|
|
44
|
+
const withdraw = getEncryptedBalanceToPublicBalanceDirectWithdrawerFunction({ client });
|
|
45
|
+
await withdraw(signer.address, USDC, 1_000_000n);
|
|
46
46
|
```
|
|
47
47
|
|
|
48
48
|
## Features
|
|
@@ -58,9 +58,12 @@ await withdraw(signer.address, MINT, 1_000_000n);
|
|
|
58
58
|
The SDK provides granular subpath exports to keep bundle sizes small:
|
|
59
59
|
|
|
60
60
|
- `@umbra-privacy/sdk` — Client construction, service factories, cryptographic operations
|
|
61
|
+
- `@umbra-privacy/sdk/crypto` — Rescue cipher, Poseidon hash, AES, key derivation, Fiat-Shamir challenges
|
|
62
|
+
- `@umbra-privacy/sdk/pda` — Program Derived Address derivation for all Umbra and Arcium accounts
|
|
63
|
+
- `@umbra-privacy/sdk/solana` — RPC providers, signers, transaction forwarding
|
|
64
|
+
- `@umbra-privacy/sdk/math` — BN254 and Curve25519 field arithmetic
|
|
61
65
|
- `@umbra-privacy/sdk/types` — Branded types and assertion functions (`assertU64`, `assertAddress`, etc.)
|
|
62
66
|
- `@umbra-privacy/sdk/interfaces` — Function type signatures for all factory functions and dependencies
|
|
63
|
-
- `@umbra-privacy/sdk/utils` — Converter utilities, PDA derivation helpers, address utilities
|
|
64
67
|
- `@umbra-privacy/sdk/constants` — Network configs, program IDs, domain separators
|
|
65
68
|
- `@umbra-privacy/sdk/errors` — Error classes, stage enums, and type guards
|
|
66
69
|
|
|
@@ -69,10 +72,10 @@ The SDK provides granular subpath exports to keep bundle sizes small:
|
|
|
69
72
|
Every SDK operation follows the same two-step pattern:
|
|
70
73
|
|
|
71
74
|
```typescript
|
|
72
|
-
// Build the function once (captures client config and optional dependency overrides)
|
|
75
|
+
// Step 1: Build the function once (captures client config and optional dependency overrides)
|
|
73
76
|
const operation = getOperationFunction({ client }, optionalDeps);
|
|
74
77
|
|
|
75
|
-
// Call it at runtime
|
|
78
|
+
// Step 2: Call it at runtime (can be called many times with different args)
|
|
76
79
|
const result = await operation(/* runtime arguments */);
|
|
77
80
|
```
|
|
78
81
|
|
|
@@ -80,15 +83,91 @@ The optional `deps` argument accepts injectable overrides for RPC providers, key
|
|
|
80
83
|
|
|
81
84
|
## Available Services
|
|
82
85
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
- **
|
|
86
|
-
- **
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
-
|
|
91
|
-
-
|
|
86
|
+
### Token Flow (Source → Destination → Action)
|
|
87
|
+
|
|
88
|
+
- **Direct Deposit** — `getPublicBalanceToEncryptedBalanceDirectDepositorFunction` — Move tokens from public wallet into encrypted balance
|
|
89
|
+
- **Direct Withdraw** — `getEncryptedBalanceToPublicBalanceDirectWithdrawerFunction` — Move tokens from encrypted balance to public wallet
|
|
90
|
+
|
|
91
|
+
### UTXO Creation (Stealth Pool Deposits)
|
|
92
|
+
|
|
93
|
+
- `getPublicBalanceToSelfClaimableUtxoCreatorFunction` — Shield your own public tokens into the mixer
|
|
94
|
+
- `getEncryptedBalanceToSelfClaimableUtxoCreatorFunction` — Shield your own encrypted tokens into the mixer
|
|
95
|
+
- `getPublicBalanceToReceiverClaimableUtxoCreatorFunction` — Send public tokens to a receiver via the mixer
|
|
96
|
+
- `getEncryptedBalanceToReceiverClaimableUtxoCreatorFunction` — Send encrypted tokens to a receiver via the mixer
|
|
97
|
+
|
|
98
|
+
### UTXO Scanning & Claiming
|
|
99
|
+
|
|
100
|
+
- `getClaimableUtxoScannerFunction` — Scan Merkle trees for UTXOs addressed to your keys
|
|
101
|
+
- `getSelfClaimableUtxoToEncryptedBalanceClaimerFunction` — Claim your own UTXO into encrypted balance
|
|
102
|
+
- `getSelfClaimableUtxoToPublicBalanceClaimerFunction` — Claim your own UTXO into public wallet
|
|
103
|
+
- `getReceiverClaimableUtxoToEncryptedBalanceClaimerFunction` — Claim a received UTXO into encrypted balance
|
|
104
|
+
|
|
105
|
+
### User Account Management
|
|
106
|
+
|
|
107
|
+
- `getUserRegistrationFunction` — Account init, X25519 key registration, anonymous usage setup
|
|
108
|
+
- `getUserEncryptionKeyRotatorFunction` — Rotate user account X25519 encryption key
|
|
109
|
+
- `getMasterViewingKeyRotatorFunction` — Rotate master viewing key
|
|
110
|
+
- `getUserEntropySeedRotatorFunction` — Rotate user-level entropy seed
|
|
111
|
+
- `getTokenEntropySeedRotatorFunction` — Rotate per-token entropy seed
|
|
112
|
+
- `getStagedSolRecovererFunction` — Recover SOL stuck from failed MPC callbacks
|
|
113
|
+
- `getStagedSplRecovererFunction` — Recover SPL tokens stuck from failed MPC callbacks
|
|
114
|
+
|
|
115
|
+
### Query
|
|
116
|
+
|
|
117
|
+
- `getUserAccountQuerierFunction` — Read user account state
|
|
118
|
+
- `getEncryptedBalanceQuerierFunction` — Read and decrypt encrypted token balance
|
|
119
|
+
|
|
120
|
+
### Conversion
|
|
121
|
+
|
|
122
|
+
- `getNetworkEncryptionToSharedEncryptionConverterFunction` — Convert from network-only to shared encryption mode
|
|
123
|
+
- `getMintEncryptionKeyRotatorFunction` — Rotate per-mint encryption key
|
|
124
|
+
|
|
125
|
+
### Compliance
|
|
126
|
+
|
|
127
|
+
- `getComplianceGrantIssuerFunction` — Authorize an auditor to view encrypted data
|
|
128
|
+
- `getComplianceGrantRevokerFunction` — Revoke auditor access
|
|
129
|
+
- `getSharedCiphertextReencryptorForUserGrantFunction` — Re-encrypt shared balance for a user-granted auditor
|
|
130
|
+
- `getNetworkCiphertextReencryptorForNetworkGrantFunction` — Re-encrypt network balance for a network-granted auditor
|
|
131
|
+
- `getSharedCiphertextReencryptorForNetworkGrantFunction` — Re-encrypt shared balance for a network-granted auditor
|
|
132
|
+
|
|
133
|
+
## PDA Derivation
|
|
134
|
+
|
|
135
|
+
All Program Derived Address functions use the `find*Pda` convention:
|
|
136
|
+
|
|
137
|
+
```typescript
|
|
138
|
+
import {
|
|
139
|
+
findEncryptedTokenAccountPda,
|
|
140
|
+
findStealthPoolPda,
|
|
141
|
+
findNullifierSetPdas,
|
|
142
|
+
} from "@umbra-privacy/sdk/pda";
|
|
143
|
+
|
|
144
|
+
const tokenAccountPda = await findEncryptedTokenAccountPda(userAddress, mintAddress, programId);
|
|
145
|
+
const stealthPoolPda = await findStealthPoolPda(treeIndex, programId);
|
|
146
|
+
const nullifierPdas = await findNullifierSetPdas(treeIndex, programId);
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
## Cryptography
|
|
150
|
+
|
|
151
|
+
```typescript
|
|
152
|
+
import {
|
|
153
|
+
getRescueEncryptorFromPrivateKey,
|
|
154
|
+
getRescueDecryptorFromPrivateKey,
|
|
155
|
+
getPoseidonHasher,
|
|
156
|
+
getMasterViewingKeyDeriver,
|
|
157
|
+
} from "@umbra-privacy/sdk/crypto";
|
|
158
|
+
|
|
159
|
+
// Rescue cipher encryption
|
|
160
|
+
const encryptor = getRescueEncryptorFromPrivateKey(privateKey);
|
|
161
|
+
const { ciphertexts, nonce } = await encryptor([plaintext]);
|
|
162
|
+
|
|
163
|
+
// Poseidon hashing
|
|
164
|
+
const hasher = getPoseidonHasher();
|
|
165
|
+
const hash = hasher([input1, input2]);
|
|
166
|
+
|
|
167
|
+
// Key derivation
|
|
168
|
+
const deriveMvk = getMasterViewingKeyDeriver({ client });
|
|
169
|
+
const masterViewingKey = await deriveMvk();
|
|
170
|
+
```
|
|
92
171
|
|
|
93
172
|
## ZK Provers
|
|
94
173
|
|
|
@@ -102,7 +181,7 @@ pnpm add @umbra-privacy/web-zk-prover
|
|
|
102
181
|
import { getCreateReceiverClaimableUtxoFromPublicBalanceProver } from "@umbra-privacy/web-zk-prover";
|
|
103
182
|
|
|
104
183
|
const zkProver = getCreateReceiverClaimableUtxoFromPublicBalanceProver();
|
|
105
|
-
const createUtxo =
|
|
184
|
+
const createUtxo = getPublicBalanceToReceiverClaimableUtxoCreatorFunction(
|
|
106
185
|
{ client },
|
|
107
186
|
{ zkProver },
|
|
108
187
|
);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Address } from '@solana/kit';
|
|
2
|
-
import { U as U128 } from './
|
|
2
|
+
import { U as U128 } from './types-C_V_CaKK.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Address Utilities
|
|
@@ -34,6 +34,7 @@ import { U as U128 } from './cryptography-BTGC72u-.js';
|
|
|
34
34
|
* Poseidon hash calls, and the TypeScript SDK.
|
|
35
35
|
*
|
|
36
36
|
* @packageDocumentation
|
|
37
|
+
* @since 2.0.0
|
|
37
38
|
* @module utils/miscellaneous/addresses
|
|
38
39
|
*/
|
|
39
40
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Address } from '@solana/kit';
|
|
2
|
-
import { U as U128 } from './
|
|
2
|
+
import { U as U128 } from './types-C_V_CaKK.cjs';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Address Utilities
|
|
@@ -34,6 +34,7 @@ import { U as U128 } from './cryptography-BTGC72u-.cjs';
|
|
|
34
34
|
* Poseidon hash calls, and the TypeScript SDK.
|
|
35
35
|
*
|
|
36
36
|
* @packageDocumentation
|
|
37
|
+
* @since 2.0.0
|
|
37
38
|
* @module utils/miscellaneous/addresses
|
|
38
39
|
*/
|
|
39
40
|
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Arcium Protocol Types
|
|
3
|
+
*
|
|
4
|
+
* Branded types for Arcium-specific protocol values.
|
|
5
|
+
*
|
|
6
|
+
* @since 2.0.0
|
|
7
|
+
* @module types/arcium
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Micro-lamports per Arcium Computation Unit.
|
|
11
|
+
*
|
|
12
|
+
* This is a branded bigint representing the price a user is willing to pay
|
|
13
|
+
* per ACU of Arcium computation. The value is passed directly to the on-chain
|
|
14
|
+
* `priorityFees` instruction field.
|
|
15
|
+
*/
|
|
16
|
+
type MicroLamportsPerAcu = bigint & {
|
|
17
|
+
readonly __brand: "MicroLamportsPerAcu";
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export type { MicroLamportsPerAcu as M };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Arcium Protocol Types
|
|
3
|
+
*
|
|
4
|
+
* Branded types for Arcium-specific protocol values.
|
|
5
|
+
*
|
|
6
|
+
* @since 2.0.0
|
|
7
|
+
* @module types/arcium
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Micro-lamports per Arcium Computation Unit.
|
|
11
|
+
*
|
|
12
|
+
* This is a branded bigint representing the price a user is willing to pay
|
|
13
|
+
* per ACU of Arcium computation. The value is passed directly to the on-chain
|
|
14
|
+
* `priorityFees` instruction field.
|
|
15
|
+
*/
|
|
16
|
+
type MicroLamportsPerAcu = bigint & {
|
|
17
|
+
readonly __brand: "MicroLamportsPerAcu";
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export type { MicroLamportsPerAcu as M };
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import { __name } from './chunk-7QVYU63E.js';
|
|
2
|
+
import { address } from '@solana/kit';
|
|
3
|
+
|
|
4
|
+
var ENDPOINTS = {
|
|
5
|
+
/** Fetches relayer address, supported mints, and active stealth pool indices. */
|
|
6
|
+
RELAYER_INFO: `/v1/relayer/info`,
|
|
7
|
+
/** Submits a claim request (relayer builds transactions from crypto data). */
|
|
8
|
+
CLAIM_SUBMIT: `/v1/claims`,
|
|
9
|
+
/** Polls claim status by request ID. `{id}` is replaced at call time. */
|
|
10
|
+
CLAIM_STATUS: `/v1/claims/{id}`
|
|
11
|
+
};
|
|
12
|
+
var RelayerError = class _RelayerError extends Error {
|
|
13
|
+
static {
|
|
14
|
+
__name(this, "RelayerError");
|
|
15
|
+
}
|
|
16
|
+
/** The relayer operation that failed (e.g. `"getRelayerAddress"`, `"claimSubmit"`). */
|
|
17
|
+
operation;
|
|
18
|
+
/** HTTP status code if the server responded, `undefined` for transport errors. */
|
|
19
|
+
statusCode;
|
|
20
|
+
/** Machine-readable error code from the API error body. */
|
|
21
|
+
errorCode;
|
|
22
|
+
constructor(operation, message, statusCode, errorCode, cause) {
|
|
23
|
+
super(`Relayer operation '${operation}' failed: ${message}`);
|
|
24
|
+
this.name = "RelayerError";
|
|
25
|
+
this.operation = operation;
|
|
26
|
+
this.statusCode = statusCode;
|
|
27
|
+
this.errorCode = errorCode;
|
|
28
|
+
this.cause = cause;
|
|
29
|
+
if (Error.captureStackTrace !== void 0) {
|
|
30
|
+
Error.captureStackTrace(this, _RelayerError);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
async function makeRequest(endpoint, fetchImpl, options) {
|
|
35
|
+
const { method = "GET", body, operation } = options;
|
|
36
|
+
try {
|
|
37
|
+
const requestInit = {
|
|
38
|
+
method,
|
|
39
|
+
headers: {
|
|
40
|
+
"Content-Type": "application/json",
|
|
41
|
+
Accept: "application/json"
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
if (body !== void 0) {
|
|
45
|
+
requestInit.body = JSON.stringify(body);
|
|
46
|
+
}
|
|
47
|
+
const response = await fetchImpl(endpoint, requestInit);
|
|
48
|
+
const data = await response.json();
|
|
49
|
+
if (!response.ok) {
|
|
50
|
+
const errorData = data;
|
|
51
|
+
const message = errorData.error?.message ?? errorData.message ?? `HTTP ${String(response.status)}`;
|
|
52
|
+
const code = errorData.error?.code ?? errorData.error_code;
|
|
53
|
+
throw new RelayerError(operation, message, response.status, code);
|
|
54
|
+
}
|
|
55
|
+
return data;
|
|
56
|
+
} catch (error) {
|
|
57
|
+
if (error instanceof RelayerError) {
|
|
58
|
+
throw error;
|
|
59
|
+
}
|
|
60
|
+
throw new RelayerError(
|
|
61
|
+
operation,
|
|
62
|
+
error instanceof Error ? error.message : "Unknown error",
|
|
63
|
+
void 0,
|
|
64
|
+
void 0,
|
|
65
|
+
error instanceof Error ? error : void 0
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
__name(makeRequest, "makeRequest");
|
|
70
|
+
function convertClaimStatusResponse(api) {
|
|
71
|
+
return {
|
|
72
|
+
requestId: api.request_id,
|
|
73
|
+
status: api.status,
|
|
74
|
+
variant: api.variant,
|
|
75
|
+
resolvedVariant: api.resolved_variant,
|
|
76
|
+
txSignature: api.tx_signature,
|
|
77
|
+
callbackSignature: api.callback_signature,
|
|
78
|
+
computationAccount: api.computation_account,
|
|
79
|
+
failureReason: api.failure_reason,
|
|
80
|
+
createdAt: api.created_at,
|
|
81
|
+
updatedAt: api.updated_at
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
__name(convertClaimStatusResponse, "convertClaimStatusResponse");
|
|
85
|
+
function getUmbraRelayer(args, deps) {
|
|
86
|
+
const { apiEndpoint } = args;
|
|
87
|
+
const fetchImpl = deps?.fetch ?? globalThis.fetch;
|
|
88
|
+
if (apiEndpoint === "") {
|
|
89
|
+
throw new RelayerError("initialization", "apiEndpoint must be a non-empty string");
|
|
90
|
+
}
|
|
91
|
+
const normalizedEndpoint = apiEndpoint.replace(/\/$/, "");
|
|
92
|
+
let cachedAddress = null;
|
|
93
|
+
let cachedInfo = null;
|
|
94
|
+
async function fetchInfo() {
|
|
95
|
+
if (cachedInfo !== null) {
|
|
96
|
+
return cachedInfo;
|
|
97
|
+
}
|
|
98
|
+
const response = await makeRequest(
|
|
99
|
+
`${normalizedEndpoint}${ENDPOINTS.RELAYER_INFO}`,
|
|
100
|
+
fetchImpl,
|
|
101
|
+
{ operation: "getRelayerInfo" }
|
|
102
|
+
);
|
|
103
|
+
cachedInfo = response;
|
|
104
|
+
cachedAddress = address(response.address);
|
|
105
|
+
return response;
|
|
106
|
+
}
|
|
107
|
+
__name(fetchInfo, "fetchInfo");
|
|
108
|
+
return {
|
|
109
|
+
apiEndpoint: normalizedEndpoint,
|
|
110
|
+
async getFeePayer() {
|
|
111
|
+
if (cachedAddress !== null) {
|
|
112
|
+
return cachedAddress;
|
|
113
|
+
}
|
|
114
|
+
const info = await fetchInfo();
|
|
115
|
+
return address(info.address);
|
|
116
|
+
},
|
|
117
|
+
async getRelayerAddress() {
|
|
118
|
+
if (cachedAddress !== null) {
|
|
119
|
+
return cachedAddress;
|
|
120
|
+
}
|
|
121
|
+
const info = await fetchInfo();
|
|
122
|
+
return address(info.address);
|
|
123
|
+
},
|
|
124
|
+
async getSupportedMints() {
|
|
125
|
+
const info = await fetchInfo();
|
|
126
|
+
return {
|
|
127
|
+
relayer: info.address,
|
|
128
|
+
mints: info.supported_mints,
|
|
129
|
+
count: BigInt(info.supported_mints.length)
|
|
130
|
+
};
|
|
131
|
+
},
|
|
132
|
+
async submitClaim(request) {
|
|
133
|
+
const response = await makeRequest(
|
|
134
|
+
`${normalizedEndpoint}${ENDPOINTS.CLAIM_SUBMIT}`,
|
|
135
|
+
fetchImpl,
|
|
136
|
+
{ method: "POST", body: request, operation: "claimSubmit" }
|
|
137
|
+
);
|
|
138
|
+
return {
|
|
139
|
+
requestId: response.request_id,
|
|
140
|
+
status: response.status
|
|
141
|
+
};
|
|
142
|
+
},
|
|
143
|
+
async pollClaimStatus(requestId) {
|
|
144
|
+
const url = `${normalizedEndpoint}${ENDPOINTS.CLAIM_STATUS.replace("{id}", requestId)}`;
|
|
145
|
+
const response = await makeRequest(url, fetchImpl, {
|
|
146
|
+
operation: "claimStatus"
|
|
147
|
+
});
|
|
148
|
+
return convertClaimStatusResponse(response);
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
__name(getUmbraRelayer, "getUmbraRelayer");
|
|
153
|
+
var TERMINAL_CLAIM_STATUSES = /* @__PURE__ */ new Set([
|
|
154
|
+
"completed",
|
|
155
|
+
"failed",
|
|
156
|
+
"timed_out"
|
|
157
|
+
]);
|
|
158
|
+
async function pollClaimUntilTerminal(pollClaimStatus, requestId, options) {
|
|
159
|
+
const pollingIntervalMs = options?.pollingIntervalMs ?? 3e3;
|
|
160
|
+
const timeoutMs = options?.timeoutMs ?? 12e4;
|
|
161
|
+
const onProgress = options?.onProgress;
|
|
162
|
+
const startTime = Date.now();
|
|
163
|
+
while (true) {
|
|
164
|
+
const status = await pollClaimStatus(requestId);
|
|
165
|
+
if (onProgress !== void 0) {
|
|
166
|
+
onProgress({
|
|
167
|
+
requestId: status.requestId,
|
|
168
|
+
status: status.status,
|
|
169
|
+
resolvedVariant: status.resolvedVariant,
|
|
170
|
+
txSignature: status.txSignature,
|
|
171
|
+
callbackSignature: status.callbackSignature,
|
|
172
|
+
failureReason: status.failureReason
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
if (TERMINAL_CLAIM_STATUSES.has(status.status)) {
|
|
176
|
+
const result = {
|
|
177
|
+
requestId: status.requestId,
|
|
178
|
+
status: status.status,
|
|
179
|
+
txSignature: status.txSignature,
|
|
180
|
+
callbackSignature: status.callbackSignature,
|
|
181
|
+
resolvedVariant: status.resolvedVariant,
|
|
182
|
+
failureReason: status.failureReason
|
|
183
|
+
};
|
|
184
|
+
return result;
|
|
185
|
+
}
|
|
186
|
+
if (Date.now() - startTime >= timeoutMs) {
|
|
187
|
+
const timedOutResult = {
|
|
188
|
+
requestId: status.requestId,
|
|
189
|
+
status: "timed_out",
|
|
190
|
+
failureReason: `Polling timed out after ${String(timeoutMs)}ms (last status: ${String(status.status)})`
|
|
191
|
+
};
|
|
192
|
+
return timedOutResult;
|
|
193
|
+
}
|
|
194
|
+
await new Promise((resolve) => {
|
|
195
|
+
setTimeout(resolve, pollingIntervalMs);
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
__name(pollClaimUntilTerminal, "pollClaimUntilTerminal");
|
|
200
|
+
|
|
201
|
+
export { RelayerError, getUmbraRelayer, pollClaimUntilTerminal };
|
|
202
|
+
//# sourceMappingURL=chunk-4RHXVBNI.js.map
|
|
203
|
+
//# sourceMappingURL=chunk-4RHXVBNI.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/umbra/relayer.ts"],"names":[],"mappings":";;;AAkDA,IAAM,SAAA,GAAY;AAAA;AAAA,EAEhB,YAAA,EAAc,CAAA,gBAAA,CAAA;AAAA;AAAA,EAEd,YAAA,EAAc,CAAA,UAAA,CAAA;AAAA;AAAA,EAEd,YAAA,EAAc,CAAA,eAAA;AAChB,CAAA;AAgBO,IAAM,YAAA,GAAN,MAAM,aAAA,SAAqB,KAAA,CAAM;AAAA,EAzExC;AAyEwC,IAAA,MAAA,CAAA,IAAA,EAAA,cAAA,CAAA;AAAA;AAAA;AAAA,EAEtB,SAAA;AAAA;AAAA,EAEA,UAAA;AAAA;AAAA,EAEA,SAAA;AAAA,EAEhB,WAAA,CACE,SAAA,EACA,OAAA,EACA,UAAA,EACA,WACA,KAAA,EACA;AACA,IAAA,KAAA,CAAM,CAAA,mBAAA,EAAsB,SAAS,CAAA,UAAA,EAAa,OAAO,CAAA,CAAE,CAAA;AAC3D,IAAA,IAAA,CAAK,IAAA,GAAO,cAAA;AACZ,IAAA,IAAA,CAAK,SAAA,GAAY,SAAA;AACjB,IAAA,IAAA,CAAK,UAAA,GAAa,UAAA;AAClB,IAAA,IAAA,CAAK,SAAA,GAAY,SAAA;AACjB,IAAA,IAAA,CAAK,KAAA,GAAQ,KAAA;AAEb,IAAA,IAAI,KAAA,CAAM,sBAAsB,MAAA,EAAW;AACzC,MAAA,KAAA,CAAM,iBAAA,CAAkB,MAAM,aAAY,CAAA;AAAA,IAC5C;AAAA,EACF;AACF;AAoDA,eAAe,WAAA,CACb,QAAA,EACA,SAAA,EACA,OAAA,EAKY;AACZ,EAAA,MAAM,EAAE,MAAA,GAAS,KAAA,EAAO,IAAA,EAAM,WAAU,GAAI,OAAA;AAE5C,EAAA,IAAI;AACF,IAAA,MAAM,WAAA,GAA2B;AAAA,MAC/B,MAAA;AAAA,MACA,OAAA,EAAS;AAAA,QACP,cAAA,EAAgB,kBAAA;AAAA,QAChB,MAAA,EAAQ;AAAA;AACV,KACF;AACA,IAAA,IAAI,SAAS,KAAA,CAAA,EAAW;AACtB,MAAA,WAAA,CAAY,IAAA,GAAO,IAAA,CAAK,SAAA,CAAU,IAAI,CAAA;AAAA,IACxC;AACA,IAAA,MAAM,QAAA,GAAW,MAAM,SAAA,CAAU,QAAA,EAAU,WAAW,CAAA;AAEtD,IAAA,MAAM,IAAA,GAAQ,MAAM,QAAA,CAAS,IAAA,EAAK;AAElC,IAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,MAAA,MAAM,SAAA,GAAY,IAAA;AAClB,MAAA,MAAM,OAAA,GACJ,SAAA,CAAU,KAAA,EAAO,OAAA,IAAW,SAAA,CAAU,WAAW,CAAA,KAAA,EAAQ,MAAA,CAAO,QAAA,CAAS,MAAM,CAAC,CAAA,CAAA;AAClF,MAAA,MAAM,IAAA,GAAO,SAAA,CAAU,KAAA,EAAO,IAAA,IAAQ,SAAA,CAAU,UAAA;AAChD,MAAA,MAAM,IAAI,YAAA,CAAa,SAAA,EAAW,OAAA,EAAS,QAAA,CAAS,QAAQ,IAAI,CAAA;AAAA,IAClE;AAEA,IAAA,OAAO,IAAA;AAAA,EACT,SAAS,KAAA,EAAO;AACd,IAAA,IAAI,iBAAiB,YAAA,EAAc;AACjC,MAAA,MAAM,KAAA;AAAA,IACR;AACA,IAAA,MAAM,IAAI,YAAA;AAAA,MACR,SAAA;AAAA,MACA,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,eAAA;AAAA,MACzC,MAAA;AAAA,MACA,MAAA;AAAA,MACA,KAAA,YAAiB,QAAQ,KAAA,GAAQ;AAAA,KACnC;AAAA,EACF;AACF;AA/Ce,MAAA,CAAA,WAAA,EAAA,aAAA,CAAA;AAkDf,SAAS,2BAA2B,GAAA,EAAkD;AACpF,EAAA,OAAO;AAAA,IACL,WAAW,GAAA,CAAI,UAAA;AAAA,IACf,QAAQ,GAAA,CAAI,MAAA;AAAA,IACZ,SAAS,GAAA,CAAI,OAAA;AAAA,IACb,iBAAiB,GAAA,CAAI,gBAAA;AAAA,IACrB,aAAa,GAAA,CAAI,YAAA;AAAA,IACjB,mBAAmB,GAAA,CAAI,kBAAA;AAAA,IACvB,oBAAoB,GAAA,CAAI,mBAAA;AAAA,IACxB,eAAe,GAAA,CAAI,cAAA;AAAA,IACnB,WAAW,GAAA,CAAI,UAAA;AAAA,IACf,WAAW,GAAA,CAAI;AAAA,GACjB;AACF;AAbS,MAAA,CAAA,0BAAA,EAAA,4BAAA,CAAA;AAkDF,SAAS,eAAA,CACd,MACA,IAAA,EACe;AACf,EAAA,MAAM,EAAE,aAAY,GAAI,IAAA;AACxB,EAAA,MAAM,SAAA,GAAY,IAAA,EAAM,KAAA,IAAS,UAAA,CAAW,KAAA;AAE5C,EAAA,IAAI,gBAAgB,EAAA,EAAI;AACtB,IAAA,MAAM,IAAI,YAAA,CAAa,gBAAA,EAAkB,wCAAwC,CAAA;AAAA,EACnF;AAEA,EAAA,MAAM,kBAAA,GAAqB,WAAA,CAAY,OAAA,CAAQ,KAAA,EAAO,EAAE,CAAA;AAGxD,EAAA,IAAI,aAAA,GAAgC,IAAA;AACpC,EAAA,IAAI,UAAA,GAA4C,IAAA;AAEhD,EAAA,eAAe,SAAA,GAA6C;AAC1D,IAAA,IAAI,eAAe,IAAA,EAAM;AACvB,MAAA,OAAO,UAAA;AAAA,IACT;AACA,IAAA,MAAM,WAAW,MAAM,WAAA;AAAA,MACrB,CAAA,EAAG,kBAAkB,CAAA,EAAG,SAAA,CAAU,YAAY,CAAA,CAAA;AAAA,MAC9C,SAAA;AAAA,MACA,EAAE,WAAW,gBAAA;AAAiB,KAChC;AACA,IAAA,UAAA,GAAa,QAAA;AACb,IAAA,aAAA,GAAgB,OAAA,CAAQ,SAAS,OAAO,CAAA;AACxC,IAAA,OAAO,QAAA;AAAA,EACT;AAZe,EAAA,MAAA,CAAA,SAAA,EAAA,WAAA,CAAA;AAcf,EAAA,OAAO;AAAA,IACL,WAAA,EAAa,kBAAA;AAAA,IAEb,MAAM,WAAA,GAAgC;AACpC,MAAA,IAAI,kBAAkB,IAAA,EAAM;AAC1B,QAAA,OAAO,aAAA;AAAA,MACT;AACA,MAAA,MAAM,IAAA,GAAO,MAAM,SAAA,EAAU;AAC7B,MAAA,OAAO,OAAA,CAAQ,KAAK,OAAO,CAAA;AAAA,IAC7B,CAAA;AAAA,IAEA,MAAM,iBAAA,GAAsC;AAC1C,MAAA,IAAI,kBAAkB,IAAA,EAAM;AAC1B,QAAA,OAAO,aAAA;AAAA,MACT;AACA,MAAA,MAAM,IAAA,GAAO,MAAM,SAAA,EAAU;AAC7B,MAAA,OAAO,OAAA,CAAQ,KAAK,OAAO,CAAA;AAAA,IAC7B,CAAA;AAAA,IAEA,MAAM,iBAAA,GAAqD;AACzD,MAAA,MAAM,IAAA,GAAO,MAAM,SAAA,EAAU;AAC7B,MAAA,OAAO;AAAA,QACL,SAAS,IAAA,CAAK,OAAA;AAAA,QACd,OAAO,IAAA,CAAK,eAAA;AAAA,QACZ,KAAA,EAAO,MAAA,CAAO,IAAA,CAAK,eAAA,CAAgB,MAAM;AAAA,OAC3C;AAAA,IACF,CAAA;AAAA,IAEA,MAAM,YAAY,OAAA,EAAqD;AACrE,MAAA,MAAM,WAAW,MAAM,WAAA;AAAA,QACrB,CAAA,EAAG,kBAAkB,CAAA,EAAG,SAAA,CAAU,YAAY,CAAA,CAAA;AAAA,QAC9C,SAAA;AAAA,QACA,EAAE,MAAA,EAAQ,MAAA,EAAQ,IAAA,EAAM,OAAA,EAAS,WAAW,aAAA;AAAc,OAC5D;AACA,MAAA,OAAO;AAAA,QACL,WAAW,QAAA,CAAS,UAAA;AAAA,QACpB,QAAQ,QAAA,CAAS;AAAA,OACnB;AAAA,IACF,CAAA;AAAA,IAEA,MAAM,gBAAgB,SAAA,EAAiD;AACrE,MAAA,MAAM,GAAA,GAAM,GAAG,kBAAkB,CAAA,EAAG,UAAU,YAAA,CAAa,OAAA,CAAQ,MAAA,EAAQ,SAAS,CAAC,CAAA,CAAA;AACrF,MAAA,MAAM,QAAA,GAAW,MAAM,WAAA,CAAoC,GAAA,EAAK,SAAA,EAAW;AAAA,QACzE,SAAA,EAAW;AAAA,OACZ,CAAA;AACD,MAAA,OAAO,2BAA2B,QAAQ,CAAA;AAAA,IAC5C;AAAA,GACF;AACF;AA/EgB,MAAA,CAAA,eAAA,EAAA,iBAAA,CAAA;AAyFhB,IAAM,uBAAA,uBAAwD,GAAA,CAAI;AAAA,EAChE,WAAA;AAAA,EACA,QAAA;AAAA,EACA;AACF,CAAC,CAAA;AAgBD,eAAsB,sBAAA,CACpB,eAAA,EACA,SAAA,EACA,OAAA,EAY2B;AAC3B,EAAA,MAAM,iBAAA,GAA4B,SAAS,iBAAA,IAAqB,GAAA;AAChE,EAAA,MAAM,SAAA,GAAoB,SAAS,SAAA,IAAa,IAAA;AAChD,EAAA,MAAM,aAAa,OAAA,EAAS,UAAA;AAE5B,EAAA,MAAM,SAAA,GAAoB,KAAK,GAAA,EAAI;AAGnC,EAAA,OAAO,IAAA,EAAM;AACX,IAAA,MAAM,MAAA,GAA8B,MAAM,eAAA,CAAgB,SAAS,CAAA;AAEnE,IAAA,IAAI,eAAe,MAAA,EAAW;AAC5B,MAAA,UAAA,CAAW;AAAA,QACT,WAAW,MAAA,CAAO,SAAA;AAAA,QAClB,QAAQ,MAAA,CAAO,MAAA;AAAA,QACf,iBAAiB,MAAA,CAAO,eAAA;AAAA,QACxB,aAAa,MAAA,CAAO,WAAA;AAAA,QACpB,mBAAmB,MAAA,CAAO,iBAAA;AAAA,QAC1B,eAAe,MAAA,CAAO;AAAA,OACvB,CAAA;AAAA,IACH;AAEA,IAAA,IAAI,uBAAA,CAAwB,GAAA,CAAI,MAAA,CAAO,MAAM,CAAA,EAAG;AAC9C,MAAA,MAAM,MAAA,GAA2B;AAAA,QAC/B,WAAW,MAAA,CAAO,SAAA;AAAA,QAClB,QAAQ,MAAA,CAAO,MAAA;AAAA,QACf,aAAa,MAAA,CAAO,WAAA;AAAA,QACpB,mBAAmB,MAAA,CAAO,iBAAA;AAAA,QAC1B,iBAAiB,MAAA,CAAO,eAAA;AAAA,QACxB,eAAe,MAAA,CAAO;AAAA,OACxB;AACA,MAAA,OAAO,MAAA;AAAA,IACT;AAEA,IAAA,IAAI,IAAA,CAAK,GAAA,EAAI,GAAI,SAAA,IAAa,SAAA,EAAW;AACvC,MAAA,MAAM,cAAA,GAAmC;AAAA,QACvC,WAAW,MAAA,CAAO,SAAA;AAAA,QAClB,MAAA,EAAQ,WAAA;AAAA,QACR,aAAA,EAAe,2BAA2B,MAAA,CAAO,SAAS,CAAC,CAAA,iBAAA,EAAoB,MAAA,CAAO,MAAA,CAAO,MAAM,CAAC,CAAA,CAAA;AAAA,OACtG;AACA,MAAA,OAAO,cAAA;AAAA,IACT;AAEA,IAAA,MAAM,IAAI,OAAA,CAAc,CAAC,OAAA,KAAY;AACnC,MAAA,UAAA,CAAW,SAAS,iBAAiB,CAAA;AAAA,IACvC,CAAC,CAAA;AAAA,EACH;AACF;AA9DsB,MAAA,CAAA,sBAAA,EAAA,wBAAA,CAAA","file":"chunk-4RHXVBNI.js","sourcesContent":["/**\n * Relayer Module (V2 API).\n *\n * @remarks\n * This module provides the `getUmbraRelayer` factory for creating relayer instances\n * that interact with the Umbra relayer's V2 API. The relayer builds, signs, and\n * submits claim transactions on behalf of users.\n *\n * **What is the Relayer?**\n * The Umbra relayer is a semi-trusted intermediary that submits privacy-preserving\n * transactions on behalf of users. It receives cryptographic data (ZK proofs,\n * nullifiers, linker encryptions) and builds all Solana transactions server-side.\n *\n * **Trust Model (Semi-Trusted):**\n * The relayer is SEMI-TRUSTED. It can observe transaction contents (amounts,\n * mints, timing) because it must broadcast them. However, it CANNOT:\n * - Steal funds — ZK proofs and nullifier commitments prevent double-spending\n * - Forge signatures — Transactions use cryptographic commitments verified on-chain\n * - Link sender to recipient — Merkle commitments and ZK proofs sever that link\n *\n * **API Endpoints Used:**\n * - `GET /v1/relayer/info` — Get relayer address, supported mints, active pools\n * - `POST /v1/claims` — Submit a claim request (relayer builds transactions)\n * - `GET /v1/claims/{id}` — Poll claim status\n *\n * @packageDocumentation\n */\n\nimport { address, type Address } from \"@solana/kit\";\nimport type { U32 } from \"../types\";\nimport type {\n IUmbraRelayer,\n GetUmbraRelayerArgs,\n GetUmbraRelayerDeps,\n SupportedMintsResponse,\n ClaimRequest,\n ClaimSubmitResponse,\n ClaimStatusResponse,\n ClaimStatus,\n ClaimBatchResult,\n} from \"./interfaces\";\n\n// ============================================================================\n// Constants\n// ============================================================================\n\n/**\n * Canonical endpoint paths for all relayer API operations.\n * @internal\n */\nconst ENDPOINTS = {\n /** Fetches relayer address, supported mints, and active stealth pool indices. */\n RELAYER_INFO: `/v1/relayer/info`,\n /** Submits a claim request (relayer builds transactions from crypto data). */\n CLAIM_SUBMIT: `/v1/claims`,\n /** Polls claim status by request ID. `{id}` is replaced at call time. */\n CLAIM_STATUS: `/v1/claims/{id}`,\n} as const;\n\n// ============================================================================\n// Error Class\n// ============================================================================\n\n/**\n * Error class for relayer-related failures.\n *\n * @remarks\n * Thrown when relayer API calls fail due to network issues, invalid responses,\n * transaction rejections, or server errors. Provides structured fields for\n * programmatic error handling.\n *\n * @public\n */\nexport class RelayerError extends Error {\n /** The relayer operation that failed (e.g. `\"getRelayerAddress\"`, `\"claimSubmit\"`). */\n public readonly operation: string;\n /** HTTP status code if the server responded, `undefined` for transport errors. */\n public readonly statusCode: number | undefined;\n /** Machine-readable error code from the API error body. */\n public readonly errorCode: string | undefined;\n\n constructor(\n operation: string,\n message: string,\n statusCode?: number,\n errorCode?: string,\n cause?: Error,\n ) {\n super(`Relayer operation '${operation}' failed: ${message}`);\n this.name = \"RelayerError\";\n this.operation = operation;\n this.statusCode = statusCode;\n this.errorCode = errorCode;\n this.cause = cause;\n\n if (Error.captureStackTrace !== undefined) {\n Error.captureStackTrace(this, RelayerError);\n }\n }\n}\n\n// ============================================================================\n// Internal Types (API Response Shapes)\n// ============================================================================\n\n/** @internal */\ninterface ApiErrorResponse {\n error?: {\n code: string;\n message: string;\n };\n success?: false;\n error_code?: string;\n message?: string;\n}\n\n/** Shape of `GET /v1/relayer/info` response. @internal */\ninterface ApiRelayerInfoResponse {\n address: string;\n supported_mints: string[];\n active_stealth_pool_indices: string[];\n}\n\n/** Shape of `POST /v1/claims` response. @internal */\ninterface ApiClaimSubmitResponse {\n request_id: string;\n status: \"received\";\n}\n\n/** Shape of `GET /v1/claims/{id}` response. @internal */\ninterface ApiClaimStatusResponse {\n request_id: string;\n status: string;\n variant: string;\n resolved_variant?: string;\n tx_signature?: string;\n callback_signature?: string;\n computation_account?: string;\n failure_reason?: string | null;\n created_at: string;\n updated_at: string;\n}\n\n// ============================================================================\n// Internal Helpers\n// ============================================================================\n\n/**\n * Generic HTTP request helper with structured error handling.\n * @internal\n */\nasync function makeRequest<T>(\n endpoint: string,\n fetchImpl: typeof globalThis.fetch,\n options: {\n method?: \"GET\" | \"POST\";\n body?: unknown;\n operation: string;\n },\n): Promise<T> {\n const { method = \"GET\", body, operation } = options;\n\n try {\n const requestInit: RequestInit = {\n method,\n headers: {\n \"Content-Type\": \"application/json\",\n Accept: \"application/json\",\n },\n };\n if (body !== undefined) {\n requestInit.body = JSON.stringify(body);\n }\n const response = await fetchImpl(endpoint, requestInit);\n\n const data = (await response.json()) as T | ApiErrorResponse;\n\n if (!response.ok) {\n const errorData = data as ApiErrorResponse;\n const message =\n errorData.error?.message ?? errorData.message ?? `HTTP ${String(response.status)}`;\n const code = errorData.error?.code ?? errorData.error_code;\n throw new RelayerError(operation, message, response.status, code);\n }\n\n return data as T;\n } catch (error) {\n if (error instanceof RelayerError) {\n throw error;\n }\n throw new RelayerError(\n operation,\n error instanceof Error ? error.message : \"Unknown error\",\n undefined,\n undefined,\n error instanceof Error ? error : undefined,\n );\n }\n}\n\n/** Converts wire-format claim status response to SDK type. @internal */\nfunction convertClaimStatusResponse(api: ApiClaimStatusResponse): ClaimStatusResponse {\n return {\n requestId: api.request_id,\n status: api.status as ClaimStatus,\n variant: api.variant as ClaimStatusResponse[\"variant\"],\n resolvedVariant: api.resolved_variant,\n txSignature: api.tx_signature,\n callbackSignature: api.callback_signature,\n computationAccount: api.computation_account,\n failureReason: api.failure_reason,\n createdAt: api.created_at,\n updatedAt: api.updated_at,\n };\n}\n\n// ============================================================================\n// Core Relayer Factory\n// ============================================================================\n\n/**\n * Creates an Umbra relayer instance.\n *\n * @remarks\n * The returned `IUmbraRelayer` object provides all methods needed by claim\n * services: relayer info, claim submission, and status polling. Pass it\n * directly as the `relayer` dependency to any claim function.\n *\n * **Address caching:**\n * `getRelayerAddress()` and `getFeePayer()` cache the result after the first\n * HTTP call. The cache is per-instance.\n *\n * @param args - Required arguments\n * @param args.apiEndpoint - The base URL of the relayer API\n * @param deps - Optional dependencies for testing\n * @param deps.fetch - Custom fetch implementation; defaults to `globalThis.fetch`\n * @returns An {@link IUmbraRelayer} instance\n *\n * @example\n * ```typescript\n * const relayer = getUmbraRelayer({ apiEndpoint: \"https://relayer.umbra.finance\" });\n *\n * // Use directly with claim functions\n * const claim = getSelfClaimableUtxoToEncryptedBalanceClaimerFunction(\n * { client },\n * { zkProver, relayer },\n * );\n * ```\n *\n * @public\n */\nexport function getUmbraRelayer(\n args: GetUmbraRelayerArgs,\n deps?: GetUmbraRelayerDeps,\n): IUmbraRelayer {\n const { apiEndpoint } = args;\n const fetchImpl = deps?.fetch ?? globalThis.fetch;\n\n if (apiEndpoint === \"\") {\n throw new RelayerError(\"initialization\", \"apiEndpoint must be a non-empty string\");\n }\n\n const normalizedEndpoint = apiEndpoint.replace(/\\/$/, \"\");\n\n // Shared cache for relayer address (used by both getFeePayer and getRelayerAddress)\n let cachedAddress: Address | null = null;\n let cachedInfo: ApiRelayerInfoResponse | null = null;\n\n async function fetchInfo(): Promise<ApiRelayerInfoResponse> {\n if (cachedInfo !== null) {\n return cachedInfo;\n }\n const response = await makeRequest<ApiRelayerInfoResponse>(\n `${normalizedEndpoint}${ENDPOINTS.RELAYER_INFO}`,\n fetchImpl,\n { operation: \"getRelayerInfo\" },\n );\n cachedInfo = response;\n cachedAddress = address(response.address);\n return response;\n }\n\n return {\n apiEndpoint: normalizedEndpoint,\n\n async getFeePayer(): Promise<Address> {\n if (cachedAddress !== null) {\n return cachedAddress;\n }\n const info = await fetchInfo();\n return address(info.address);\n },\n\n async getRelayerAddress(): Promise<Address> {\n if (cachedAddress !== null) {\n return cachedAddress;\n }\n const info = await fetchInfo();\n return address(info.address);\n },\n\n async getSupportedMints(): Promise<SupportedMintsResponse> {\n const info = await fetchInfo();\n return {\n relayer: info.address,\n mints: info.supported_mints,\n count: BigInt(info.supported_mints.length) as U32,\n };\n },\n\n async submitClaim(request: ClaimRequest): Promise<ClaimSubmitResponse> {\n const response = await makeRequest<ApiClaimSubmitResponse>(\n `${normalizedEndpoint}${ENDPOINTS.CLAIM_SUBMIT}`,\n fetchImpl,\n { method: \"POST\", body: request, operation: \"claimSubmit\" },\n );\n return {\n requestId: response.request_id,\n status: response.status,\n };\n },\n\n async pollClaimStatus(requestId: string): Promise<ClaimStatusResponse> {\n const url = `${normalizedEndpoint}${ENDPOINTS.CLAIM_STATUS.replace(\"{id}\", requestId)}`;\n const response = await makeRequest<ApiClaimStatusResponse>(url, fetchImpl, {\n operation: \"claimStatus\",\n });\n return convertClaimStatusResponse(response);\n },\n };\n}\n\n// ============================================================================\n// Claim Polling Utility\n// ============================================================================\n\n/**\n * Terminal claim statuses. Polling stops when the status matches one of these.\n * @internal\n */\nconst TERMINAL_CLAIM_STATUSES: ReadonlySet<ClaimStatus> = new Set([\n \"completed\",\n \"failed\",\n \"timed_out\",\n]);\n\n/**\n * Polls a claim request until it reaches a terminal status or times out.\n *\n * @remarks\n * Terminal statuses are: `completed`, `failed`, `timed_out`.\n * The `onProgress` callback is invoked after each poll with the latest status.\n *\n * @param pollClaimStatus - Function to poll claim status\n * @param requestId - The claim request ID to poll\n * @param options - Polling configuration\n * @returns The final {@link ClaimBatchResult}\n *\n * @public\n */\nexport async function pollClaimUntilTerminal(\n pollClaimStatus: (requestId: string) => Promise<ClaimStatusResponse>,\n requestId: string,\n options?: {\n pollingIntervalMs?: number;\n timeoutMs?: number;\n onProgress?: (event: {\n readonly requestId: string;\n readonly status: ClaimStatus;\n readonly resolvedVariant?: string;\n readonly txSignature?: string;\n readonly callbackSignature?: string;\n readonly failureReason?: string | null;\n }) => void;\n },\n): Promise<ClaimBatchResult> {\n const pollingIntervalMs: number = options?.pollingIntervalMs ?? 3000;\n const timeoutMs: number = options?.timeoutMs ?? 120_000;\n const onProgress = options?.onProgress;\n\n const startTime: number = Date.now();\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- polling loop\n while (true) {\n const status: ClaimStatusResponse = await pollClaimStatus(requestId);\n\n if (onProgress !== undefined) {\n onProgress({\n requestId: status.requestId,\n status: status.status,\n resolvedVariant: status.resolvedVariant,\n txSignature: status.txSignature,\n callbackSignature: status.callbackSignature,\n failureReason: status.failureReason,\n });\n }\n\n if (TERMINAL_CLAIM_STATUSES.has(status.status)) {\n const result: ClaimBatchResult = {\n requestId: status.requestId,\n status: status.status,\n txSignature: status.txSignature,\n callbackSignature: status.callbackSignature,\n resolvedVariant: status.resolvedVariant,\n failureReason: status.failureReason,\n };\n return result;\n }\n\n if (Date.now() - startTime >= timeoutMs) {\n const timedOutResult: ClaimBatchResult = {\n requestId: status.requestId,\n status: \"timed_out\" as ClaimStatus,\n failureReason: `Polling timed out after ${String(timeoutMs)}ms (last status: ${String(status.status)})`,\n };\n return timedOutResult;\n }\n\n await new Promise<void>((resolve) => {\n setTimeout(resolve, pollingIntervalMs);\n });\n }\n}\n"]}
|