@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 +41 -7
- package/dist/index.d.ts +41 -7
- package/dist/index.js +72 -4
- package/dist/index.mjs +70 -3
- package/package.json +1 -1
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
|
};
|