@unclaimedsol/spl-burn-close-sdk 1.2.0 โ 1.2.1
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 +22 -3
- package/dist/index.cjs +27 -25
- package/dist/index.d.ts +2 -1
- package/dist/index.js +9 -12
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -9,6 +9,7 @@ This library only **builds unsigned transactions** โ you handle signing and se
|
|
|
9
9
|
- ๐งน Close token accounts, reclaiming rent to the user.
|
|
10
10
|
- ๐ธ Automatic 5% protocol fee (hardcoded in program).
|
|
11
11
|
- โก Automatic batching (default 12 ATAs per transaction).
|
|
12
|
+
- ๐ช Supports SPL Token and Token-2022.
|
|
12
13
|
- ๐ Supports **frontend partial signing** and **backend full signing** workflows.
|
|
13
14
|
- ๐ No hidden config: single function to integrate.
|
|
14
15
|
|
|
@@ -29,7 +30,7 @@ This library only **builds unsigned transactions** โ you handle signing and se
|
|
|
29
30
|
npm i @unclaimedsol/spl-burn-close-sdk
|
|
30
31
|
```
|
|
31
32
|
|
|
32
|
-
We use @solana/web3.js in peerDependencies to avoid version conflicts
|
|
33
|
+
We use @solana/web3.js in peerDependencies to avoid version conflicts, so make sure you already have it installed.
|
|
33
34
|
|
|
34
35
|
Requires Node 18+.
|
|
35
36
|
|
|
@@ -40,7 +41,7 @@ Requires Node 18+.
|
|
|
40
41
|
### Signing with Keypair
|
|
41
42
|
|
|
42
43
|
```typescript
|
|
43
|
-
import { Connection, Keypair } from "@solana/web3.js";
|
|
44
|
+
import { Connection, Keypair, PublicKey } from "@solana/web3.js";
|
|
44
45
|
import {
|
|
45
46
|
buildBurnAndCloseTransactions,
|
|
46
47
|
PROGRAM_ID,
|
|
@@ -82,6 +83,7 @@ import { Connection, PublicKey } from "@solana/web3.js";
|
|
|
82
83
|
import {
|
|
83
84
|
buildBurnAndCloseTransactions,
|
|
84
85
|
PROGRAM_ID,
|
|
86
|
+
TOKEN_2022_PROGRAM_ID,
|
|
85
87
|
} from "@unclaimedsol/spl-burn-close-sdk";
|
|
86
88
|
|
|
87
89
|
const connection = new Connection("https://api.mainnet-beta.solana.com");
|
|
@@ -100,6 +102,16 @@ const txs = await buildBurnAndCloseTransactions(
|
|
|
100
102
|
pairs
|
|
101
103
|
);
|
|
102
104
|
|
|
105
|
+
// For Token-2022 accounts, pass TOKEN_2022_PROGRAM_ID and consider using a smaller chunkSize:
|
|
106
|
+
// const txs = await buildBurnAndCloseTransactions(
|
|
107
|
+
// connection,
|
|
108
|
+
// PROGRAM_ID,
|
|
109
|
+
// user,
|
|
110
|
+
// pairs,
|
|
111
|
+
// { chunkSize: 2 },
|
|
112
|
+
// TOKEN_2022_PROGRAM_ID
|
|
113
|
+
// );
|
|
114
|
+
|
|
103
115
|
// Sign
|
|
104
116
|
const signed = wallet.signAllTransactions
|
|
105
117
|
? await wallet.signAllTransactions(txs)
|
|
@@ -107,7 +119,7 @@ const signed = wallet.signAllTransactions
|
|
|
107
119
|
|
|
108
120
|
// Send
|
|
109
121
|
for (const stx of signed) {
|
|
110
|
-
const sig = await connection.sendRawTransaction(
|
|
122
|
+
const sig = await connection.sendRawTransaction(stx.serialize());
|
|
111
123
|
let latestBlockhash = await connection.getLatestBlockhash(
|
|
112
124
|
connection.commitment
|
|
113
125
|
);
|
|
@@ -122,6 +134,13 @@ for (const stx of signed) {
|
|
|
122
134
|
|
|
123
135
|
---
|
|
124
136
|
|
|
137
|
+
## ๐ Cluster support
|
|
138
|
+
|
|
139
|
+
This SDK targets the Unclaimed SOL mainnet program (`PROGRAM_ID`) and fee recipient (`FEE_RECIPIENT`).
|
|
140
|
+
Transactions will only succeed on a cluster where that program is deployed.
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
125
144
|
## ๐ป Demo
|
|
126
145
|
|
|
127
146
|
There is a nice tutorial guide with a demo repository that shows the usage of the SDK to burn and close all token accounts for the wallet. You can find it [here](https://blog.unclaimedsol.com/close-burn-solana-tokens-web3js-sdk/).
|
package/dist/index.cjs
CHANGED
|
@@ -1,9 +1,15 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TOKEN_2022_PROGRAM_ID = exports.TOKEN_PROGRAM_ID = exports.FEE_RECIPIENT = exports.PROGRAM_ID = void 0;
|
|
4
|
+
exports.buildBurnAndCloseTransactions = buildBurnAndCloseTransactions;
|
|
5
|
+
exports.buildBurnAndCloseInstruction = buildBurnAndCloseInstruction;
|
|
6
|
+
const web3_js_1 = require("@solana/web3.js");
|
|
2
7
|
/** Exporting on-chain program ID for convenience */
|
|
3
|
-
|
|
8
|
+
exports.PROGRAM_ID = new web3_js_1.PublicKey("UNCaXzXkR3vp8mbCJyxWUvwuRk5uHgzrwe6jcWPfiUR");
|
|
4
9
|
/** Hardcoded fee recipient on-chain expectation */
|
|
5
|
-
|
|
6
|
-
|
|
10
|
+
exports.FEE_RECIPIENT = new web3_js_1.PublicKey("uncNCRycMtNPj2kXHfwiCgNrzCTnC9xU5FS8ZeWyn3M");
|
|
11
|
+
exports.TOKEN_PROGRAM_ID = new web3_js_1.PublicKey("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA");
|
|
12
|
+
exports.TOKEN_2022_PROGRAM_ID = new web3_js_1.PublicKey("TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb");
|
|
7
13
|
/**
|
|
8
14
|
* Build *unsigned* transactions that call the on-chain burn+close program.
|
|
9
15
|
* You sign and send them yourself (frontend wallet or backend keypair).
|
|
@@ -16,11 +22,11 @@ const TOKEN_PROGRAM_ID = new PublicKey("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ
|
|
|
16
22
|
* @param tokenProgramId Support for multiple Token programs
|
|
17
23
|
* @returns Array of *unsigned* Transaction objects
|
|
18
24
|
*/
|
|
19
|
-
|
|
25
|
+
async function buildBurnAndCloseTransactions(connection, programId, user, pairs, options = {}, tokenProgramId = exports.TOKEN_PROGRAM_ID) {
|
|
20
26
|
if (!pairs.length)
|
|
21
27
|
return [];
|
|
22
28
|
const chunkSize = Math.max(1, options.chunkSize ?? 12);
|
|
23
|
-
const commitment = options.commitment ?? "
|
|
29
|
+
const commitment = options.commitment ?? "confirmed";
|
|
24
30
|
const feePayer = options.feePayer ?? user;
|
|
25
31
|
// Split into chunks so we stay under CU / account limits
|
|
26
32
|
const chunks = [];
|
|
@@ -28,35 +34,31 @@ export async function buildBurnAndCloseTransactions(connection, programId, user,
|
|
|
28
34
|
chunks.push(pairs.slice(i, i + chunkSize));
|
|
29
35
|
}
|
|
30
36
|
// Instruction data: [selector=0]
|
|
31
|
-
|
|
37
|
+
// Use Uint8Array (browser-safe) and cast for web3.js' Buffer typing.
|
|
38
|
+
const data = new Uint8Array([0]);
|
|
39
|
+
const recentBlockhash = options.recentBlockhash ??
|
|
40
|
+
(await connection.getLatestBlockhash({ commitment })).blockhash;
|
|
32
41
|
const txs = [];
|
|
33
42
|
for (const chunk of chunks) {
|
|
34
43
|
const keys = [
|
|
35
44
|
// NOTE: Mark the user as signer in the instruction meta;
|
|
36
45
|
// the caller must actually sign the Transaction later.
|
|
37
|
-
{ pubkey: FEE_RECIPIENT, isSigner: false, isWritable: true },
|
|
46
|
+
{ pubkey: exports.FEE_RECIPIENT, isSigner: false, isWritable: true },
|
|
38
47
|
{ pubkey: user, isSigner: true, isWritable: true },
|
|
39
48
|
{ pubkey: tokenProgramId, isSigner: false, isWritable: false },
|
|
40
|
-
{ pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
|
|
49
|
+
{ pubkey: web3_js_1.SystemProgram.programId, isSigner: false, isWritable: false },
|
|
41
50
|
];
|
|
42
51
|
for (const { mint, ata } of chunk) {
|
|
43
52
|
keys.push({ pubkey: mint, isSigner: false, isWritable: true }, { pubkey: ata, isSigner: false, isWritable: true });
|
|
44
53
|
}
|
|
45
|
-
const ix = new TransactionInstruction({
|
|
54
|
+
const ix = new web3_js_1.TransactionInstruction({
|
|
46
55
|
programId,
|
|
47
56
|
keys,
|
|
48
57
|
data,
|
|
49
58
|
});
|
|
50
|
-
const tx = new Transaction().add(ix);
|
|
59
|
+
const tx = new web3_js_1.Transaction().add(ix);
|
|
51
60
|
tx.feePayer = feePayer;
|
|
52
|
-
|
|
53
|
-
if (options.recentBlockhash) {
|
|
54
|
-
tx.recentBlockhash = options.recentBlockhash;
|
|
55
|
-
}
|
|
56
|
-
else {
|
|
57
|
-
const { blockhash } = await connection.getLatestBlockhash({ commitment });
|
|
58
|
-
tx.recentBlockhash = blockhash;
|
|
59
|
-
}
|
|
61
|
+
tx.recentBlockhash = recentBlockhash;
|
|
60
62
|
txs.push(tx);
|
|
61
63
|
}
|
|
62
64
|
return txs;
|
|
@@ -69,28 +71,28 @@ export async function buildBurnAndCloseTransactions(connection, programId, user,
|
|
|
69
71
|
* create or sign full transactions โ it only constructs one
|
|
70
72
|
* instruction for a batch of (mint, ATA) pairs.
|
|
71
73
|
*/
|
|
72
|
-
|
|
74
|
+
async function buildBurnAndCloseInstruction(programId, user, pairs, tokenProgramId) {
|
|
73
75
|
if (!pairs.length) {
|
|
74
76
|
return null;
|
|
75
77
|
}
|
|
76
78
|
// instruction data selector: 0 = burn_and_close_token_accounts
|
|
77
|
-
const data =
|
|
79
|
+
const data = new Uint8Array([0]);
|
|
78
80
|
// accounts order MUST match the on-chain program's expectation:
|
|
79
|
-
// [0]
|
|
81
|
+
// [0] fee_recipient_account (your fee recipient)
|
|
80
82
|
// [1] user_wallet_account (the signer)
|
|
81
83
|
// [2] token_program_account (SPL Token program or Token-2022 program)
|
|
82
84
|
// [3] system_program_account
|
|
83
85
|
// then repeating (mint, ata) pairs, both writable
|
|
84
86
|
const keys = [
|
|
85
|
-
{ pubkey: FEE_RECIPIENT, isSigner: false, isWritable: true },
|
|
87
|
+
{ pubkey: exports.FEE_RECIPIENT, isSigner: false, isWritable: true },
|
|
86
88
|
{ pubkey: user, isSigner: true, isWritable: true },
|
|
87
89
|
{ pubkey: tokenProgramId, isSigner: false, isWritable: false },
|
|
88
|
-
{ pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
|
|
90
|
+
{ pubkey: web3_js_1.SystemProgram.programId, isSigner: false, isWritable: false },
|
|
89
91
|
];
|
|
90
92
|
for (const { mint, ata } of pairs) {
|
|
91
93
|
keys.push({ pubkey: mint, isSigner: false, isWritable: true }, { pubkey: ata, isSigner: false, isWritable: true });
|
|
92
94
|
}
|
|
93
|
-
return new TransactionInstruction({
|
|
95
|
+
return new web3_js_1.TransactionInstruction({
|
|
94
96
|
programId,
|
|
95
97
|
keys,
|
|
96
98
|
data,
|
package/dist/index.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ export declare const PROGRAM_ID: PublicKey;
|
|
|
4
4
|
/** Hardcoded fee recipient on-chain expectation */
|
|
5
5
|
export declare const FEE_RECIPIENT: PublicKey;
|
|
6
6
|
export declare const TOKEN_PROGRAM_ID: PublicKey;
|
|
7
|
+
export declare const TOKEN_2022_PROGRAM_ID: PublicKey;
|
|
7
8
|
export type Pair = {
|
|
8
9
|
mint: PublicKey;
|
|
9
10
|
ata: PublicKey;
|
|
@@ -20,7 +21,7 @@ export type BuildOptions = {
|
|
|
20
21
|
feePayer?: PublicKey;
|
|
21
22
|
/**
|
|
22
23
|
* Provide your own recent blockhash (advanced). If omitted,
|
|
23
|
-
* we fetch a fresh one
|
|
24
|
+
* we fetch a fresh one and reuse it for all built transactions.
|
|
24
25
|
*/
|
|
25
26
|
recentBlockhash?: string;
|
|
26
27
|
};
|
package/dist/index.js
CHANGED
|
@@ -4,6 +4,7 @@ export const PROGRAM_ID = new PublicKey("UNCaXzXkR3vp8mbCJyxWUvwuRk5uHgzrwe6jcWP
|
|
|
4
4
|
/** Hardcoded fee recipient on-chain expectation */
|
|
5
5
|
export const FEE_RECIPIENT = new PublicKey("uncNCRycMtNPj2kXHfwiCgNrzCTnC9xU5FS8ZeWyn3M");
|
|
6
6
|
export const TOKEN_PROGRAM_ID = new PublicKey("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA");
|
|
7
|
+
export const TOKEN_2022_PROGRAM_ID = new PublicKey("TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb");
|
|
7
8
|
/**
|
|
8
9
|
* Build *unsigned* transactions that call the on-chain burn+close program.
|
|
9
10
|
* You sign and send them yourself (frontend wallet or backend keypair).
|
|
@@ -20,7 +21,7 @@ export async function buildBurnAndCloseTransactions(connection, programId, user,
|
|
|
20
21
|
if (!pairs.length)
|
|
21
22
|
return [];
|
|
22
23
|
const chunkSize = Math.max(1, options.chunkSize ?? 12);
|
|
23
|
-
const commitment = options.commitment ?? "
|
|
24
|
+
const commitment = options.commitment ?? "confirmed";
|
|
24
25
|
const feePayer = options.feePayer ?? user;
|
|
25
26
|
// Split into chunks so we stay under CU / account limits
|
|
26
27
|
const chunks = [];
|
|
@@ -28,7 +29,10 @@ export async function buildBurnAndCloseTransactions(connection, programId, user,
|
|
|
28
29
|
chunks.push(pairs.slice(i, i + chunkSize));
|
|
29
30
|
}
|
|
30
31
|
// Instruction data: [selector=0]
|
|
31
|
-
|
|
32
|
+
// Use Uint8Array (browser-safe) and cast for web3.js' Buffer typing.
|
|
33
|
+
const data = new Uint8Array([0]);
|
|
34
|
+
const recentBlockhash = options.recentBlockhash ??
|
|
35
|
+
(await connection.getLatestBlockhash({ commitment })).blockhash;
|
|
32
36
|
const txs = [];
|
|
33
37
|
for (const chunk of chunks) {
|
|
34
38
|
const keys = [
|
|
@@ -49,14 +53,7 @@ export async function buildBurnAndCloseTransactions(connection, programId, user,
|
|
|
49
53
|
});
|
|
50
54
|
const tx = new Transaction().add(ix);
|
|
51
55
|
tx.feePayer = feePayer;
|
|
52
|
-
|
|
53
|
-
if (options.recentBlockhash) {
|
|
54
|
-
tx.recentBlockhash = options.recentBlockhash;
|
|
55
|
-
}
|
|
56
|
-
else {
|
|
57
|
-
const { blockhash } = await connection.getLatestBlockhash({ commitment });
|
|
58
|
-
tx.recentBlockhash = blockhash;
|
|
59
|
-
}
|
|
56
|
+
tx.recentBlockhash = recentBlockhash;
|
|
60
57
|
txs.push(tx);
|
|
61
58
|
}
|
|
62
59
|
return txs;
|
|
@@ -74,9 +71,9 @@ export async function buildBurnAndCloseInstruction(programId, user, pairs, token
|
|
|
74
71
|
return null;
|
|
75
72
|
}
|
|
76
73
|
// instruction data selector: 0 = burn_and_close_token_accounts
|
|
77
|
-
const data =
|
|
74
|
+
const data = new Uint8Array([0]);
|
|
78
75
|
// accounts order MUST match the on-chain program's expectation:
|
|
79
|
-
// [0]
|
|
76
|
+
// [0] fee_recipient_account (your fee recipient)
|
|
80
77
|
// [1] user_wallet_account (the signer)
|
|
81
78
|
// [2] token_program_account (SPL Token program or Token-2022 program)
|
|
82
79
|
// [3] system_program_account
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unclaimedsol/spl-burn-close-sdk",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.1",
|
|
4
4
|
"description": "SDK to burn and close SPL token accounts via the Unclaimed SOL program (with a built-in 5% fee).",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Unclaimed SOL",
|
|
@@ -28,13 +28,14 @@
|
|
|
28
28
|
"README.md"
|
|
29
29
|
],
|
|
30
30
|
"scripts": {
|
|
31
|
-
"build": "tsc -p tsconfig.json && node ./scripts/build-cjs.js",
|
|
31
|
+
"build": "tsc -p tsconfig.json && tsc -p tsconfig.cjs.json && node ./scripts/build-cjs.js",
|
|
32
32
|
"prepublishOnly": "npm run build"
|
|
33
33
|
},
|
|
34
|
-
"
|
|
34
|
+
"peerDependencies": {
|
|
35
35
|
"@solana/web3.js": "^1.98.4"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
|
+
"@solana/web3.js": "^1.98.4",
|
|
38
39
|
"typescript": "^5.6.3"
|
|
39
40
|
},
|
|
40
41
|
"engines": {
|