nulltrace-sdk 1.0.3 → 1.0.5
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.cjs +152 -117
- package/dist/index.mjs +33 -21
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -33,16 +33,43 @@ __export(src_exports, {
|
|
|
33
33
|
default: () => src_default
|
|
34
34
|
});
|
|
35
35
|
module.exports = __toCommonJS(src_exports);
|
|
36
|
-
var
|
|
37
|
-
var
|
|
38
|
-
var
|
|
39
|
-
var
|
|
36
|
+
var web3 = __toESM(require("@solana/web3.js"), 1);
|
|
37
|
+
var splToken = __toESM(require("@solana/spl-token"), 1);
|
|
38
|
+
var stateless = __toESM(require("@lightprotocol/stateless.js"), 1);
|
|
39
|
+
var compressedToken = __toESM(require("@lightprotocol/compressed-token"), 1);
|
|
40
40
|
var import_bs58 = __toESM(require("bs58"), 1);
|
|
41
41
|
var import_crypto = require("crypto");
|
|
42
42
|
var import_tweetnacl = __toESM(require("tweetnacl"), 1);
|
|
43
|
+
var {
|
|
44
|
+
VersionedTransaction,
|
|
45
|
+
PublicKey,
|
|
46
|
+
TransactionMessage,
|
|
47
|
+
ComputeBudgetProgram,
|
|
48
|
+
Keypair
|
|
49
|
+
} = web3;
|
|
50
|
+
var {
|
|
51
|
+
TOKEN_PROGRAM_ID,
|
|
52
|
+
TOKEN_2022_PROGRAM_ID,
|
|
53
|
+
getAssociatedTokenAddress,
|
|
54
|
+
createAssociatedTokenAccountInstruction,
|
|
55
|
+
createTransferCheckedInstruction,
|
|
56
|
+
NATIVE_MINT
|
|
57
|
+
} = splToken;
|
|
58
|
+
var {
|
|
59
|
+
createRpc,
|
|
60
|
+
bn,
|
|
61
|
+
LightSystemProgram,
|
|
62
|
+
COMPRESSED_TOKEN_PROGRAM_ID,
|
|
63
|
+
selectStateTreeInfo
|
|
64
|
+
} = stateless;
|
|
65
|
+
var {
|
|
66
|
+
getTokenPoolInfos,
|
|
67
|
+
selectTokenPoolInfosForDecompression,
|
|
68
|
+
CompressedTokenProgram
|
|
69
|
+
} = compressedToken;
|
|
43
70
|
var OPERATOR_KEY = "5STUuhrL8kJ4up9spEY39VJ6ibQCFrg8x8cRV5UeEcfv";
|
|
44
|
-
var OPERATOR_PUBLIC_KEY = new
|
|
45
|
-
var ALT_ADDRESS = new
|
|
71
|
+
var OPERATOR_PUBLIC_KEY = new PublicKey(OPERATOR_KEY);
|
|
72
|
+
var ALT_ADDRESS = new PublicKey("9NYFyEqPkyXUhkerbGHXUXkvb4qpzeEdHuGpgbgpH1NJ");
|
|
46
73
|
var REMOTE_OPERATOR_URL = "http://34.68.76.183:3333";
|
|
47
74
|
var SHARED_SECRET = "NULL_TRACE_OPERATOR_SECRET_BASE_V1";
|
|
48
75
|
var FEE_BPS = 1e-3;
|
|
@@ -78,19 +105,19 @@ function _sleep(ms) {
|
|
|
78
105
|
return new Promise((r) => setTimeout(r, ms));
|
|
79
106
|
}
|
|
80
107
|
async function _getMintInfo(connection, mintAddress) {
|
|
81
|
-
if (mintAddress ===
|
|
82
|
-
return { decimals: 9, tokenProgram:
|
|
108
|
+
if (mintAddress === NATIVE_MINT.toBase58()) {
|
|
109
|
+
return { decimals: 9, tokenProgram: TOKEN_PROGRAM_ID };
|
|
83
110
|
}
|
|
84
|
-
const mintInfo = await connection.getParsedAccountInfo(new
|
|
111
|
+
const mintInfo = await connection.getParsedAccountInfo(new PublicKey(mintAddress));
|
|
85
112
|
if (!mintInfo.value)
|
|
86
113
|
throw new Error(`Mint not found: ${mintAddress}`);
|
|
87
114
|
return {
|
|
88
115
|
decimals: mintInfo.value.data.parsed.info.decimals,
|
|
89
|
-
tokenProgram: new
|
|
116
|
+
tokenProgram: new PublicKey(mintInfo.value.owner)
|
|
90
117
|
};
|
|
91
118
|
}
|
|
92
119
|
async function _getCompressedAccounts(connection, owner, mint, isSOL) {
|
|
93
|
-
const accounts = isSOL ? await connection.getCompressedAccountsByOwner(owner) : await connection.getCompressedTokenAccountsByOwner(owner, { mint: new
|
|
120
|
+
const accounts = isSOL ? await connection.getCompressedAccountsByOwner(owner) : await connection.getCompressedTokenAccountsByOwner(owner, { mint: new PublicKey(mint) });
|
|
94
121
|
return accounts.items.sort((a, b) => {
|
|
95
122
|
const aAmt = isSOL ? a.lamports : a.parsed.amount;
|
|
96
123
|
const bAmt = isSOL ? b.lamports : b.parsed.amount;
|
|
@@ -122,15 +149,15 @@ function _batchAccounts(accounts) {
|
|
|
122
149
|
async function _packTransactions(connection, payer, instructions, adl) {
|
|
123
150
|
const { blockhash } = await connection.getLatestBlockhash();
|
|
124
151
|
const computeIxs = [
|
|
125
|
-
|
|
126
|
-
|
|
152
|
+
ComputeBudgetProgram.setComputeUnitLimit({ units: COMPUTE_UNITS }),
|
|
153
|
+
ComputeBudgetProgram.setComputeUnitPrice({ microLamports: COMPUTE_PRICE })
|
|
127
154
|
];
|
|
128
155
|
let current = [...computeIxs];
|
|
129
156
|
const messages = [];
|
|
130
157
|
for (const ix of instructions) {
|
|
131
158
|
try {
|
|
132
159
|
current.push(ix);
|
|
133
|
-
const msg = new
|
|
160
|
+
const msg = new TransactionMessage({
|
|
134
161
|
payerKey: payer,
|
|
135
162
|
recentBlockhash: blockhash,
|
|
136
163
|
instructions: current
|
|
@@ -141,7 +168,7 @@ async function _packTransactions(connection, payer, instructions, adl) {
|
|
|
141
168
|
current.pop();
|
|
142
169
|
if (current.length > computeIxs.length) {
|
|
143
170
|
messages.push(
|
|
144
|
-
new
|
|
171
|
+
new TransactionMessage({
|
|
145
172
|
payerKey: payer,
|
|
146
173
|
recentBlockhash: blockhash,
|
|
147
174
|
instructions: current
|
|
@@ -153,20 +180,22 @@ async function _packTransactions(connection, payer, instructions, adl) {
|
|
|
153
180
|
}
|
|
154
181
|
if (current.length > computeIxs.length) {
|
|
155
182
|
messages.push(
|
|
156
|
-
new
|
|
183
|
+
new TransactionMessage({
|
|
157
184
|
payerKey: payer,
|
|
158
185
|
recentBlockhash: blockhash,
|
|
159
186
|
instructions: current
|
|
160
187
|
}).compileToV0Message([adl])
|
|
161
188
|
);
|
|
162
189
|
}
|
|
163
|
-
return messages.map((m) => new
|
|
190
|
+
return messages.map((m) => new VersionedTransaction(m));
|
|
164
191
|
}
|
|
165
192
|
async function _signSendConfirm(connection, wallet, transactions) {
|
|
166
193
|
const signed = await wallet.signAllTransactions(transactions);
|
|
167
194
|
const sigs = [];
|
|
168
195
|
for (const tx of signed) {
|
|
169
|
-
const sig = await connection.sendRawTransaction(tx.serialize()
|
|
196
|
+
const sig = await connection.sendRawTransaction(tx.serialize(), {
|
|
197
|
+
skipPreflight: true
|
|
198
|
+
});
|
|
170
199
|
await connection.confirmTransaction(sig);
|
|
171
200
|
sigs.push(sig);
|
|
172
201
|
}
|
|
@@ -279,7 +308,7 @@ var NullTrace = class _NullTrace {
|
|
|
279
308
|
throw new Error("NullTrace: a wallet, Keypair, secret key, or private key string is required");
|
|
280
309
|
this.rpcUrl = rpcUrl;
|
|
281
310
|
this.wallet = _NullTrace._resolveWallet(walletOrKey);
|
|
282
|
-
this.connection =
|
|
311
|
+
this.connection = createRpc(rpcUrl, rpcUrl, rpcUrl, { commitment: "processed" });
|
|
283
312
|
this._adlCache = null;
|
|
284
313
|
this._sigCache = null;
|
|
285
314
|
}
|
|
@@ -296,14 +325,17 @@ var NullTrace = class _NullTrace {
|
|
|
296
325
|
if (!keypair?.publicKey || !keypair?.secretKey) {
|
|
297
326
|
throw new Error("NullTrace.fromKeypair: invalid Keypair");
|
|
298
327
|
}
|
|
328
|
+
const secretKeyBytes = new Uint8Array(keypair.secretKey);
|
|
329
|
+
const internalKeypair = Keypair.fromSecretKey(secretKeyBytes);
|
|
330
|
+
const pubkey = internalKeypair.publicKey;
|
|
299
331
|
return {
|
|
300
|
-
publicKey:
|
|
332
|
+
publicKey: pubkey,
|
|
301
333
|
signAllTransactions: async (txs) => {
|
|
302
334
|
for (const tx of txs)
|
|
303
|
-
tx.sign([
|
|
335
|
+
tx.sign([internalKeypair]);
|
|
304
336
|
return txs;
|
|
305
337
|
},
|
|
306
|
-
signMessage: async (msg) => import_tweetnacl.default.sign.detached(msg,
|
|
338
|
+
signMessage: async (msg) => import_tweetnacl.default.sign.detached(msg, secretKeyBytes)
|
|
307
339
|
};
|
|
308
340
|
}
|
|
309
341
|
/**
|
|
@@ -313,10 +345,10 @@ var NullTrace = class _NullTrace {
|
|
|
313
345
|
* @returns {{ publicKey: PublicKey, signAllTransactions: Function, signMessage: Function }}
|
|
314
346
|
*/
|
|
315
347
|
static fromSecretKey(secretKey) {
|
|
316
|
-
if (!
|
|
348
|
+
if (!secretKey || typeof secretKey.length !== "number" || secretKey.length !== 64) {
|
|
317
349
|
throw new Error("NullTrace.fromSecretKey: expected a 64-byte Uint8Array");
|
|
318
350
|
}
|
|
319
|
-
return _NullTrace.fromKeypair(
|
|
351
|
+
return _NullTrace.fromKeypair(Keypair.fromSecretKey(new Uint8Array(secretKey)));
|
|
320
352
|
}
|
|
321
353
|
/**
|
|
322
354
|
* Create a wallet adapter interface from a base58-encoded private key string.
|
|
@@ -329,19 +361,20 @@ var NullTrace = class _NullTrace {
|
|
|
329
361
|
throw new Error("NullTrace.fromPrivateKey: expected a base58-encoded private key string");
|
|
330
362
|
}
|
|
331
363
|
const decoded = import_bs58.default.decode(base58Key);
|
|
332
|
-
return _NullTrace.fromKeypair(
|
|
364
|
+
return _NullTrace.fromKeypair(Keypair.fromSecretKey(decoded));
|
|
333
365
|
}
|
|
334
366
|
/**
|
|
335
367
|
* @internal Resolve any supported wallet input into a wallet adapter interface.
|
|
368
|
+
* Uses duck-typing instead of instanceof to avoid cross-realm module boundary issues.
|
|
336
369
|
*/
|
|
337
370
|
static _resolveWallet(input) {
|
|
338
371
|
if (input?.publicKey && typeof input.signAllTransactions === "function") {
|
|
339
372
|
return input;
|
|
340
373
|
}
|
|
341
|
-
if (input
|
|
374
|
+
if (input?.publicKey?.toBytes && input?.secretKey?.length === 64) {
|
|
342
375
|
return _NullTrace.fromKeypair(input);
|
|
343
376
|
}
|
|
344
|
-
if (input
|
|
377
|
+
if (typeof input !== "string" && input?.length === 64 && typeof input[0] === "number") {
|
|
345
378
|
return _NullTrace.fromSecretKey(input);
|
|
346
379
|
}
|
|
347
380
|
if (typeof input === "string") {
|
|
@@ -376,22 +409,22 @@ var NullTrace = class _NullTrace {
|
|
|
376
409
|
if (!mint || !amount)
|
|
377
410
|
throw new Error("NullTrace.nullify: mint and amount are required");
|
|
378
411
|
const owner = this.wallet.publicKey;
|
|
379
|
-
const isSOL = mint ===
|
|
412
|
+
const isSOL = mint === NATIVE_MINT.toBase58();
|
|
380
413
|
const { decimals, tokenProgram } = await _getMintInfo(this.connection, mint);
|
|
381
|
-
const amountLamports =
|
|
382
|
-
const feeLamports =
|
|
414
|
+
const amountLamports = bn(Math.floor(parseFloat(amount) * 10 ** decimals).toString());
|
|
415
|
+
const feeLamports = bn(Math.floor(parseInt(amountLamports.toString()) * FEE_BPS).toString());
|
|
383
416
|
const ixs = [];
|
|
384
417
|
const activeStateTrees = await this.connection.getStateTreeInfos();
|
|
385
|
-
const tree =
|
|
418
|
+
const tree = selectStateTreeInfo(activeStateTrees);
|
|
386
419
|
if (isSOL) {
|
|
387
420
|
ixs.push(
|
|
388
|
-
await
|
|
421
|
+
await LightSystemProgram.compress({
|
|
389
422
|
payer: owner,
|
|
390
423
|
toAddress: owner,
|
|
391
424
|
lamports: amountLamports.sub(feeLamports),
|
|
392
425
|
outputStateTreeInfo: tree
|
|
393
426
|
}),
|
|
394
|
-
await
|
|
427
|
+
await LightSystemProgram.compress({
|
|
395
428
|
payer: owner,
|
|
396
429
|
toAddress: OPERATOR_PUBLIC_KEY,
|
|
397
430
|
lamports: feeLamports,
|
|
@@ -399,16 +432,16 @@ var NullTrace = class _NullTrace {
|
|
|
399
432
|
})
|
|
400
433
|
);
|
|
401
434
|
} else {
|
|
402
|
-
const mintPk = new
|
|
403
|
-
const sourceAta = await
|
|
404
|
-
const [tokenPoolPda] =
|
|
435
|
+
const mintPk = new PublicKey(mint);
|
|
436
|
+
const sourceAta = await getAssociatedTokenAddress(mintPk, owner, false, tokenProgram);
|
|
437
|
+
const [tokenPoolPda] = PublicKey.findProgramAddressSync(
|
|
405
438
|
[Buffer.from("pool"), mintPk.toBuffer()],
|
|
406
|
-
|
|
439
|
+
COMPRESSED_TOKEN_PROGRAM_ID
|
|
407
440
|
);
|
|
408
441
|
const poolInfo = await this.connection.getAccountInfo(tokenPoolPda);
|
|
409
442
|
if (!poolInfo) {
|
|
410
443
|
ixs.push(
|
|
411
|
-
await
|
|
444
|
+
await CompressedTokenProgram.createTokenPool({
|
|
412
445
|
feePayer: owner,
|
|
413
446
|
mint: mintPk,
|
|
414
447
|
tokenProgramId: tokenProgram
|
|
@@ -416,7 +449,7 @@ var NullTrace = class _NullTrace {
|
|
|
416
449
|
);
|
|
417
450
|
}
|
|
418
451
|
ixs.push(
|
|
419
|
-
await
|
|
452
|
+
await CompressedTokenProgram.compress({
|
|
420
453
|
payer: owner,
|
|
421
454
|
owner,
|
|
422
455
|
source: sourceAta,
|
|
@@ -428,7 +461,7 @@ var NullTrace = class _NullTrace {
|
|
|
428
461
|
tokenPoolPda,
|
|
429
462
|
tokenProgram,
|
|
430
463
|
isInitialized: true,
|
|
431
|
-
balance:
|
|
464
|
+
balance: bn("0"),
|
|
432
465
|
poolIndex: 0,
|
|
433
466
|
mint: mintPk
|
|
434
467
|
}
|
|
@@ -456,7 +489,7 @@ var NullTrace = class _NullTrace {
|
|
|
456
489
|
if (!mint || !amount)
|
|
457
490
|
throw new Error("NullTrace.reveal: mint and amount are required");
|
|
458
491
|
const owner = this.wallet.publicKey;
|
|
459
|
-
const isSOL = mint ===
|
|
492
|
+
const isSOL = mint === NATIVE_MINT.toBase58();
|
|
460
493
|
const { decimals, tokenProgram } = await _getMintInfo(this.connection, mint);
|
|
461
494
|
const amountLamports = Math.floor(parseFloat(amount) * 10 ** decimals);
|
|
462
495
|
const sorted = await _getCompressedAccounts(this.connection, owner, mint, isSOL);
|
|
@@ -468,12 +501,12 @@ var NullTrace = class _NullTrace {
|
|
|
468
501
|
let selectedTokenPoolInfos;
|
|
469
502
|
let destinationAta;
|
|
470
503
|
if (!isSOL) {
|
|
471
|
-
const tokenPoolInfos = await
|
|
472
|
-
selectedTokenPoolInfos =
|
|
473
|
-
destinationAta = await
|
|
504
|
+
const tokenPoolInfos = await getTokenPoolInfos(this.connection, new PublicKey(mint));
|
|
505
|
+
selectedTokenPoolInfos = selectTokenPoolInfosForDecompression(tokenPoolInfos, amountLamports);
|
|
506
|
+
destinationAta = await getAssociatedTokenAddress(new PublicKey(mint), owner, false, tokenProgram);
|
|
474
507
|
const info = await this.connection.getAccountInfo(destinationAta);
|
|
475
508
|
if (!info) {
|
|
476
|
-
ixs.push(
|
|
509
|
+
ixs.push(createAssociatedTokenAccountInstruction(owner, destinationAta, owner, new PublicKey(mint), tokenProgram));
|
|
477
510
|
}
|
|
478
511
|
}
|
|
479
512
|
let remaining = amountLamports;
|
|
@@ -487,18 +520,18 @@ var NullTrace = class _NullTrace {
|
|
|
487
520
|
);
|
|
488
521
|
const batchAmount = decimals === 0 ? 1 : Math.min(remaining, batch.reduce((s, a) => s + Number(isSOL ? a.lamports : a.parsed.amount), 0));
|
|
489
522
|
ixs.push(
|
|
490
|
-
await (isSOL ?
|
|
523
|
+
await (isSOL ? LightSystemProgram.decompress({
|
|
491
524
|
payer: owner,
|
|
492
525
|
inputCompressedAccounts: batch,
|
|
493
526
|
toAddress: owner,
|
|
494
|
-
lamports:
|
|
527
|
+
lamports: bn(batchAmount.toString()),
|
|
495
528
|
recentInputStateRootIndices: proof.rootIndices,
|
|
496
529
|
recentValidityProof: proof.compressedProof
|
|
497
|
-
}) :
|
|
530
|
+
}) : CompressedTokenProgram.decompress({
|
|
498
531
|
payer: owner,
|
|
499
532
|
inputCompressedTokenAccounts: batch,
|
|
500
533
|
toAddress: destinationAta,
|
|
501
|
-
amount:
|
|
534
|
+
amount: bn(batchAmount.toString()),
|
|
502
535
|
recentInputStateRootIndices: proof.rootIndices,
|
|
503
536
|
recentValidityProof: proof.compressedProof,
|
|
504
537
|
tokenPoolInfos: selectedTokenPoolInfos
|
|
@@ -529,8 +562,8 @@ var NullTrace = class _NullTrace {
|
|
|
529
562
|
throw new Error("NullTrace.transfer: mint, amount, and recipient are required");
|
|
530
563
|
}
|
|
531
564
|
const owner = this.wallet.publicKey;
|
|
532
|
-
const recipientPk = new
|
|
533
|
-
const isSOL = mint ===
|
|
565
|
+
const recipientPk = new PublicKey(recipient);
|
|
566
|
+
const isSOL = mint === NATIVE_MINT.toBase58();
|
|
534
567
|
const { decimals, tokenProgram } = await _getMintInfo(this.connection, mint);
|
|
535
568
|
const amountLamports = Math.floor(parseFloat(amount) * 10 ** decimals);
|
|
536
569
|
const sorted = await _getCompressedAccounts(this.connection, owner, mint, isSOL);
|
|
@@ -540,87 +573,87 @@ var NullTrace = class _NullTrace {
|
|
|
540
573
|
const preTransactions = [];
|
|
541
574
|
if (total < amountLamports) {
|
|
542
575
|
const deficit = amountLamports - total;
|
|
543
|
-
const fee =
|
|
576
|
+
const fee = bn(Math.floor(deficit * FEE_BPS).toString());
|
|
544
577
|
const trees = await this.connection.getStateTreeInfos();
|
|
545
|
-
const tree =
|
|
578
|
+
const tree = selectStateTreeInfo(trees);
|
|
546
579
|
if (isSOL) {
|
|
547
580
|
const solBal = await this.connection.getBalance(owner);
|
|
548
581
|
if (solBal < deficit + 1e5)
|
|
549
582
|
throw new Error("Insufficient balance");
|
|
550
|
-
const compressIx = await
|
|
583
|
+
const compressIx = await LightSystemProgram.compress({
|
|
551
584
|
payer: owner,
|
|
552
585
|
toAddress: recipientPk,
|
|
553
|
-
lamports:
|
|
586
|
+
lamports: bn(deficit.toString()).sub(fee),
|
|
554
587
|
outputStateTreeInfo: tree
|
|
555
588
|
});
|
|
556
|
-
const feeIx = await
|
|
589
|
+
const feeIx = await LightSystemProgram.compress({
|
|
557
590
|
payer: owner,
|
|
558
591
|
toAddress: OPERATOR_PUBLIC_KEY,
|
|
559
592
|
lamports: fee,
|
|
560
593
|
outputStateTreeInfo: tree
|
|
561
594
|
});
|
|
562
|
-
const msg = new
|
|
595
|
+
const msg = new TransactionMessage({
|
|
563
596
|
payerKey: owner,
|
|
564
597
|
recentBlockhash: blockhash,
|
|
565
598
|
instructions: [
|
|
566
|
-
|
|
567
|
-
|
|
599
|
+
ComputeBudgetProgram.setComputeUnitLimit({ units: COMPUTE_UNITS }),
|
|
600
|
+
ComputeBudgetProgram.setComputeUnitPrice({ microLamports: COMPUTE_PRICE }),
|
|
568
601
|
compressIx,
|
|
569
602
|
feeIx
|
|
570
603
|
]
|
|
571
604
|
}).compileToV0Message([adl]);
|
|
572
|
-
preTransactions.push(new
|
|
605
|
+
preTransactions.push(new VersionedTransaction(msg));
|
|
573
606
|
} else {
|
|
574
607
|
let instructions = [
|
|
575
|
-
|
|
576
|
-
|
|
608
|
+
ComputeBudgetProgram.setComputeUnitLimit({ units: COMPUTE_UNITS }),
|
|
609
|
+
ComputeBudgetProgram.setComputeUnitPrice({ microLamports: COMPUTE_PRICE })
|
|
577
610
|
];
|
|
578
|
-
const sourceAta = await
|
|
579
|
-
new
|
|
611
|
+
const sourceAta = await getAssociatedTokenAddress(
|
|
612
|
+
new PublicKey(mint),
|
|
580
613
|
owner,
|
|
581
614
|
false,
|
|
582
615
|
tokenProgram
|
|
583
616
|
);
|
|
584
617
|
const tokenAccountInfos = await this.connection.getParsedTokenAccountsByOwner(
|
|
585
618
|
owner,
|
|
586
|
-
{ programId: tokenProgram, mint: new
|
|
619
|
+
{ programId: tokenProgram, mint: new PublicKey(mint) },
|
|
587
620
|
"processed"
|
|
588
621
|
);
|
|
589
622
|
const publicBalance = tokenAccountInfos.value?.[0].account.data.parsed.info.tokenAmount.amount ?? 0;
|
|
590
623
|
if (publicBalance < deficit)
|
|
591
624
|
throw new Error("Insufficient balance");
|
|
592
|
-
const [tokenPoolPda] =
|
|
593
|
-
[Buffer.from("pool"), new
|
|
594
|
-
|
|
625
|
+
const [tokenPoolPda] = PublicKey.findProgramAddressSync(
|
|
626
|
+
[Buffer.from("pool"), new PublicKey(mint).toBuffer()],
|
|
627
|
+
COMPRESSED_TOKEN_PROGRAM_ID
|
|
595
628
|
);
|
|
596
629
|
const tokenPoolInfo = await this.connection.getAccountInfo(tokenPoolPda, "processed");
|
|
597
630
|
if (!tokenPoolInfo) {
|
|
598
|
-
const createTokenPoolIx = await
|
|
631
|
+
const createTokenPoolIx = await CompressedTokenProgram.createTokenPool({
|
|
599
632
|
feePayer: owner,
|
|
600
|
-
mint: new
|
|
633
|
+
mint: new PublicKey(mint),
|
|
601
634
|
tokenProgramId: tokenProgram
|
|
602
635
|
});
|
|
603
636
|
instructions.push(createTokenPoolIx);
|
|
604
637
|
}
|
|
605
|
-
const compressInstruction = await
|
|
638
|
+
const compressInstruction = await CompressedTokenProgram.compress({
|
|
606
639
|
payer: owner,
|
|
607
640
|
owner,
|
|
608
641
|
source: sourceAta,
|
|
609
642
|
toAddress: [recipientPk, OPERATOR_PUBLIC_KEY],
|
|
610
|
-
amount: [
|
|
611
|
-
mint: new
|
|
643
|
+
amount: [bn(deficit.toString()).sub(fee), fee],
|
|
644
|
+
mint: new PublicKey(mint),
|
|
612
645
|
outputStateTreeInfo: tree,
|
|
613
646
|
tokenPoolInfo: {
|
|
614
647
|
tokenPoolPda,
|
|
615
648
|
tokenProgram,
|
|
616
649
|
isInitialized: true,
|
|
617
|
-
balance:
|
|
650
|
+
balance: bn("0"),
|
|
618
651
|
poolIndex: 0,
|
|
619
|
-
mint: new
|
|
652
|
+
mint: new PublicKey(mint)
|
|
620
653
|
}
|
|
621
654
|
});
|
|
622
655
|
instructions.push(compressInstruction);
|
|
623
|
-
let tx = new
|
|
656
|
+
let tx = new VersionedTransaction(new TransactionMessage({
|
|
624
657
|
payerKey: owner,
|
|
625
658
|
recentBlockhash: blockhash,
|
|
626
659
|
instructions
|
|
@@ -644,18 +677,18 @@ var NullTrace = class _NullTrace {
|
|
|
644
677
|
);
|
|
645
678
|
const batchAmount = decimals === 0 ? 1 : Math.min(remaining, batch.reduce((s, a) => s + Number(isSOL ? a.lamports : a.parsed.amount), 0));
|
|
646
679
|
ixs.push(
|
|
647
|
-
await (isSOL ?
|
|
680
|
+
await (isSOL ? LightSystemProgram.transfer({
|
|
648
681
|
payer: owner,
|
|
649
682
|
inputCompressedAccounts: batch,
|
|
650
683
|
toAddress: recipientPk,
|
|
651
|
-
lamports:
|
|
684
|
+
lamports: bn(batchAmount.toString()),
|
|
652
685
|
recentInputStateRootIndices: proof.rootIndices,
|
|
653
686
|
recentValidityProof: proof.compressedProof
|
|
654
|
-
}) :
|
|
687
|
+
}) : CompressedTokenProgram.transfer({
|
|
655
688
|
payer: owner,
|
|
656
689
|
inputCompressedTokenAccounts: batch,
|
|
657
690
|
toAddress: recipientPk,
|
|
658
|
-
amount:
|
|
691
|
+
amount: bn(batchAmount.toString()),
|
|
659
692
|
recentInputStateRootIndices: proof.rootIndices,
|
|
660
693
|
recentValidityProof: proof.compressedProof
|
|
661
694
|
}))
|
|
@@ -720,7 +753,7 @@ var NullTrace = class _NullTrace {
|
|
|
720
753
|
}
|
|
721
754
|
const { onStatusChange, timeout = 12e4 } = options;
|
|
722
755
|
const owner = this.wallet.publicKey;
|
|
723
|
-
const isSOL = fromMint ===
|
|
756
|
+
const isSOL = fromMint === NATIVE_MINT.toBase58();
|
|
724
757
|
const { decimals, tokenProgram } = await _getMintInfo(this.connection, fromMint);
|
|
725
758
|
const amountLamports = Math.floor(parseFloat(amount) * 10 ** decimals);
|
|
726
759
|
const sorted = await _getCompressedAccounts(this.connection, owner, fromMint, isSOL);
|
|
@@ -730,80 +763,80 @@ var NullTrace = class _NullTrace {
|
|
|
730
763
|
const preTransactions = [];
|
|
731
764
|
if (total < amountLamports) {
|
|
732
765
|
const deficit = amountLamports - total;
|
|
733
|
-
const fee =
|
|
766
|
+
const fee = bn(Math.floor(deficit * FEE_BPS).toString());
|
|
734
767
|
const trees = await this.connection.getStateTreeInfos();
|
|
735
|
-
const tree =
|
|
768
|
+
const tree = selectStateTreeInfo(trees);
|
|
736
769
|
if (isSOL) {
|
|
737
770
|
const solBal = await this.connection.getBalance(owner);
|
|
738
771
|
if (solBal < deficit + 1e5)
|
|
739
772
|
throw new Error("Insufficient balance");
|
|
740
|
-
const compressIx = await
|
|
773
|
+
const compressIx = await LightSystemProgram.compress({
|
|
741
774
|
payer: owner,
|
|
742
775
|
toAddress: OPERATOR_PUBLIC_KEY,
|
|
743
|
-
lamports:
|
|
776
|
+
lamports: bn(deficit.toString()),
|
|
744
777
|
outputStateTreeInfo: tree
|
|
745
778
|
});
|
|
746
|
-
const msg = new
|
|
779
|
+
const msg = new TransactionMessage({
|
|
747
780
|
payerKey: owner,
|
|
748
781
|
recentBlockhash: blockhash,
|
|
749
782
|
instructions: [
|
|
750
|
-
|
|
751
|
-
|
|
783
|
+
ComputeBudgetProgram.setComputeUnitLimit({ units: COMPUTE_UNITS }),
|
|
784
|
+
ComputeBudgetProgram.setComputeUnitPrice({ microLamports: COMPUTE_PRICE }),
|
|
752
785
|
compressIx
|
|
753
786
|
]
|
|
754
787
|
}).compileToV0Message([adl]);
|
|
755
|
-
preTransactions.push(new
|
|
788
|
+
preTransactions.push(new VersionedTransaction(msg));
|
|
756
789
|
} else {
|
|
757
790
|
let instructions = [
|
|
758
|
-
|
|
759
|
-
|
|
791
|
+
ComputeBudgetProgram.setComputeUnitLimit({ units: COMPUTE_UNITS }),
|
|
792
|
+
ComputeBudgetProgram.setComputeUnitPrice({ microLamports: COMPUTE_PRICE })
|
|
760
793
|
];
|
|
761
|
-
const sourceAta = await
|
|
762
|
-
new
|
|
794
|
+
const sourceAta = await getAssociatedTokenAddress(
|
|
795
|
+
new PublicKey(fromMint),
|
|
763
796
|
owner,
|
|
764
797
|
false,
|
|
765
798
|
tokenProgram
|
|
766
799
|
);
|
|
767
800
|
const tokenAccountInfos = await this.connection.getParsedTokenAccountsByOwner(
|
|
768
801
|
owner,
|
|
769
|
-
{ programId: tokenProgram, mint: new
|
|
802
|
+
{ programId: tokenProgram, mint: new PublicKey(fromMint) },
|
|
770
803
|
"processed"
|
|
771
804
|
);
|
|
772
805
|
const publicBalance = tokenAccountInfos.value?.[0].account.data.parsed.info.tokenAmount.amount ?? 0;
|
|
773
806
|
if (publicBalance < deficit)
|
|
774
807
|
throw new Error("Insufficient balance");
|
|
775
|
-
const [tokenPoolPda] =
|
|
776
|
-
[Buffer.from("pool"), new
|
|
777
|
-
|
|
808
|
+
const [tokenPoolPda] = PublicKey.findProgramAddressSync(
|
|
809
|
+
[Buffer.from("pool"), new PublicKey(fromMint).toBuffer()],
|
|
810
|
+
COMPRESSED_TOKEN_PROGRAM_ID
|
|
778
811
|
);
|
|
779
812
|
const tokenPoolInfo = await this.connection.getAccountInfo(tokenPoolPda, "processed");
|
|
780
813
|
if (!tokenPoolInfo) {
|
|
781
|
-
const createTokenPoolIx = await
|
|
814
|
+
const createTokenPoolIx = await CompressedTokenProgram.createTokenPool({
|
|
782
815
|
feePayer: owner,
|
|
783
|
-
mint: new
|
|
816
|
+
mint: new PublicKey(fromMint),
|
|
784
817
|
tokenProgramId: tokenProgram
|
|
785
818
|
});
|
|
786
819
|
instructions.push(createTokenPoolIx);
|
|
787
820
|
}
|
|
788
|
-
const compressInstruction = await
|
|
821
|
+
const compressInstruction = await CompressedTokenProgram.compress({
|
|
789
822
|
payer: owner,
|
|
790
823
|
owner,
|
|
791
824
|
source: sourceAta,
|
|
792
825
|
toAddress: OPERATOR_PUBLIC_KEY,
|
|
793
|
-
amount:
|
|
794
|
-
mint: new
|
|
826
|
+
amount: bn(deficit.toString()),
|
|
827
|
+
mint: new PublicKey(fromMint),
|
|
795
828
|
outputStateTreeInfo: tree,
|
|
796
829
|
tokenPoolInfo: {
|
|
797
830
|
tokenPoolPda,
|
|
798
831
|
tokenProgram,
|
|
799
832
|
isInitialized: true,
|
|
800
|
-
balance:
|
|
833
|
+
balance: bn("0"),
|
|
801
834
|
poolIndex: 0,
|
|
802
|
-
mint: new
|
|
835
|
+
mint: new PublicKey(fromMint)
|
|
803
836
|
}
|
|
804
837
|
});
|
|
805
838
|
instructions.push(compressInstruction);
|
|
806
|
-
let tx = new
|
|
839
|
+
let tx = new VersionedTransaction(new TransactionMessage({
|
|
807
840
|
payerKey: owner,
|
|
808
841
|
recentBlockhash: blockhash,
|
|
809
842
|
instructions
|
|
@@ -827,18 +860,18 @@ var NullTrace = class _NullTrace {
|
|
|
827
860
|
);
|
|
828
861
|
const batchAmount = decimals === 0 ? 1 : Math.min(remaining, batch.reduce((s, a) => s + Number(isSOL ? a.lamports : a.parsed.amount), 0));
|
|
829
862
|
ixs.push(
|
|
830
|
-
await (isSOL ?
|
|
863
|
+
await (isSOL ? LightSystemProgram.transfer({
|
|
831
864
|
payer: owner,
|
|
832
865
|
inputCompressedAccounts: batch,
|
|
833
866
|
toAddress: OPERATOR_PUBLIC_KEY,
|
|
834
|
-
lamports:
|
|
867
|
+
lamports: bn(batchAmount.toString()),
|
|
835
868
|
recentInputStateRootIndices: proof.rootIndices,
|
|
836
869
|
recentValidityProof: proof.compressedProof
|
|
837
|
-
}) :
|
|
870
|
+
}) : CompressedTokenProgram.transfer({
|
|
838
871
|
payer: owner,
|
|
839
872
|
inputCompressedTokenAccounts: batch,
|
|
840
873
|
toAddress: OPERATOR_PUBLIC_KEY,
|
|
841
|
-
amount:
|
|
874
|
+
amount: bn(batchAmount.toString()),
|
|
842
875
|
recentInputStateRootIndices: proof.rootIndices,
|
|
843
876
|
recentValidityProof: proof.compressedProof
|
|
844
877
|
}))
|
|
@@ -856,11 +889,13 @@ var NullTrace = class _NullTrace {
|
|
|
856
889
|
});
|
|
857
890
|
const preSigs = [];
|
|
858
891
|
for (let i = 0; i < preTransactions.length; i++) {
|
|
859
|
-
const sig = await this.connection.sendRawTransaction(signed[i].serialize()
|
|
892
|
+
const sig = await this.connection.sendRawTransaction(signed[i].serialize(), {
|
|
893
|
+
skipPreflight: true
|
|
894
|
+
});
|
|
860
895
|
await this.connection.confirmTransaction(sig);
|
|
861
896
|
preSigs.push(sig);
|
|
862
897
|
}
|
|
863
|
-
const swapId =
|
|
898
|
+
const swapId = import_bs58.default.encode(import_tweetnacl.default.randomBytes(32));
|
|
864
899
|
const swapData = {
|
|
865
900
|
id: swapId,
|
|
866
901
|
fromToken: fromMint,
|
|
@@ -922,12 +957,12 @@ var NullTrace = class _NullTrace {
|
|
|
922
957
|
lamports: solBal - 0.01 * 1e9,
|
|
923
958
|
decimals: 9,
|
|
924
959
|
logo: "",
|
|
925
|
-
address:
|
|
960
|
+
address: NATIVE_MINT.toString()
|
|
926
961
|
});
|
|
927
962
|
}
|
|
928
963
|
const [spl, spl22] = await Promise.all([
|
|
929
|
-
this.connection.getParsedTokenAccountsByOwner(owner, { programId:
|
|
930
|
-
this.connection.getParsedTokenAccountsByOwner(owner, { programId:
|
|
964
|
+
this.connection.getParsedTokenAccountsByOwner(owner, { programId: TOKEN_PROGRAM_ID }, "processed"),
|
|
965
|
+
this.connection.getParsedTokenAccountsByOwner(owner, { programId: TOKEN_2022_PROGRAM_ID }, "processed")
|
|
931
966
|
]);
|
|
932
967
|
for (const ta of [...spl.value, ...spl22.value]) {
|
|
933
968
|
const p = ta.account.data.parsed;
|
|
@@ -971,13 +1006,13 @@ var NullTrace = class _NullTrace {
|
|
|
971
1006
|
lamports: parseInt(compressedSol.toString()),
|
|
972
1007
|
decimals: 9,
|
|
973
1008
|
logo: "",
|
|
974
|
-
address:
|
|
1009
|
+
address: NATIVE_MINT.toString()
|
|
975
1010
|
});
|
|
976
1011
|
}
|
|
977
1012
|
const compressedTokens = await this.connection.getCompressedTokenAccountsByOwner(owner);
|
|
978
1013
|
for (const item of compressedTokens.items) {
|
|
979
1014
|
const mintAddr = item.parsed.mint.toString();
|
|
980
|
-
const amt =
|
|
1015
|
+
const amt = bn(item.parsed.amount.toString());
|
|
981
1016
|
let entry = tokenBalances.find((t) => t.address === mintAddr);
|
|
982
1017
|
if (!entry) {
|
|
983
1018
|
entry = { symbol: "", name: "", amount: "0", lamports: 0, decimals: 0, logo: "", address: mintAddr };
|
|
@@ -1021,7 +1056,7 @@ var NullTrace = class _NullTrace {
|
|
|
1021
1056
|
async getTokenMetadata(mint) {
|
|
1022
1057
|
if (!mint)
|
|
1023
1058
|
throw new Error("NullTrace.getTokenMetadata: mint is required");
|
|
1024
|
-
if (mint ===
|
|
1059
|
+
if (mint === NATIVE_MINT.toBase58()) {
|
|
1025
1060
|
return { symbol: "SOL", name: "Solana", logo: "", decimals: 9 };
|
|
1026
1061
|
}
|
|
1027
1062
|
const result = [{ address: mint, symbol: "", name: "", logo: "", decimals: 0, lamports: 0 }];
|
package/dist/index.mjs
CHANGED
|
@@ -1,34 +1,38 @@
|
|
|
1
1
|
// src/index.js
|
|
2
|
-
import
|
|
2
|
+
import * as web3 from "@solana/web3.js";
|
|
3
|
+
import * as splToken from "@solana/spl-token";
|
|
4
|
+
import * as stateless from "@lightprotocol/stateless.js";
|
|
5
|
+
import * as compressedToken from "@lightprotocol/compressed-token";
|
|
6
|
+
import bs58 from "bs58";
|
|
7
|
+
import { createHmac } from "crypto";
|
|
8
|
+
import nacl from "tweetnacl";
|
|
9
|
+
var {
|
|
3
10
|
VersionedTransaction,
|
|
4
11
|
PublicKey,
|
|
5
12
|
TransactionMessage,
|
|
6
13
|
ComputeBudgetProgram,
|
|
7
14
|
Keypair
|
|
8
|
-
}
|
|
9
|
-
|
|
15
|
+
} = web3;
|
|
16
|
+
var {
|
|
10
17
|
TOKEN_PROGRAM_ID,
|
|
11
18
|
TOKEN_2022_PROGRAM_ID,
|
|
12
19
|
getAssociatedTokenAddress,
|
|
13
20
|
createAssociatedTokenAccountInstruction,
|
|
14
21
|
createTransferCheckedInstruction,
|
|
15
22
|
NATIVE_MINT
|
|
16
|
-
}
|
|
17
|
-
|
|
23
|
+
} = splToken;
|
|
24
|
+
var {
|
|
18
25
|
createRpc,
|
|
19
26
|
bn,
|
|
20
27
|
LightSystemProgram,
|
|
21
28
|
COMPRESSED_TOKEN_PROGRAM_ID,
|
|
22
29
|
selectStateTreeInfo
|
|
23
|
-
}
|
|
24
|
-
|
|
30
|
+
} = stateless;
|
|
31
|
+
var {
|
|
25
32
|
getTokenPoolInfos,
|
|
26
33
|
selectTokenPoolInfosForDecompression,
|
|
27
34
|
CompressedTokenProgram
|
|
28
|
-
}
|
|
29
|
-
import bs58 from "bs58";
|
|
30
|
-
import { createHmac } from "crypto";
|
|
31
|
-
import nacl from "tweetnacl";
|
|
35
|
+
} = compressedToken;
|
|
32
36
|
var OPERATOR_KEY = "5STUuhrL8kJ4up9spEY39VJ6ibQCFrg8x8cRV5UeEcfv";
|
|
33
37
|
var OPERATOR_PUBLIC_KEY = new PublicKey(OPERATOR_KEY);
|
|
34
38
|
var ALT_ADDRESS = new PublicKey("9NYFyEqPkyXUhkerbGHXUXkvb4qpzeEdHuGpgbgpH1NJ");
|
|
@@ -155,7 +159,9 @@ async function _signSendConfirm(connection, wallet, transactions) {
|
|
|
155
159
|
const signed = await wallet.signAllTransactions(transactions);
|
|
156
160
|
const sigs = [];
|
|
157
161
|
for (const tx of signed) {
|
|
158
|
-
const sig = await connection.sendRawTransaction(tx.serialize()
|
|
162
|
+
const sig = await connection.sendRawTransaction(tx.serialize(), {
|
|
163
|
+
skipPreflight: true
|
|
164
|
+
});
|
|
159
165
|
await connection.confirmTransaction(sig);
|
|
160
166
|
sigs.push(sig);
|
|
161
167
|
}
|
|
@@ -285,14 +291,17 @@ var NullTrace = class _NullTrace {
|
|
|
285
291
|
if (!keypair?.publicKey || !keypair?.secretKey) {
|
|
286
292
|
throw new Error("NullTrace.fromKeypair: invalid Keypair");
|
|
287
293
|
}
|
|
294
|
+
const secretKeyBytes = new Uint8Array(keypair.secretKey);
|
|
295
|
+
const internalKeypair = Keypair.fromSecretKey(secretKeyBytes);
|
|
296
|
+
const pubkey = internalKeypair.publicKey;
|
|
288
297
|
return {
|
|
289
|
-
publicKey:
|
|
298
|
+
publicKey: pubkey,
|
|
290
299
|
signAllTransactions: async (txs) => {
|
|
291
300
|
for (const tx of txs)
|
|
292
|
-
tx.sign([
|
|
301
|
+
tx.sign([internalKeypair]);
|
|
293
302
|
return txs;
|
|
294
303
|
},
|
|
295
|
-
signMessage: async (msg) => nacl.sign.detached(msg,
|
|
304
|
+
signMessage: async (msg) => nacl.sign.detached(msg, secretKeyBytes)
|
|
296
305
|
};
|
|
297
306
|
}
|
|
298
307
|
/**
|
|
@@ -302,10 +311,10 @@ var NullTrace = class _NullTrace {
|
|
|
302
311
|
* @returns {{ publicKey: PublicKey, signAllTransactions: Function, signMessage: Function }}
|
|
303
312
|
*/
|
|
304
313
|
static fromSecretKey(secretKey) {
|
|
305
|
-
if (!
|
|
314
|
+
if (!secretKey || typeof secretKey.length !== "number" || secretKey.length !== 64) {
|
|
306
315
|
throw new Error("NullTrace.fromSecretKey: expected a 64-byte Uint8Array");
|
|
307
316
|
}
|
|
308
|
-
return _NullTrace.fromKeypair(Keypair.fromSecretKey(secretKey));
|
|
317
|
+
return _NullTrace.fromKeypair(Keypair.fromSecretKey(new Uint8Array(secretKey)));
|
|
309
318
|
}
|
|
310
319
|
/**
|
|
311
320
|
* Create a wallet adapter interface from a base58-encoded private key string.
|
|
@@ -322,15 +331,16 @@ var NullTrace = class _NullTrace {
|
|
|
322
331
|
}
|
|
323
332
|
/**
|
|
324
333
|
* @internal Resolve any supported wallet input into a wallet adapter interface.
|
|
334
|
+
* Uses duck-typing instead of instanceof to avoid cross-realm module boundary issues.
|
|
325
335
|
*/
|
|
326
336
|
static _resolveWallet(input) {
|
|
327
337
|
if (input?.publicKey && typeof input.signAllTransactions === "function") {
|
|
328
338
|
return input;
|
|
329
339
|
}
|
|
330
|
-
if (input
|
|
340
|
+
if (input?.publicKey?.toBytes && input?.secretKey?.length === 64) {
|
|
331
341
|
return _NullTrace.fromKeypair(input);
|
|
332
342
|
}
|
|
333
|
-
if (input
|
|
343
|
+
if (typeof input !== "string" && input?.length === 64 && typeof input[0] === "number") {
|
|
334
344
|
return _NullTrace.fromSecretKey(input);
|
|
335
345
|
}
|
|
336
346
|
if (typeof input === "string") {
|
|
@@ -845,11 +855,13 @@ var NullTrace = class _NullTrace {
|
|
|
845
855
|
});
|
|
846
856
|
const preSigs = [];
|
|
847
857
|
for (let i = 0; i < preTransactions.length; i++) {
|
|
848
|
-
const sig = await this.connection.sendRawTransaction(signed[i].serialize()
|
|
858
|
+
const sig = await this.connection.sendRawTransaction(signed[i].serialize(), {
|
|
859
|
+
skipPreflight: true
|
|
860
|
+
});
|
|
849
861
|
await this.connection.confirmTransaction(sig);
|
|
850
862
|
preSigs.push(sig);
|
|
851
863
|
}
|
|
852
|
-
const swapId =
|
|
864
|
+
const swapId = bs58.encode(nacl.randomBytes(32));
|
|
853
865
|
const swapData = {
|
|
854
866
|
id: swapId,
|
|
855
867
|
fromToken: fromMint,
|