@umbra-privacy/sdk 1.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/LICENSE +21 -0
- package/README.md +122 -0
- package/dist/addresses-Brzgurv_.d.ts +145 -0
- package/dist/addresses-D_0YAS6B.d.cts +145 -0
- package/dist/chunk-2Q75CQQJ.js +12 -0
- package/dist/chunk-2Q75CQQJ.js.map +1 -0
- package/dist/chunk-7QVYU63E.js +6 -0
- package/dist/chunk-7QVYU63E.js.map +1 -0
- package/dist/chunk-BM7N6N7E.js +1883 -0
- package/dist/chunk-BM7N6N7E.js.map +1 -0
- package/dist/chunk-GXKSUB2U.cjs +4416 -0
- package/dist/chunk-GXKSUB2U.cjs.map +1 -0
- package/dist/chunk-HOEXDXRC.cjs +792 -0
- package/dist/chunk-HOEXDXRC.cjs.map +1 -0
- package/dist/chunk-MDFSBU5W.cjs +2033 -0
- package/dist/chunk-MDFSBU5W.cjs.map +1 -0
- package/dist/chunk-MQY7HDIA.js +600 -0
- package/dist/chunk-MQY7HDIA.js.map +1 -0
- package/dist/chunk-MVKTV3FT.cjs +20 -0
- package/dist/chunk-MVKTV3FT.cjs.map +1 -0
- package/dist/chunk-PG2J6V6Y.js +4094 -0
- package/dist/chunk-PG2J6V6Y.js.map +1 -0
- package/dist/chunk-PK6SKIKE.cjs +8 -0
- package/dist/chunk-PK6SKIKE.cjs.map +1 -0
- package/dist/chunk-VEGLTTYQ.cjs +621 -0
- package/dist/chunk-VEGLTTYQ.cjs.map +1 -0
- package/dist/chunk-WVHQ46DD.js +758 -0
- package/dist/chunk-WVHQ46DD.js.map +1 -0
- package/dist/constants/index.cjs +316 -0
- package/dist/constants/index.cjs.map +1 -0
- package/dist/constants/index.d.cts +739 -0
- package/dist/constants/index.d.ts +739 -0
- package/dist/constants/index.js +193 -0
- package/dist/constants/index.js.map +1 -0
- package/dist/cryptography-BTGC72u-.d.cts +4809 -0
- package/dist/cryptography-BTGC72u-.d.ts +4809 -0
- package/dist/errors/index.cjs +141 -0
- package/dist/errors/index.cjs.map +1 -0
- package/dist/errors/index.d.cts +1415 -0
- package/dist/errors/index.d.ts +1415 -0
- package/dist/errors/index.js +4 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/index-B9pDY73x.d.ts +12933 -0
- package/dist/index-CLj_zWSD.d.ts +235 -0
- package/dist/index-CX6_pIRS.d.cts +235 -0
- package/dist/index-D33yo0qB.d.cts +12933 -0
- package/dist/index.cjs +22464 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +11694 -0
- package/dist/index.d.ts +11694 -0
- package/dist/index.js +22314 -0
- package/dist/index.js.map +1 -0
- package/dist/interfaces/index.cjs +4 -0
- package/dist/interfaces/index.cjs.map +1 -0
- package/dist/interfaces/index.d.cts +8 -0
- package/dist/interfaces/index.d.ts +8 -0
- package/dist/interfaces/index.js +3 -0
- package/dist/interfaces/index.js.map +1 -0
- package/dist/networks-C-orpSFW.d.ts +65 -0
- package/dist/networks-FxYERGD1.d.cts +65 -0
- package/dist/types/index.cjs +605 -0
- package/dist/types/index.cjs.map +1 -0
- package/dist/types/index.d.cts +1853 -0
- package/dist/types/index.d.ts +1853 -0
- package/dist/types/index.js +4 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types-BBuELtY8.d.cts +495 -0
- package/dist/types-n-sHFcgr.d.ts +495 -0
- package/dist/utils/index.cjs +1295 -0
- package/dist/utils/index.cjs.map +1 -0
- package/dist/utils/index.d.cts +9559 -0
- package/dist/utils/index.d.ts +9559 -0
- package/dist/utils/index.js +6 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/versions-D9PqsEvj.d.cts +173 -0
- package/dist/versions-D9PqsEvj.d.ts +173 -0
- package/package.json +151 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Umbra Privacy
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# @umbra-privacy/sdk
|
|
2
|
+
|
|
3
|
+
TypeScript SDK for the Umbra privacy protocol on Solana. Provides encrypted balances, anonymous transfers via an on-chain mixer, and full compliance tooling.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pnpm add @umbra-privacy/sdk
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
import {
|
|
15
|
+
createInMemorySigner,
|
|
16
|
+
getUmbraClientFromSigner,
|
|
17
|
+
getUserRegistrationFunction,
|
|
18
|
+
getDirectDepositIntoEncryptedBalanceFunction,
|
|
19
|
+
getDirectWithdrawIntoPublicBalanceV3Function,
|
|
20
|
+
} from "@umbra-privacy/sdk";
|
|
21
|
+
|
|
22
|
+
// 1. Create a signer (use a wallet adapter in production)
|
|
23
|
+
const signer = await createInMemorySigner();
|
|
24
|
+
|
|
25
|
+
// 2. Create the Umbra client
|
|
26
|
+
const client = await getUmbraClientFromSigner({
|
|
27
|
+
signer,
|
|
28
|
+
network: "mainnet",
|
|
29
|
+
rpcUrl: "https://api.mainnet-beta.solana.com",
|
|
30
|
+
rpcSubscriptionsUrl: "wss://api.mainnet-beta.solana.com",
|
|
31
|
+
indexerApiEndpoint: "https://acqzie0a1h.execute-api.eu-central-1.amazonaws.com",
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
// 3. Register (idempotent — safe to call even if already registered)
|
|
35
|
+
const register = getUserRegistrationFunction({ client });
|
|
36
|
+
await register({ confidential: true, anonymous: true });
|
|
37
|
+
|
|
38
|
+
// 4. Deposit tokens into an encrypted balance
|
|
39
|
+
const deposit = getDirectDepositIntoEncryptedBalanceFunction({ client });
|
|
40
|
+
const MINT = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"; // USDC
|
|
41
|
+
await deposit(signer.address, MINT, 1_000_000n);
|
|
42
|
+
|
|
43
|
+
// 5. Withdraw back to public wallet
|
|
44
|
+
const withdraw = getDirectWithdrawIntoPublicBalanceV3Function({ client });
|
|
45
|
+
await withdraw(signer.address, MINT, 1_000_000n);
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Features
|
|
49
|
+
|
|
50
|
+
- **Encrypted Balances** — Deposit SPL / Token-2022 tokens into on-chain encrypted accounts. Withdraw back to a public wallet at any time.
|
|
51
|
+
- **Anonymous Transfers (Mixer)** — Create UTXOs in an Indexed Merkle Tree. Recipients claim with a Groth16 ZK proof, breaking any on-chain link to the sender.
|
|
52
|
+
- **Compliance** — Master viewing key hierarchy and X25519 compliance grants for authorized auditors.
|
|
53
|
+
- **Branded Types** — Runtime-validated `U64`, `U128`, `U256`, `Address`, `X25519PublicKey`, and other branded types prevent accidental misuse of cryptographic values.
|
|
54
|
+
- **Dual Module Format** — Ships ESM and CommonJS bundles with full TypeScript declarations.
|
|
55
|
+
|
|
56
|
+
## Entry Points
|
|
57
|
+
|
|
58
|
+
The SDK provides granular subpath exports to keep bundle sizes small:
|
|
59
|
+
|
|
60
|
+
- `@umbra-privacy/sdk` — Client construction, service factories, cryptographic operations
|
|
61
|
+
- `@umbra-privacy/sdk/types` — Branded types and assertion functions (`assertU64`, `assertAddress`, etc.)
|
|
62
|
+
- `@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
|
+
- `@umbra-privacy/sdk/constants` — Network configs, program IDs, domain separators
|
|
65
|
+
- `@umbra-privacy/sdk/errors` — Error classes, stage enums, and type guards
|
|
66
|
+
|
|
67
|
+
## Service Factory Pattern
|
|
68
|
+
|
|
69
|
+
Every SDK operation follows the same two-step pattern:
|
|
70
|
+
|
|
71
|
+
```typescript
|
|
72
|
+
// Build the function once (captures client config and optional dependency overrides)
|
|
73
|
+
const operation = getOperationFunction({ client }, optionalDeps);
|
|
74
|
+
|
|
75
|
+
// Call it at runtime
|
|
76
|
+
const result = await operation(/* runtime arguments */);
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
The optional `deps` argument accepts injectable overrides for RPC providers, key generators, and ZK provers — useful for unit testing or custom infrastructure.
|
|
80
|
+
|
|
81
|
+
## Available Services
|
|
82
|
+
|
|
83
|
+
- **Registration** — `getUserRegistrationFunction` — Account init, X25519 key registration, anonymous usage setup
|
|
84
|
+
- **Deposit** — `getDirectDepositIntoEncryptedBalanceFunction` — Shield tokens into encrypted accounts
|
|
85
|
+
- **Withdraw** — `getDirectWithdrawIntoPublicBalanceV3Function` — Unshield tokens back to public wallets
|
|
86
|
+
- **UTXO Creation** — `getCreateSelfClaimableUtxoFromPublicBalanceFunction`, `getCreateReceiverClaimableUtxoFromPublicBalanceFunction`, and encrypted-balance variants
|
|
87
|
+
- **UTXO Fetching** — `getFetchClaimableUtxosFunction` — Scan Merkle trees for UTXOs addressed to your keys
|
|
88
|
+
- **UTXO Claiming** — `getClaimSelfClaimableUtxoIntoEncryptedBalanceFunction`, `getClaimReceiverClaimableUtxoIntoEncryptedBalanceFunction`, and public-balance variants
|
|
89
|
+
- **Query** — `getQueryUserAccountFunction`, `getQueryEncryptedBalanceFunction` — Read on-chain state
|
|
90
|
+
- **Conversion** — `getConvertToSharedEncryptionFunction`, `getRotateMintX25519EncryptionKeyFunction`
|
|
91
|
+
- **Compliance** — `getCreateUserGrantedComplianceGrantFunction`, `getDeleteUserGrantedComplianceGrantFunction`, re-encryption operations
|
|
92
|
+
|
|
93
|
+
## ZK Provers
|
|
94
|
+
|
|
95
|
+
UTXO creation and claim operations require a Groth16 prover. Install the companion package for browser-based proving:
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
pnpm add @umbra-privacy/web-zk-prover
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
```typescript
|
|
102
|
+
import { getCreateReceiverClaimableUtxoFromPublicBalanceProver } from "@umbra-privacy/web-zk-prover";
|
|
103
|
+
|
|
104
|
+
const zkProver = getCreateReceiverClaimableUtxoFromPublicBalanceProver();
|
|
105
|
+
const createUtxo = getCreateReceiverClaimableUtxoFromPublicBalanceFunction(
|
|
106
|
+
{ client },
|
|
107
|
+
{ zkProver },
|
|
108
|
+
);
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Requirements
|
|
112
|
+
|
|
113
|
+
- Node.js 18+
|
|
114
|
+
- Solana RPC endpoint
|
|
115
|
+
|
|
116
|
+
## Documentation
|
|
117
|
+
|
|
118
|
+
Full documentation at [docs.umbraprivacy.com](https://docs.umbraprivacy.com).
|
|
119
|
+
|
|
120
|
+
## License
|
|
121
|
+
|
|
122
|
+
MIT
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { Address } from '@solana/kit';
|
|
2
|
+
import { U as U128 } from './cryptography-BTGC72u-.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Address Utilities
|
|
6
|
+
*
|
|
7
|
+
* This module provides utility functions for working with Solana public-key
|
|
8
|
+
* addresses in the context of zero-knowledge proof circuits used by the Umbra
|
|
9
|
+
* protocol.
|
|
10
|
+
*
|
|
11
|
+
* ## Problem Statement
|
|
12
|
+
*
|
|
13
|
+
* Solana addresses are 32-byte (256-bit) values. BN254-based ZK circuits
|
|
14
|
+
* (used by Groth16) operate over a scalar field whose prime is slightly less
|
|
15
|
+
* than 254 bits, making it impossible to represent a full 256-bit address in a
|
|
16
|
+
* single field element. To work around this, the SDK splits each address into
|
|
17
|
+
* two 128-bit halves that each fit comfortably within the BN254 field.
|
|
18
|
+
*
|
|
19
|
+
* ## Split Convention
|
|
20
|
+
*
|
|
21
|
+
* Given a 32-byte address `A`:
|
|
22
|
+
*
|
|
23
|
+
* ```
|
|
24
|
+
* low = little-endian U128 of bytes A[0..15]
|
|
25
|
+
* high = little-endian U128 of bytes A[16..31]
|
|
26
|
+
* ```
|
|
27
|
+
*
|
|
28
|
+
* The original value can be reconstructed as:
|
|
29
|
+
* ```
|
|
30
|
+
* address_value = (high << 128) | low
|
|
31
|
+
* ```
|
|
32
|
+
*
|
|
33
|
+
* This convention is used consistently across Circom circuit inputs, on-chain
|
|
34
|
+
* Poseidon hash calls, and the TypeScript SDK.
|
|
35
|
+
*
|
|
36
|
+
* @packageDocumentation
|
|
37
|
+
* @module utils/miscellaneous/addresses
|
|
38
|
+
*/
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Result of splitting a 32-byte Solana address into two 128-bit halves.
|
|
42
|
+
*
|
|
43
|
+
* Both halves are unsigned 128-bit integers interpreted from their respective
|
|
44
|
+
* byte ranges in little-endian order. Together they represent the full 256-bit
|
|
45
|
+
* address and can be passed independently as BN254 field element inputs to
|
|
46
|
+
* Poseidon hash functions or Groth16 circuit public inputs.
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```typescript
|
|
50
|
+
* import { splitAddressToLowHigh } from "@umbra-privacy/sdk";
|
|
51
|
+
* import { address } from "@solana/kit";
|
|
52
|
+
*
|
|
53
|
+
* const { low, high } = splitAddressToLowHigh(
|
|
54
|
+
* address("So11111111111111111111111111111111111111112"),
|
|
55
|
+
* );
|
|
56
|
+
*
|
|
57
|
+
* // Pass both halves as separate field elements to a Poseidon hash
|
|
58
|
+
* const digest = await poseidonHash([masterViewingKey, low, high]);
|
|
59
|
+
* ```
|
|
60
|
+
*
|
|
61
|
+
* @see {@link splitAddressToLowHigh} for the function that produces this result
|
|
62
|
+
* @public
|
|
63
|
+
*/
|
|
64
|
+
interface AddressSplitResult {
|
|
65
|
+
/**
|
|
66
|
+
* Lower 128 bits of the address.
|
|
67
|
+
*
|
|
68
|
+
* Derived by taking bytes 0–15 of the 32-byte address encoding and
|
|
69
|
+
* interpreting them as a little-endian 128-bit unsigned integer.
|
|
70
|
+
*
|
|
71
|
+
* @readonly
|
|
72
|
+
*/
|
|
73
|
+
readonly low: U128;
|
|
74
|
+
/**
|
|
75
|
+
* Upper 128 bits of the address.
|
|
76
|
+
*
|
|
77
|
+
* Derived by taking bytes 16–31 of the 32-byte address encoding and
|
|
78
|
+
* interpreting them as a little-endian 128-bit unsigned integer.
|
|
79
|
+
*
|
|
80
|
+
* @readonly
|
|
81
|
+
*/
|
|
82
|
+
readonly high: U128;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Splits a 32-byte Solana address into two little-endian 128-bit unsigned
|
|
86
|
+
* integers for use as BN254 circuit inputs.
|
|
87
|
+
*
|
|
88
|
+
* Solana addresses are 256-bit public keys. The BN254 scalar field used by
|
|
89
|
+
* Groth16 circuits cannot hold a full 256-bit value in a single field element,
|
|
90
|
+
* so addresses must be split into two 128-bit halves before being hashed or
|
|
91
|
+
* supplied as circuit public inputs. This function performs that split using
|
|
92
|
+
* the little-endian convention that matches the Umbra Circom circuit
|
|
93
|
+
* definitions.
|
|
94
|
+
*
|
|
95
|
+
* ## Algorithm
|
|
96
|
+
*
|
|
97
|
+
* 1. Encode `address` to its canonical 32-byte representation using
|
|
98
|
+
* `@solana/kit`'s address encoder.
|
|
99
|
+
* 2. Slice bytes 0–15; interpret them as a little-endian `U128` → `low`.
|
|
100
|
+
* 3. Slice bytes 16–31; interpret them as a little-endian `U128` → `high`.
|
|
101
|
+
* 4. Return `{ low, high }`.
|
|
102
|
+
*
|
|
103
|
+
* ## Reconstruction
|
|
104
|
+
*
|
|
105
|
+
* The original 256-bit address integer can be recovered as:
|
|
106
|
+
* ```
|
|
107
|
+
* address_value = (high << 128n) | low
|
|
108
|
+
* ```
|
|
109
|
+
*
|
|
110
|
+
* This reconstruction is used by the on-chain Poseidon hash and the Circom
|
|
111
|
+
* circuits to verify that a claimed address matches the committed value.
|
|
112
|
+
*
|
|
113
|
+
* @param address - A Solana `Address` (base-58 encoded 32-byte public key).
|
|
114
|
+
* The value must be a valid Solana address; the encoder will throw if the
|
|
115
|
+
* input is malformed.
|
|
116
|
+
* @returns An {@link AddressSplitResult} containing the `low` and `high`
|
|
117
|
+
* 128-bit halves of the address, each expressed as a branded {@link U128}.
|
|
118
|
+
*
|
|
119
|
+
* @example
|
|
120
|
+
* ```typescript
|
|
121
|
+
* import { splitAddressToLowHigh } from "@umbra-privacy/sdk";
|
|
122
|
+
* import { address } from "@solana/kit";
|
|
123
|
+
*
|
|
124
|
+
* const mintAddress = address("So11111111111111111111111111111111111111112");
|
|
125
|
+
* const { low, high } = splitAddressToLowHigh(mintAddress);
|
|
126
|
+
*
|
|
127
|
+
* // Supply both halves as independent BN254 field elements in a Poseidon hash
|
|
128
|
+
* const viewingKeyForMint = await poseidonHash([masterViewingKey, low, high]);
|
|
129
|
+
* ```
|
|
130
|
+
*
|
|
131
|
+
* @example
|
|
132
|
+
* ```typescript
|
|
133
|
+
* // Reconstruct the original 256-bit address value from the split result
|
|
134
|
+
* const { low, high } = splitAddressToLowHigh(someAddress);
|
|
135
|
+
* const fullValue = (BigInt(high) << 128n) | BigInt(low);
|
|
136
|
+
* ```
|
|
137
|
+
*
|
|
138
|
+
* @see {@link AddressSplitResult} for the returned type
|
|
139
|
+
* @see {@link createU128LeBytes} for the byte-slice branding step
|
|
140
|
+
* @see {@link decodeU128LeBytesToU128} for the little-endian decode step
|
|
141
|
+
* @public
|
|
142
|
+
*/
|
|
143
|
+
declare function splitAddressToLowHigh(address: Address): AddressSplitResult;
|
|
144
|
+
|
|
145
|
+
export { type AddressSplitResult as A, splitAddressToLowHigh as s };
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { Address } from '@solana/kit';
|
|
2
|
+
import { U as U128 } from './cryptography-BTGC72u-.cjs';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Address Utilities
|
|
6
|
+
*
|
|
7
|
+
* This module provides utility functions for working with Solana public-key
|
|
8
|
+
* addresses in the context of zero-knowledge proof circuits used by the Umbra
|
|
9
|
+
* protocol.
|
|
10
|
+
*
|
|
11
|
+
* ## Problem Statement
|
|
12
|
+
*
|
|
13
|
+
* Solana addresses are 32-byte (256-bit) values. BN254-based ZK circuits
|
|
14
|
+
* (used by Groth16) operate over a scalar field whose prime is slightly less
|
|
15
|
+
* than 254 bits, making it impossible to represent a full 256-bit address in a
|
|
16
|
+
* single field element. To work around this, the SDK splits each address into
|
|
17
|
+
* two 128-bit halves that each fit comfortably within the BN254 field.
|
|
18
|
+
*
|
|
19
|
+
* ## Split Convention
|
|
20
|
+
*
|
|
21
|
+
* Given a 32-byte address `A`:
|
|
22
|
+
*
|
|
23
|
+
* ```
|
|
24
|
+
* low = little-endian U128 of bytes A[0..15]
|
|
25
|
+
* high = little-endian U128 of bytes A[16..31]
|
|
26
|
+
* ```
|
|
27
|
+
*
|
|
28
|
+
* The original value can be reconstructed as:
|
|
29
|
+
* ```
|
|
30
|
+
* address_value = (high << 128) | low
|
|
31
|
+
* ```
|
|
32
|
+
*
|
|
33
|
+
* This convention is used consistently across Circom circuit inputs, on-chain
|
|
34
|
+
* Poseidon hash calls, and the TypeScript SDK.
|
|
35
|
+
*
|
|
36
|
+
* @packageDocumentation
|
|
37
|
+
* @module utils/miscellaneous/addresses
|
|
38
|
+
*/
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Result of splitting a 32-byte Solana address into two 128-bit halves.
|
|
42
|
+
*
|
|
43
|
+
* Both halves are unsigned 128-bit integers interpreted from their respective
|
|
44
|
+
* byte ranges in little-endian order. Together they represent the full 256-bit
|
|
45
|
+
* address and can be passed independently as BN254 field element inputs to
|
|
46
|
+
* Poseidon hash functions or Groth16 circuit public inputs.
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```typescript
|
|
50
|
+
* import { splitAddressToLowHigh } from "@umbra-privacy/sdk";
|
|
51
|
+
* import { address } from "@solana/kit";
|
|
52
|
+
*
|
|
53
|
+
* const { low, high } = splitAddressToLowHigh(
|
|
54
|
+
* address("So11111111111111111111111111111111111111112"),
|
|
55
|
+
* );
|
|
56
|
+
*
|
|
57
|
+
* // Pass both halves as separate field elements to a Poseidon hash
|
|
58
|
+
* const digest = await poseidonHash([masterViewingKey, low, high]);
|
|
59
|
+
* ```
|
|
60
|
+
*
|
|
61
|
+
* @see {@link splitAddressToLowHigh} for the function that produces this result
|
|
62
|
+
* @public
|
|
63
|
+
*/
|
|
64
|
+
interface AddressSplitResult {
|
|
65
|
+
/**
|
|
66
|
+
* Lower 128 bits of the address.
|
|
67
|
+
*
|
|
68
|
+
* Derived by taking bytes 0–15 of the 32-byte address encoding and
|
|
69
|
+
* interpreting them as a little-endian 128-bit unsigned integer.
|
|
70
|
+
*
|
|
71
|
+
* @readonly
|
|
72
|
+
*/
|
|
73
|
+
readonly low: U128;
|
|
74
|
+
/**
|
|
75
|
+
* Upper 128 bits of the address.
|
|
76
|
+
*
|
|
77
|
+
* Derived by taking bytes 16–31 of the 32-byte address encoding and
|
|
78
|
+
* interpreting them as a little-endian 128-bit unsigned integer.
|
|
79
|
+
*
|
|
80
|
+
* @readonly
|
|
81
|
+
*/
|
|
82
|
+
readonly high: U128;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Splits a 32-byte Solana address into two little-endian 128-bit unsigned
|
|
86
|
+
* integers for use as BN254 circuit inputs.
|
|
87
|
+
*
|
|
88
|
+
* Solana addresses are 256-bit public keys. The BN254 scalar field used by
|
|
89
|
+
* Groth16 circuits cannot hold a full 256-bit value in a single field element,
|
|
90
|
+
* so addresses must be split into two 128-bit halves before being hashed or
|
|
91
|
+
* supplied as circuit public inputs. This function performs that split using
|
|
92
|
+
* the little-endian convention that matches the Umbra Circom circuit
|
|
93
|
+
* definitions.
|
|
94
|
+
*
|
|
95
|
+
* ## Algorithm
|
|
96
|
+
*
|
|
97
|
+
* 1. Encode `address` to its canonical 32-byte representation using
|
|
98
|
+
* `@solana/kit`'s address encoder.
|
|
99
|
+
* 2. Slice bytes 0–15; interpret them as a little-endian `U128` → `low`.
|
|
100
|
+
* 3. Slice bytes 16–31; interpret them as a little-endian `U128` → `high`.
|
|
101
|
+
* 4. Return `{ low, high }`.
|
|
102
|
+
*
|
|
103
|
+
* ## Reconstruction
|
|
104
|
+
*
|
|
105
|
+
* The original 256-bit address integer can be recovered as:
|
|
106
|
+
* ```
|
|
107
|
+
* address_value = (high << 128n) | low
|
|
108
|
+
* ```
|
|
109
|
+
*
|
|
110
|
+
* This reconstruction is used by the on-chain Poseidon hash and the Circom
|
|
111
|
+
* circuits to verify that a claimed address matches the committed value.
|
|
112
|
+
*
|
|
113
|
+
* @param address - A Solana `Address` (base-58 encoded 32-byte public key).
|
|
114
|
+
* The value must be a valid Solana address; the encoder will throw if the
|
|
115
|
+
* input is malformed.
|
|
116
|
+
* @returns An {@link AddressSplitResult} containing the `low` and `high`
|
|
117
|
+
* 128-bit halves of the address, each expressed as a branded {@link U128}.
|
|
118
|
+
*
|
|
119
|
+
* @example
|
|
120
|
+
* ```typescript
|
|
121
|
+
* import { splitAddressToLowHigh } from "@umbra-privacy/sdk";
|
|
122
|
+
* import { address } from "@solana/kit";
|
|
123
|
+
*
|
|
124
|
+
* const mintAddress = address("So11111111111111111111111111111111111111112");
|
|
125
|
+
* const { low, high } = splitAddressToLowHigh(mintAddress);
|
|
126
|
+
*
|
|
127
|
+
* // Supply both halves as independent BN254 field elements in a Poseidon hash
|
|
128
|
+
* const viewingKeyForMint = await poseidonHash([masterViewingKey, low, high]);
|
|
129
|
+
* ```
|
|
130
|
+
*
|
|
131
|
+
* @example
|
|
132
|
+
* ```typescript
|
|
133
|
+
* // Reconstruct the original 256-bit address value from the split result
|
|
134
|
+
* const { low, high } = splitAddressToLowHigh(someAddress);
|
|
135
|
+
* const fullValue = (BigInt(high) << 128n) | BigInt(low);
|
|
136
|
+
* ```
|
|
137
|
+
*
|
|
138
|
+
* @see {@link AddressSplitResult} for the returned type
|
|
139
|
+
* @see {@link createU128LeBytes} for the byte-slice branding step
|
|
140
|
+
* @see {@link decodeU128LeBytesToU128} for the little-endian decode step
|
|
141
|
+
* @public
|
|
142
|
+
*/
|
|
143
|
+
declare function splitAddressToLowHigh(address: Address): AddressSplitResult;
|
|
144
|
+
|
|
145
|
+
export { type AddressSplitResult as A, splitAddressToLowHigh as s };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// src/constants/arcium.ts
|
|
2
|
+
var ARCIUM_MXE_ACCOUNT_SEED = "MXEAccount";
|
|
3
|
+
var ARCIUM_MEMPOOL_SEED = "Mempool";
|
|
4
|
+
var ARCIUM_EXEC_POOL_SEED = "Execpool";
|
|
5
|
+
var ARCIUM_COMPUTATION_SEED = "ComputationAccount";
|
|
6
|
+
var ARCIUM_COMP_DEF_SEED = "ComputationDefinitionAccount";
|
|
7
|
+
var ARCIUM_CLUSTER_SEED = "Cluster";
|
|
8
|
+
var ARCIUM_OFFSET_BUFFER_SIZE = 4;
|
|
9
|
+
|
|
10
|
+
export { ARCIUM_CLUSTER_SEED, ARCIUM_COMPUTATION_SEED, ARCIUM_COMP_DEF_SEED, ARCIUM_EXEC_POOL_SEED, ARCIUM_MEMPOOL_SEED, ARCIUM_MXE_ACCOUNT_SEED, ARCIUM_OFFSET_BUFFER_SIZE };
|
|
11
|
+
//# sourceMappingURL=chunk-2Q75CQQJ.js.map
|
|
12
|
+
//# sourceMappingURL=chunk-2Q75CQQJ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/constants/arcium.ts"],"names":[],"mappings":";AAeO,IAAM,uBAAA,GAA0B;AAQhC,IAAM,mBAAA,GAAsB;AAQ5B,IAAM,qBAAA,GAAwB;AAQ9B,IAAM,uBAAA,GAA0B;AAQhC,IAAM,oBAAA,GAAuB;AAQ7B,IAAM,mBAAA,GAAsB;AAQ5B,IAAM,yBAAA,GAA4B","file":"chunk-2Q75CQQJ.js","sourcesContent":["/**\n * Arcium Protocol Constants\n *\n * This module contains constants for interacting with the Arcium protocol,\n * including the program address and PDA seed prefixes for various account types.\n *\n * @module constants/arcium\n */\n\n/**\n * Seed prefix for MXE account PDAs.\n *\n * @remarks\n * Used to derive the MXE account address for a given program.\n */\nexport const ARCIUM_MXE_ACCOUNT_SEED = \"MXEAccount\";\n\n/**\n * Seed prefix for mempool account PDAs.\n *\n * @remarks\n * The mempool stores pending computations for a cluster.\n */\nexport const ARCIUM_MEMPOOL_SEED = \"Mempool\";\n\n/**\n * Seed prefix for executing pool account PDAs.\n *\n * @remarks\n * The executing pool tracks computations currently being processed.\n */\nexport const ARCIUM_EXEC_POOL_SEED = \"Execpool\";\n\n/**\n * Seed prefix for computation account PDAs.\n *\n * @remarks\n * Each computation gets its own account to track state and results.\n */\nexport const ARCIUM_COMPUTATION_SEED = \"ComputationAccount\";\n\n/**\n * Seed prefix for computation definition account PDAs.\n *\n * @remarks\n * Computation definitions describe the circuit/program to be executed.\n */\nexport const ARCIUM_COMP_DEF_SEED = \"ComputationDefinitionAccount\";\n\n/**\n * Seed prefix for cluster account PDAs.\n *\n * @remarks\n * Clusters are groups of MXE nodes that process computations together.\n */\nexport const ARCIUM_CLUSTER_SEED = \"Cluster\";\n\n/**\n * Buffer size for cluster/computation offsets in bytes.\n *\n * @remarks\n * Offsets are encoded as 4-byte little-endian unsigned integers.\n */\nexport const ARCIUM_OFFSET_BUFFER_SIZE = 4;\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"chunk-7QVYU63E.js"}
|