@adelos/sdk 0.1.10 → 0.1.12

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/dist/index.d.mts CHANGED
@@ -22,6 +22,20 @@ interface RegistryInfo {
22
22
  account: RegistryAccount;
23
23
  exists: boolean;
24
24
  }
25
+ /** Stealth transaction detected during scanning */
26
+ interface StealthTransaction {
27
+ signature: string;
28
+ blockTime: number | null;
29
+ stealthAddress: PublicKey;
30
+ amount: bigint;
31
+ /** Ephemeral public key from memo - needed for withdraw */
32
+ ephemeralPk: Uint8Array;
33
+ }
34
+ /** Stealth transaction ready for withdrawal */
35
+ interface WithdrawableTransaction extends StealthTransaction {
36
+ /** Recovered stealth secret key - used to sign withdraw tx */
37
+ stealthSecretKey: Uint8Array;
38
+ }
25
39
 
26
40
  type SolanaCluster = "devnet";
27
41
  declare const ADELOS_CONFIG: {
@@ -101,17 +115,17 @@ declare function generateStealthAddress(recipientMetaPk: Uint8Array): {
101
115
  sharedSecret: Uint8Array<ArrayBufferLike>;
102
116
  memo: string;
103
117
  };
118
+ /**
119
+ * Sign a message using a raw private SCALAR (not seed).
120
+ * Required because derived stealth keys are scalars, not seeds.
121
+ * Uses a random nonce for R, valid for Ed25519.
122
+ */
123
+ declare function signWithScalar(message: Uint8Array, scalarBytes: Uint8Array): Promise<Uint8Array>;
104
124
 
105
125
  /**
106
126
  * Adelos Indexer - Privacy-Preserving Transaction Scanner
107
127
  */
108
128
 
109
- interface StealthTransaction {
110
- signature: string;
111
- blockTime: number | null;
112
- stealthAddress: PublicKey;
113
- amount: bigint;
114
- }
115
129
  declare class AdelosIndexer {
116
130
  private connection;
117
131
  constructor(connection: Connection);
@@ -124,7 +138,12 @@ declare class AdelosIndexer {
124
138
  attemptDecryption(tx: ParsedTransactionWithMeta, metaSk: Uint8Array, metaPk: Uint8Array): {
125
139
  stealthAddress: PublicKey;
126
140
  amount: bigint;
141
+ ephemeralPk: Uint8Array;
127
142
  } | null;
143
+ /**
144
+ * Prepare a stealth transaction for withdrawal by recovering the secret key.
145
+ */
146
+ prepareWithdraw(stealthTx: StealthTransaction, metaSk: Uint8Array, metaPk: Uint8Array): WithdrawableTransaction;
128
147
  private extractMemo;
129
148
  }
130
149
  /** Helper for quick initialization */
@@ -147,9 +166,24 @@ declare class AdelosSDK {
147
166
  createRegisterTransaction(owner: PublicKey, metaPubkey: Uint8Array, version?: "legacy" | "v0"): Promise<Transaction | VersionedTransaction>;
148
167
  /** Membuat transaksi pembaruan identitas (jika sudah terdaftar) */
149
168
  createUpdateTransaction(owner: PublicKey, metaPubkey: Uint8Array, version?: "legacy" | "v0"): Promise<Transaction | VersionedTransaction>;
169
+ /**
170
+ * Create a withdraw transaction from stealth address to any destination.
171
+ * This enables both:
172
+ * - Withdraw to self (destination = user's main wallet)
173
+ * - Withdraw to any address (for enhanced privacy - no link to main wallet!)
174
+ *
175
+ * @param stealthSecretKey - The recovered stealth private key (from prepareWithdraw)
176
+ * @param stealthAddress - The stealth address holding the funds
177
+ * @param destination - Where to send the funds (can be ANY address)
178
+ * @param amountLamports - Amount to withdraw in lamports (use BigInt)
179
+ */
180
+ createWithdrawTransaction(stealthSecretKey: Uint8Array, stealthAddress: PublicKey, destination: PublicKey, amountLamports: bigint): Promise<{
181
+ transaction: VersionedTransaction;
182
+ signature: string;
183
+ }>;
150
184
  buildTransaction(payer: PublicKey, instructions: TransactionInstruction[], version?: "legacy" | "v0"): Promise<Transaction | VersionedTransaction>;
151
185
  /** Satu fungsi kirim untuk semua jenis transaksi (Legacy/V0) */
152
186
  sendAndConfirm(signedTx: Transaction | VersionedTransaction): Promise<string>;
153
187
  }
154
188
 
155
- export { ADELOS_CONFIG, AdelosIndexer, type AdelosOptions, AdelosSDK, MEMO_PREFIX, MEMO_PROGRAM_ID, PROGRAM_ID, REGISTRY_SEED, RPC_URL, type RegistryAccount, type RegistryInfo, STEALTH_DOMAIN, type SolanaCluster, type StealthTransaction, bytesToHex, computeSharedSecret, computeSharedSecretAsRecipient, createIndexer, derivePublicKey, deriveRegistryPda, deriveStealthPubkey, generateEphemeralKeypair, generateStealthAddress, generateStealthMemo, getDiscriminator, hexToBytes, isValidMetaPubkey, parseStealthMemo, recoverStealthSecretKey };
189
+ export { ADELOS_CONFIG, AdelosIndexer, type AdelosOptions, AdelosSDK, MEMO_PREFIX, MEMO_PROGRAM_ID, PROGRAM_ID, REGISTRY_SEED, RPC_URL, type RegistryAccount, type RegistryInfo, STEALTH_DOMAIN, type SolanaCluster, type StealthTransaction, type WithdrawableTransaction, bytesToHex, computeSharedSecret, computeSharedSecretAsRecipient, createIndexer, derivePublicKey, deriveRegistryPda, deriveStealthPubkey, generateEphemeralKeypair, generateStealthAddress, generateStealthMemo, getDiscriminator, hexToBytes, isValidMetaPubkey, parseStealthMemo, recoverStealthSecretKey, signWithScalar };
package/dist/index.d.ts CHANGED
@@ -22,6 +22,20 @@ interface RegistryInfo {
22
22
  account: RegistryAccount;
23
23
  exists: boolean;
24
24
  }
25
+ /** Stealth transaction detected during scanning */
26
+ interface StealthTransaction {
27
+ signature: string;
28
+ blockTime: number | null;
29
+ stealthAddress: PublicKey;
30
+ amount: bigint;
31
+ /** Ephemeral public key from memo - needed for withdraw */
32
+ ephemeralPk: Uint8Array;
33
+ }
34
+ /** Stealth transaction ready for withdrawal */
35
+ interface WithdrawableTransaction extends StealthTransaction {
36
+ /** Recovered stealth secret key - used to sign withdraw tx */
37
+ stealthSecretKey: Uint8Array;
38
+ }
25
39
 
26
40
  type SolanaCluster = "devnet";
27
41
  declare const ADELOS_CONFIG: {
@@ -101,17 +115,17 @@ declare function generateStealthAddress(recipientMetaPk: Uint8Array): {
101
115
  sharedSecret: Uint8Array<ArrayBufferLike>;
102
116
  memo: string;
103
117
  };
118
+ /**
119
+ * Sign a message using a raw private SCALAR (not seed).
120
+ * Required because derived stealth keys are scalars, not seeds.
121
+ * Uses a random nonce for R, valid for Ed25519.
122
+ */
123
+ declare function signWithScalar(message: Uint8Array, scalarBytes: Uint8Array): Promise<Uint8Array>;
104
124
 
105
125
  /**
106
126
  * Adelos Indexer - Privacy-Preserving Transaction Scanner
107
127
  */
108
128
 
109
- interface StealthTransaction {
110
- signature: string;
111
- blockTime: number | null;
112
- stealthAddress: PublicKey;
113
- amount: bigint;
114
- }
115
129
  declare class AdelosIndexer {
116
130
  private connection;
117
131
  constructor(connection: Connection);
@@ -124,7 +138,12 @@ declare class AdelosIndexer {
124
138
  attemptDecryption(tx: ParsedTransactionWithMeta, metaSk: Uint8Array, metaPk: Uint8Array): {
125
139
  stealthAddress: PublicKey;
126
140
  amount: bigint;
141
+ ephemeralPk: Uint8Array;
127
142
  } | null;
143
+ /**
144
+ * Prepare a stealth transaction for withdrawal by recovering the secret key.
145
+ */
146
+ prepareWithdraw(stealthTx: StealthTransaction, metaSk: Uint8Array, metaPk: Uint8Array): WithdrawableTransaction;
128
147
  private extractMemo;
129
148
  }
130
149
  /** Helper for quick initialization */
@@ -147,9 +166,24 @@ declare class AdelosSDK {
147
166
  createRegisterTransaction(owner: PublicKey, metaPubkey: Uint8Array, version?: "legacy" | "v0"): Promise<Transaction | VersionedTransaction>;
148
167
  /** Membuat transaksi pembaruan identitas (jika sudah terdaftar) */
149
168
  createUpdateTransaction(owner: PublicKey, metaPubkey: Uint8Array, version?: "legacy" | "v0"): Promise<Transaction | VersionedTransaction>;
169
+ /**
170
+ * Create a withdraw transaction from stealth address to any destination.
171
+ * This enables both:
172
+ * - Withdraw to self (destination = user's main wallet)
173
+ * - Withdraw to any address (for enhanced privacy - no link to main wallet!)
174
+ *
175
+ * @param stealthSecretKey - The recovered stealth private key (from prepareWithdraw)
176
+ * @param stealthAddress - The stealth address holding the funds
177
+ * @param destination - Where to send the funds (can be ANY address)
178
+ * @param amountLamports - Amount to withdraw in lamports (use BigInt)
179
+ */
180
+ createWithdrawTransaction(stealthSecretKey: Uint8Array, stealthAddress: PublicKey, destination: PublicKey, amountLamports: bigint): Promise<{
181
+ transaction: VersionedTransaction;
182
+ signature: string;
183
+ }>;
150
184
  buildTransaction(payer: PublicKey, instructions: TransactionInstruction[], version?: "legacy" | "v0"): Promise<Transaction | VersionedTransaction>;
151
185
  /** Satu fungsi kirim untuk semua jenis transaksi (Legacy/V0) */
152
186
  sendAndConfirm(signedTx: Transaction | VersionedTransaction): Promise<string>;
153
187
  }
154
188
 
155
- export { ADELOS_CONFIG, AdelosIndexer, type AdelosOptions, AdelosSDK, MEMO_PREFIX, MEMO_PROGRAM_ID, PROGRAM_ID, REGISTRY_SEED, RPC_URL, type RegistryAccount, type RegistryInfo, STEALTH_DOMAIN, type SolanaCluster, type StealthTransaction, bytesToHex, computeSharedSecret, computeSharedSecretAsRecipient, createIndexer, derivePublicKey, deriveRegistryPda, deriveStealthPubkey, generateEphemeralKeypair, generateStealthAddress, generateStealthMemo, getDiscriminator, hexToBytes, isValidMetaPubkey, parseStealthMemo, recoverStealthSecretKey };
189
+ export { ADELOS_CONFIG, AdelosIndexer, type AdelosOptions, AdelosSDK, MEMO_PREFIX, MEMO_PROGRAM_ID, PROGRAM_ID, REGISTRY_SEED, RPC_URL, type RegistryAccount, type RegistryInfo, STEALTH_DOMAIN, type SolanaCluster, type StealthTransaction, type WithdrawableTransaction, bytesToHex, computeSharedSecret, computeSharedSecretAsRecipient, createIndexer, derivePublicKey, deriveRegistryPda, deriveStealthPubkey, generateEphemeralKeypair, generateStealthAddress, generateStealthMemo, getDiscriminator, hexToBytes, isValidMetaPubkey, parseStealthMemo, recoverStealthSecretKey, signWithScalar };
package/dist/index.js CHANGED
@@ -53,7 +53,8 @@ __export(index_exports, {
53
53
  hexToBytes: () => hexToBytes,
54
54
  isValidMetaPubkey: () => isValidMetaPubkey,
55
55
  parseStealthMemo: () => parseStealthMemo,
56
- recoverStealthSecretKey: () => recoverStealthSecretKey
56
+ recoverStealthSecretKey: () => recoverStealthSecretKey,
57
+ signWithScalar: () => signWithScalar
57
58
  });
58
59
  module.exports = __toCommonJS(index_exports);
59
60
  var import_web33 = require("@solana/web3.js");
@@ -186,6 +187,27 @@ function generateStealthAddress(recipientMetaPk) {
186
187
  const memo = generateStealthMemo(ephemeralKeypair.publicKey);
187
188
  return { stealthPubkey, ephemeralKeypair, sharedSecret, memo };
188
189
  }
190
+ async function signWithScalar(message, scalarBytes) {
191
+ const scalar = toScalar(scalarBytes);
192
+ const pubPoint = ed.ExtendedPoint.BASE.multiply(scalar);
193
+ const pubBytes = pubPoint.toRawBytes();
194
+ const rBytes = ed.utils.randomPrivateKey();
195
+ const rScalar = toScalar(rBytes);
196
+ const R = ed.ExtendedPoint.BASE.multiply(rScalar);
197
+ const RBytes = R.toRawBytes();
198
+ const content = new Uint8Array(RBytes.length + pubBytes.length + message.length);
199
+ content.set(RBytes);
200
+ content.set(pubBytes, RBytes.length);
201
+ content.set(message, RBytes.length + pubBytes.length);
202
+ const hram = (0, import_sha512.sha512)(content);
203
+ const k = ed.etc.mod(BigInt("0x" + bytesToHex(hram)), ed.CURVE.n);
204
+ const S = ed.etc.mod(rScalar + k * scalar, ed.CURVE.n);
205
+ const SBytes = hexToBytes(S.toString(16).padStart(64, "0"));
206
+ const signature = new Uint8Array(64);
207
+ signature.set(RBytes);
208
+ signature.set(SBytes, 32);
209
+ return signature;
210
+ }
189
211
 
190
212
  // src/logger.ts
191
213
  var debugMode = false;
@@ -240,7 +262,8 @@ var AdelosIndexer = class {
240
262
  signature: s.signature,
241
263
  blockTime: tx.blockTime ?? null,
242
264
  stealthAddress: detected.stealthAddress,
243
- amount: detected.amount
265
+ amount: detected.amount,
266
+ ephemeralPk: detected.ephemeralPk
244
267
  });
245
268
  } else {
246
269
  log(` \u21B3 Not for this recipient`);
@@ -271,7 +294,19 @@ var AdelosIndexer = class {
271
294
  const change = BigInt(postBalances[idx] || 0) - BigInt(preBalances[idx] || 0);
272
295
  return {
273
296
  stealthAddress: accounts[idx].pubkey,
274
- amount: change > 0n ? change : 0n
297
+ amount: change > 0n ? change : 0n,
298
+ ephemeralPk
299
+ };
300
+ }
301
+ /**
302
+ * Prepare a stealth transaction for withdrawal by recovering the secret key.
303
+ */
304
+ prepareWithdraw(stealthTx, metaSk, metaPk) {
305
+ const sharedSecret = computeSharedSecretAsRecipient(metaSk, stealthTx.ephemeralPk);
306
+ const stealthSecretKey = recoverStealthSecretKey(metaSk, sharedSecret);
307
+ return {
308
+ ...stealthTx,
309
+ stealthSecretKey
275
310
  };
276
311
  }
277
312
  extractMemo(tx) {
@@ -371,6 +406,38 @@ var AdelosSDK = class {
371
406
  });
372
407
  return this.buildTransaction(owner, [ix], version);
373
408
  }
409
+ /**
410
+ * Create a withdraw transaction from stealth address to any destination.
411
+ * This enables both:
412
+ * - Withdraw to self (destination = user's main wallet)
413
+ * - Withdraw to any address (for enhanced privacy - no link to main wallet!)
414
+ *
415
+ * @param stealthSecretKey - The recovered stealth private key (from prepareWithdraw)
416
+ * @param stealthAddress - The stealth address holding the funds
417
+ * @param destination - Where to send the funds (can be ANY address)
418
+ * @param amountLamports - Amount to withdraw in lamports (use BigInt)
419
+ */
420
+ async createWithdrawTransaction(stealthSecretKey, stealthAddress, destination, amountLamports) {
421
+ const ix = import_web33.SystemProgram.transfer({
422
+ fromPubkey: stealthAddress,
423
+ toPubkey: destination,
424
+ lamports: amountLamports
425
+ });
426
+ const { blockhash } = await this.connection.getLatestBlockhash();
427
+ const message = new import_web33.TransactionMessage({
428
+ payerKey: stealthAddress,
429
+ // Stealth pays the fee
430
+ recentBlockhash: blockhash,
431
+ instructions: [ix]
432
+ }).compileToV0Message();
433
+ const tx = new import_web33.VersionedTransaction(message);
434
+ const serializedMessage = message.serialize();
435
+ const signature = await signWithScalar(serializedMessage, stealthSecretKey);
436
+ tx.addSignature(stealthAddress, Buffer.from(signature));
437
+ const sig = await this.connection.sendRawTransaction(tx.serialize());
438
+ await this.connection.confirmTransaction(sig, "confirmed");
439
+ return { transaction: tx, signature: sig };
440
+ }
374
441
  // --- 3. Core Engine (Internal Helpers) ---
375
442
  async buildTransaction(payer, instructions, version = "v0") {
376
443
  const { blockhash } = await this.connection.getLatestBlockhash();
@@ -420,5 +487,6 @@ var AdelosSDK = class {
420
487
  hexToBytes,
421
488
  isValidMetaPubkey,
422
489
  parseStealthMemo,
423
- recoverStealthSecretKey
490
+ recoverStealthSecretKey,
491
+ signWithScalar
424
492
  });
package/dist/index.mjs CHANGED
@@ -137,6 +137,27 @@ function generateStealthAddress(recipientMetaPk) {
137
137
  const memo = generateStealthMemo(ephemeralKeypair.publicKey);
138
138
  return { stealthPubkey, ephemeralKeypair, sharedSecret, memo };
139
139
  }
140
+ async function signWithScalar(message, scalarBytes) {
141
+ const scalar = toScalar(scalarBytes);
142
+ const pubPoint = ed.ExtendedPoint.BASE.multiply(scalar);
143
+ const pubBytes = pubPoint.toRawBytes();
144
+ const rBytes = ed.utils.randomPrivateKey();
145
+ const rScalar = toScalar(rBytes);
146
+ const R = ed.ExtendedPoint.BASE.multiply(rScalar);
147
+ const RBytes = R.toRawBytes();
148
+ const content = new Uint8Array(RBytes.length + pubBytes.length + message.length);
149
+ content.set(RBytes);
150
+ content.set(pubBytes, RBytes.length);
151
+ content.set(message, RBytes.length + pubBytes.length);
152
+ const hram = sha512(content);
153
+ const k = ed.etc.mod(BigInt("0x" + bytesToHex(hram)), ed.CURVE.n);
154
+ const S = ed.etc.mod(rScalar + k * scalar, ed.CURVE.n);
155
+ const SBytes = hexToBytes(S.toString(16).padStart(64, "0"));
156
+ const signature = new Uint8Array(64);
157
+ signature.set(RBytes);
158
+ signature.set(SBytes, 32);
159
+ return signature;
160
+ }
140
161
 
141
162
  // src/logger.ts
142
163
  var debugMode = false;
@@ -191,7 +212,8 @@ var AdelosIndexer = class {
191
212
  signature: s.signature,
192
213
  blockTime: tx.blockTime ?? null,
193
214
  stealthAddress: detected.stealthAddress,
194
- amount: detected.amount
215
+ amount: detected.amount,
216
+ ephemeralPk: detected.ephemeralPk
195
217
  });
196
218
  } else {
197
219
  log(` \u21B3 Not for this recipient`);
@@ -222,7 +244,19 @@ var AdelosIndexer = class {
222
244
  const change = BigInt(postBalances[idx] || 0) - BigInt(preBalances[idx] || 0);
223
245
  return {
224
246
  stealthAddress: accounts[idx].pubkey,
225
- amount: change > 0n ? change : 0n
247
+ amount: change > 0n ? change : 0n,
248
+ ephemeralPk
249
+ };
250
+ }
251
+ /**
252
+ * Prepare a stealth transaction for withdrawal by recovering the secret key.
253
+ */
254
+ prepareWithdraw(stealthTx, metaSk, metaPk) {
255
+ const sharedSecret = computeSharedSecretAsRecipient(metaSk, stealthTx.ephemeralPk);
256
+ const stealthSecretKey = recoverStealthSecretKey(metaSk, sharedSecret);
257
+ return {
258
+ ...stealthTx,
259
+ stealthSecretKey
226
260
  };
227
261
  }
228
262
  extractMemo(tx) {
@@ -322,6 +356,38 @@ var AdelosSDK = class {
322
356
  });
323
357
  return this.buildTransaction(owner, [ix], version);
324
358
  }
359
+ /**
360
+ * Create a withdraw transaction from stealth address to any destination.
361
+ * This enables both:
362
+ * - Withdraw to self (destination = user's main wallet)
363
+ * - Withdraw to any address (for enhanced privacy - no link to main wallet!)
364
+ *
365
+ * @param stealthSecretKey - The recovered stealth private key (from prepareWithdraw)
366
+ * @param stealthAddress - The stealth address holding the funds
367
+ * @param destination - Where to send the funds (can be ANY address)
368
+ * @param amountLamports - Amount to withdraw in lamports (use BigInt)
369
+ */
370
+ async createWithdrawTransaction(stealthSecretKey, stealthAddress, destination, amountLamports) {
371
+ const ix = SystemProgram.transfer({
372
+ fromPubkey: stealthAddress,
373
+ toPubkey: destination,
374
+ lamports: amountLamports
375
+ });
376
+ const { blockhash } = await this.connection.getLatestBlockhash();
377
+ const message = new TransactionMessage({
378
+ payerKey: stealthAddress,
379
+ // Stealth pays the fee
380
+ recentBlockhash: blockhash,
381
+ instructions: [ix]
382
+ }).compileToV0Message();
383
+ const tx = new VersionedTransaction(message);
384
+ const serializedMessage = message.serialize();
385
+ const signature = await signWithScalar(serializedMessage, stealthSecretKey);
386
+ tx.addSignature(stealthAddress, Buffer.from(signature));
387
+ const sig = await this.connection.sendRawTransaction(tx.serialize());
388
+ await this.connection.confirmTransaction(sig, "confirmed");
389
+ return { transaction: tx, signature: sig };
390
+ }
325
391
  // --- 3. Core Engine (Internal Helpers) ---
326
392
  async buildTransaction(payer, instructions, version = "v0") {
327
393
  const { blockhash } = await this.connection.getLatestBlockhash();
@@ -370,5 +436,6 @@ export {
370
436
  hexToBytes,
371
437
  isValidMetaPubkey,
372
438
  parseStealthMemo,
373
- recoverStealthSecretKey
439
+ recoverStealthSecretKey,
440
+ signWithScalar
374
441
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adelos/sdk",
3
- "version": "0.1.10",
3
+ "version": "0.1.12",
4
4
  "description": "Adelos Protocol SDK - Privacy Stealth Transfers on Solana",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",