@@ -12,7 +12,14 @@ import {
1212 sendAndConfirmTx ,
1313 dedupeSigner ,
1414 assertBetaEnabled ,
15+ LIGHT_TOKEN_PROGRAM_ID ,
1516} from '@lightprotocol/stateless.js' ;
17+ import {
18+ TOKEN_PROGRAM_ID ,
19+ TOKEN_2022_PROGRAM_ID ,
20+ createApproveInstruction as createSplApproveInstruction ,
21+ createRevokeInstruction as createSplRevokeInstruction ,
22+ } from '@solana/spl-token' ;
1623import BN from 'bn.js' ;
1724import {
1825 createLightTokenApproveInstruction ,
@@ -40,18 +47,20 @@ function calculateApproveCU(loadBatch: InternalLoadBatch | null): number {
4047}
4148
4249/**
43- * Approve a delegate for a light-token associated token account.
50+ * Approve a delegate for an associated token account.
4451 *
45- * Loads cold accounts if needed, then sends the approve instruction.
52+ * Supports light-token, SPL, and Token-2022 mints. For light-token mints,
53+ * loads cold accounts if needed before sending the approve instruction.
4654 *
4755 * @param rpc RPC connection
4856 * @param payer Fee payer (signer)
49- * @param tokenAccount Light-token ATA address
57+ * @param tokenAccount ATA address
5058 * @param mint Mint address
5159 * @param delegate Delegate to approve
5260 * @param amount Amount to delegate
5361 * @param owner Owner of the token account (signer)
5462 * @param confirmOptions Optional confirm options
63+ * @param programId Token program ID (default: LIGHT_TOKEN_PROGRAM_ID)
5564 * @returns Transaction signature
5665 */
5766export async function approveInterface (
@@ -63,12 +72,15 @@ export async function approveInterface(
6372 amount : number | bigint | BN ,
6473 owner : Signer ,
6574 confirmOptions ?: ConfirmOptions ,
75+ programId : PublicKey = LIGHT_TOKEN_PROGRAM_ID ,
6676) : Promise < TransactionSignature > {
6777 assertBetaEnabled ( ) ;
6878
6979 const expectedAta = getAssociatedTokenAddressInterface (
7080 mint ,
7181 owner . publicKey ,
82+ false ,
83+ programId ,
7284 ) ;
7385 if ( ! tokenAccount . equals ( expectedAta ) ) {
7486 throw new Error (
@@ -86,6 +98,7 @@ export async function approveInterface(
8698 amount ,
8799 owner . publicKey ,
88100 mintInterface . mint . decimals ,
101+ programId ,
89102 ) ;
90103
91104 const additionalSigners = dedupeSigner ( payer , [ owner ] ) ;
@@ -115,18 +128,20 @@ export async function approveInterface(
115128}
116129
117130/**
118- * Build instruction batches for approving a delegate on a light-token ATA.
131+ * Build instruction batches for approving a delegate on an ATA.
119132 *
133+ * Supports light-token, SPL, and Token-2022 mints.
120134 * Returns `TransactionInstruction[][]`. Send [0..n-2] in parallel, then [n-1].
121135 *
122136 * @param rpc RPC connection
123137 * @param payer Fee payer public key
124138 * @param mint Mint address
125- * @param tokenAccount Light-token ATA address
139+ * @param tokenAccount ATA address
126140 * @param delegate Delegate to approve
127141 * @param amount Amount to delegate
128142 * @param owner Owner public key
129143 * @param decimals Token decimals
144+ * @param programId Token program ID (default: LIGHT_TOKEN_PROGRAM_ID)
130145 * @returns Instruction batches
131146 */
132147export async function createApproveInterfaceInstructions (
@@ -138,20 +153,49 @@ export async function createApproveInterfaceInstructions(
138153 amount : number | bigint | BN ,
139154 owner : PublicKey ,
140155 decimals : number ,
156+ programId : PublicKey = LIGHT_TOKEN_PROGRAM_ID ,
141157) : Promise < TransactionInstruction [ ] [ ] > {
142158 assertBetaEnabled ( ) ;
143159
144160 const amountBigInt = BigInt ( amount . toString ( ) ) ;
145161
162+ const isSplOrT22 =
163+ programId . equals ( TOKEN_PROGRAM_ID ) ||
164+ programId . equals ( TOKEN_2022_PROGRAM_ID ) ;
165+
146166 const accountInterface = await _getAtaInterface (
147167 rpc ,
148168 tokenAccount ,
149169 owner ,
150170 mint ,
171+ undefined ,
172+ isSplOrT22 ? programId : undefined ,
151173 ) ;
152174
153175 checkNotFrozen ( accountInterface , 'approve' ) ;
154176
177+ if ( isSplOrT22 ) {
178+ const approveIx = createSplApproveInstruction (
179+ tokenAccount ,
180+ delegate ,
181+ owner ,
182+ amountBigInt ,
183+ [ ] ,
184+ programId ,
185+ ) ;
186+
187+ const numSigners = payer . equals ( owner ) ? 1 : 2 ;
188+ const txIxs = [
189+ ComputeBudgetProgram . setComputeUnitLimit ( {
190+ units : APPROVE_BASE_CU ,
191+ } ) ,
192+ approveIx ,
193+ ] ;
194+ assertTransactionSizeWithinLimit ( txIxs , numSigners , 'Batch' ) ;
195+ return [ txIxs ] ;
196+ }
197+
198+ // Light-token path: load cold accounts if needed
155199 const internalBatches = await _buildLoadBatches (
156200 rpc ,
157201 payer ,
@@ -223,16 +267,18 @@ export async function createApproveInterfaceInstructions(
223267}
224268
225269/**
226- * Revoke delegation for a light-token associated token account.
270+ * Revoke delegation for an associated token account.
227271 *
228- * Loads cold accounts if needed, then sends the revoke instruction.
272+ * Supports light-token, SPL, and Token-2022 mints. For light-token mints,
273+ * loads cold accounts if needed before sending the revoke instruction.
229274 *
230275 * @param rpc RPC connection
231276 * @param payer Fee payer (signer)
232- * @param tokenAccount Light-token ATA address
277+ * @param tokenAccount ATA address
233278 * @param mint Mint address
234279 * @param owner Owner of the token account (signer)
235280 * @param confirmOptions Optional confirm options
281+ * @param programId Token program ID (default: LIGHT_TOKEN_PROGRAM_ID)
236282 * @returns Transaction signature
237283 */
238284export async function revokeInterface (
@@ -242,12 +288,15 @@ export async function revokeInterface(
242288 mint : PublicKey ,
243289 owner : Signer ,
244290 confirmOptions ?: ConfirmOptions ,
291+ programId : PublicKey = LIGHT_TOKEN_PROGRAM_ID ,
245292) : Promise < TransactionSignature > {
246293 assertBetaEnabled ( ) ;
247294
248295 const expectedAta = getAssociatedTokenAddressInterface (
249296 mint ,
250297 owner . publicKey ,
298+ false ,
299+ programId ,
251300 ) ;
252301 if ( ! tokenAccount . equals ( expectedAta ) ) {
253302 throw new Error (
@@ -263,6 +312,7 @@ export async function revokeInterface(
263312 tokenAccount ,
264313 owner . publicKey ,
265314 mintInterface . mint . decimals ,
315+ programId ,
266316 ) ;
267317
268318 const additionalSigners = dedupeSigner ( payer , [ owner ] ) ;
@@ -287,16 +337,18 @@ export async function revokeInterface(
287337}
288338
289339/**
290- * Build instruction batches for revoking delegation on a light-token ATA.
340+ * Build instruction batches for revoking delegation on an ATA.
291341 *
342+ * Supports light-token, SPL, and Token-2022 mints.
292343 * Returns `TransactionInstruction[][]`. Send [0..n-2] in parallel, then [n-1].
293344 *
294345 * @param rpc RPC connection
295346 * @param payer Fee payer public key
296347 * @param mint Mint address
297- * @param tokenAccount Light-token ATA address
348+ * @param tokenAccount ATA address
298349 * @param owner Owner public key
299350 * @param decimals Token decimals
351+ * @param programId Token program ID (default: LIGHT_TOKEN_PROGRAM_ID)
300352 * @returns Instruction batches
301353 */
302354export async function createRevokeInterfaceInstructions (
@@ -306,18 +358,45 @@ export async function createRevokeInterfaceInstructions(
306358 tokenAccount : PublicKey ,
307359 owner : PublicKey ,
308360 decimals : number ,
361+ programId : PublicKey = LIGHT_TOKEN_PROGRAM_ID ,
309362) : Promise < TransactionInstruction [ ] [ ] > {
310363 assertBetaEnabled ( ) ;
311364
365+ const isSplOrT22 =
366+ programId . equals ( TOKEN_PROGRAM_ID ) ||
367+ programId . equals ( TOKEN_2022_PROGRAM_ID ) ;
368+
312369 const accountInterface = await _getAtaInterface (
313370 rpc ,
314371 tokenAccount ,
315372 owner ,
316373 mint ,
374+ undefined ,
375+ isSplOrT22 ? programId : undefined ,
317376 ) ;
318377
319378 checkNotFrozen ( accountInterface , 'revoke' ) ;
320379
380+ if ( isSplOrT22 ) {
381+ const revokeIx = createSplRevokeInstruction (
382+ tokenAccount ,
383+ owner ,
384+ [ ] ,
385+ programId ,
386+ ) ;
387+
388+ const numSigners = payer . equals ( owner ) ? 1 : 2 ;
389+ const txIxs = [
390+ ComputeBudgetProgram . setComputeUnitLimit ( {
391+ units : APPROVE_BASE_CU ,
392+ } ) ,
393+ revokeIx ,
394+ ] ;
395+ assertTransactionSizeWithinLimit ( txIxs , numSigners , 'Batch' ) ;
396+ return [ txIxs ] ;
397+ }
398+
399+ // Light-token path: load cold accounts if needed
321400 const internalBatches = await _buildLoadBatches (
322401 rpc ,
323402 payer ,
0 commit comments