nulltrace-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/README.md +254 -0
- package/dist/index.cjs +1084 -0
- package/dist/index.mjs +1074 -0
- package/package.json +57 -0
package/README.md
ADDED
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
# NullTrace SDK
|
|
2
|
+
|
|
3
|
+
Standalone JavaScript SDK for [NullTrace](https://nulltrace.app) — privacy-focused Solana transactions powered by Light Protocol ZK compression. No server needed.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install nulltrace-sdk @solana/web3.js @solana/spl-token @lightprotocol/stateless.js @lightprotocol/compressed-token
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
> A **Helius RPC endpoint** is required. ZK compression depends on Helius's photon indexer. Get a free key at [helius.dev](https://helius.dev).
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
```js
|
|
16
|
+
import { NullTrace } from 'nulltrace-sdk';
|
|
17
|
+
|
|
18
|
+
const nt = new NullTrace('https://mainnet.helius-rpc.com/?api-key=YOUR_KEY', wallet);
|
|
19
|
+
|
|
20
|
+
// Nullify 0.5 SOL (public -> private)
|
|
21
|
+
await nt.nullify('So11111111111111111111111111111111111111112', '0.5');
|
|
22
|
+
|
|
23
|
+
// Reveal 0.5 SOL (private -> public)
|
|
24
|
+
await nt.reveal('So11111111111111111111111111111111111111112', '0.5');
|
|
25
|
+
|
|
26
|
+
// Private transfer
|
|
27
|
+
await nt.transfer('So11111111111111111111111111111111111111112', '1.0', 'RecipientAddress...');
|
|
28
|
+
|
|
29
|
+
// Private swap SOL -> USDT
|
|
30
|
+
await nt.swap('So11111111111111111111111111111111111111112', 'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB', '1.0');
|
|
31
|
+
|
|
32
|
+
// Get all balances
|
|
33
|
+
const balances = await nt.getBalances();
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Constructor
|
|
37
|
+
|
|
38
|
+
```js
|
|
39
|
+
const nt = new NullTrace(rpcUrl, wallet);
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
| Param | Type | Description |
|
|
43
|
+
|-------|------|-------------|
|
|
44
|
+
| `rpcUrl` | `string` | **Helius** RPC endpoint (validated, throws if not Helius) |
|
|
45
|
+
| `walletOrKey` | see below | Wallet adapter, Keypair, secret key, or private key string |
|
|
46
|
+
|
|
47
|
+
The second argument is flexible — pass whatever you have:
|
|
48
|
+
|
|
49
|
+
### Option 1: Wallet Adapter (browser)
|
|
50
|
+
|
|
51
|
+
```js
|
|
52
|
+
// Works with Phantom, Solflare, or any Solana wallet adapter
|
|
53
|
+
const nt = new NullTrace(rpcUrl, wallet);
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Option 2: Keypair (Node.js)
|
|
57
|
+
|
|
58
|
+
```js
|
|
59
|
+
import { Keypair } from '@solana/web3.js';
|
|
60
|
+
|
|
61
|
+
const keypair = Keypair.fromSecretKey(mySecretKey);
|
|
62
|
+
const nt = new NullTrace(rpcUrl, keypair);
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Option 3: Secret Key bytes (Uint8Array)
|
|
66
|
+
|
|
67
|
+
```js
|
|
68
|
+
const secretKey = new Uint8Array([/* 64 bytes */]);
|
|
69
|
+
const nt = new NullTrace(rpcUrl, secretKey);
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Option 4: Base58 private key string
|
|
73
|
+
|
|
74
|
+
```js
|
|
75
|
+
// As exported by Phantom, Solflare, etc.
|
|
76
|
+
const nt = new NullTrace(rpcUrl, '4wBqpZM9...');
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
All four options produce identical functionality. Options 2–4 automatically create a full wallet interface (including `signMessage` for private balance lookups).
|
|
80
|
+
|
|
81
|
+
### Static factory methods
|
|
82
|
+
|
|
83
|
+
You can also build wallet adapters independently:
|
|
84
|
+
|
|
85
|
+
```js
|
|
86
|
+
const wallet = NullTrace.fromKeypair(keypair);
|
|
87
|
+
const wallet = NullTrace.fromSecretKey(uint8Array);
|
|
88
|
+
const wallet = NullTrace.fromPrivateKey('base58string...');
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## API Reference
|
|
94
|
+
|
|
95
|
+
### `nt.nullify(mint, amount)`
|
|
96
|
+
|
|
97
|
+
Convert public tokens into private ZK-compressed state.
|
|
98
|
+
|
|
99
|
+
```js
|
|
100
|
+
const sigs = await nt.nullify('So11111111111111111111111111111111111111112', '0.5');
|
|
101
|
+
// Returns: ['5xYk...', ...] (transaction signatures)
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### `nt.reveal(mint, amount)`
|
|
105
|
+
|
|
106
|
+
Decompress private tokens back to public state.
|
|
107
|
+
|
|
108
|
+
```js
|
|
109
|
+
const sigs = await nt.reveal('So11111111111111111111111111111111111111112', '0.5');
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### `nt.transfer(mint, amount, recipient)`
|
|
113
|
+
|
|
114
|
+
Send compressed tokens privately to another address.
|
|
115
|
+
|
|
116
|
+
```js
|
|
117
|
+
const sigs = await nt.transfer(
|
|
118
|
+
'So11111111111111111111111111111111111111112',
|
|
119
|
+
'1.0',
|
|
120
|
+
'7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU'
|
|
121
|
+
);
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### `nt.swap(fromMint, toMint, amount, options?)`
|
|
125
|
+
|
|
126
|
+
Execute a private swap via the NullTrace operator.
|
|
127
|
+
|
|
128
|
+
```js
|
|
129
|
+
const result = await nt.swap(
|
|
130
|
+
'So11111111111111111111111111111111111111112', // from SOL
|
|
131
|
+
'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB', // to USDT
|
|
132
|
+
'1.0'
|
|
133
|
+
);
|
|
134
|
+
console.log(result.status); // 'completed'
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
**Options:**
|
|
138
|
+
|
|
139
|
+
| Option | Type | Default | Description |
|
|
140
|
+
|--------|------|---------|-------------|
|
|
141
|
+
| `onStatusChange` | `(s) => void` | — | Called with 'signing', 'processing', 'completed' |
|
|
142
|
+
| `timeout` | `number` | `120000` | Max wait time in ms |
|
|
143
|
+
|
|
144
|
+
```js
|
|
145
|
+
// With status updates
|
|
146
|
+
await nt.swap(SOL, USDT, '1.0', {
|
|
147
|
+
onStatusChange: (status) => console.log('Status:', status),
|
|
148
|
+
});
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### `nt.quoteSwap(inputMint, outputMint, amount)`
|
|
152
|
+
|
|
153
|
+
Get a swap quote without executing.
|
|
154
|
+
|
|
155
|
+
```js
|
|
156
|
+
const quote = await nt.quoteSwap(
|
|
157
|
+
'So11111111111111111111111111111111111111112',
|
|
158
|
+
'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB',
|
|
159
|
+
'1.0'
|
|
160
|
+
);
|
|
161
|
+
console.log(`Output: ${quote.outAmount}, Impact: ${quote.priceImpact}%`);
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### `nt.getPublicBalances()`
|
|
165
|
+
|
|
166
|
+
Fetch on-chain token balances. No signing needed.
|
|
167
|
+
|
|
168
|
+
```js
|
|
169
|
+
const balances = await nt.getPublicBalances();
|
|
170
|
+
// [{ symbol: 'SOL', amount: '2.5', address: 'So11...', decimals: 9, ... }]
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### `nt.getPrivateBalances()`
|
|
174
|
+
|
|
175
|
+
Fetch ZK-compressed balances. Requires `wallet.signMessage` (prompted once, cached).
|
|
176
|
+
|
|
177
|
+
```js
|
|
178
|
+
const balances = await nt.getPrivateBalances();
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
### `nt.getBalances()`
|
|
182
|
+
|
|
183
|
+
Get all balances merged, with `publicAmount` and `privateAmount` fields.
|
|
184
|
+
|
|
185
|
+
```js
|
|
186
|
+
const all = await nt.getBalances();
|
|
187
|
+
for (const t of all) {
|
|
188
|
+
console.log(`${t.symbol}: ${t.publicAmount} public, ${t.privateAmount} private`);
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### `nt.getTokenMetadata(mint)`
|
|
193
|
+
|
|
194
|
+
Fetch token metadata (symbol, name, logo, decimals).
|
|
195
|
+
|
|
196
|
+
```js
|
|
197
|
+
const meta = await nt.getTokenMetadata('Es9vMFr...');
|
|
198
|
+
console.log(meta.symbol, meta.decimals); // 'USDT' 6
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### `nt.clearSignatureCache()`
|
|
202
|
+
|
|
203
|
+
Clear the cached message signature so the next private balance call re-prompts.
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
|
|
207
|
+
## Usage with React + Wallet Adapter
|
|
208
|
+
|
|
209
|
+
```jsx
|
|
210
|
+
import { useConnection, useWallet } from '@solana/wallet-adapter-react';
|
|
211
|
+
import { NullTrace } from 'nulltrace-sdk';
|
|
212
|
+
import { useMemo } from 'react';
|
|
213
|
+
|
|
214
|
+
function MyComponent() {
|
|
215
|
+
const wallet = useWallet();
|
|
216
|
+
|
|
217
|
+
const nt = useMemo(() => {
|
|
218
|
+
if (!wallet.publicKey) return null;
|
|
219
|
+
return new NullTrace('https://mainnet.helius-rpc.com/?api-key=YOUR_KEY', wallet);
|
|
220
|
+
}, [wallet.publicKey]);
|
|
221
|
+
|
|
222
|
+
const handleNullify = async () => {
|
|
223
|
+
const sigs = await nt.nullify('So11111111111111111111111111111111111111112', '0.5');
|
|
224
|
+
console.log('Done:', sigs);
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
return <button onClick={handleNullify}>Nullify 0.5 SOL</button>;
|
|
228
|
+
}
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
## Usage with Node.js
|
|
232
|
+
|
|
233
|
+
```js
|
|
234
|
+
import { Keypair } from '@solana/web3.js';
|
|
235
|
+
import { NullTrace } from 'nulltrace-sdk';
|
|
236
|
+
|
|
237
|
+
// Pass a Keypair directly — no manual wallet wiring needed
|
|
238
|
+
const nt = new NullTrace(
|
|
239
|
+
'https://mainnet.helius-rpc.com/?api-key=YOUR_KEY',
|
|
240
|
+
Keypair.fromSecretKey(mySecretKey)
|
|
241
|
+
);
|
|
242
|
+
|
|
243
|
+
// Or use a base58 private key string (as exported by Phantom)
|
|
244
|
+
// const nt = new NullTrace(rpcUrl, '4wBqpZM9k...');
|
|
245
|
+
|
|
246
|
+
const balances = await nt.getBalances();
|
|
247
|
+
console.log(balances);
|
|
248
|
+
|
|
249
|
+
await nt.nullify('So11111111111111111111111111111111111111112', '0.5');
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
## License
|
|
253
|
+
|
|
254
|
+
MIT — [NullTrace](https://nulltrace.app)
|