Skip to content

Commit 84166d7

Browse files
author
tilo-14
committed
add spl t22 support
1 parent ad88122 commit 84166d7

5 files changed

Lines changed: 759 additions & 37 deletions

File tree

js/compressed-token/src/v3/actions/approve-interface.ts

Lines changed: 89 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -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';
1623
import BN from 'bn.js';
1724
import {
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
*/
5766
export 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
*/
132147
export 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
*/
238284
export 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
*/
302354
export 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,

js/compressed-token/src/v3/actions/transfer-delegated-interface.ts

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,28 +5,33 @@ import {
55
TransactionInstruction,
66
TransactionSignature,
77
} from '@solana/web3.js';
8-
import { Rpc, assertBetaEnabled } from '@lightprotocol/stateless.js';
8+
import {
9+
Rpc,
10+
assertBetaEnabled,
11+
LIGHT_TOKEN_PROGRAM_ID,
12+
} from '@lightprotocol/stateless.js';
913
import BN from 'bn.js';
1014
import { transferInterface } from './transfer-interface';
1115
import { createTransferInterfaceInstructions } from '../instructions/transfer-interface';
1216

1317
/**
14-
* Transfer tokens from a light-token ATA as an approved delegate.
18+
* Transfer tokens from an ATA as an approved delegate.
1519
*
16-
* Convenience wrapper around {@link transferInterface} that makes the
17-
* delegate-transfer API explicit: the delegate is a {@link Signer} (authority),
18-
* the owner is a {@link PublicKey} (used only for ATA derivation, does NOT
19-
* sign).
20+
* Supports light-token, SPL, and Token-2022 mints. Convenience wrapper
21+
* around {@link transferInterface} that makes the delegate-transfer API
22+
* explicit: the delegate is a {@link Signer} (authority), the owner is a
23+
* {@link PublicKey} (used only for ATA derivation, does NOT sign).
2024
*
2125
* @param rpc RPC connection
2226
* @param payer Fee payer (signer)
23-
* @param source Source light-token ATA (owner's account)
27+
* @param source Source ATA (owner's account)
2428
* @param mint Mint address
25-
* @param destination Destination light-token ATA
29+
* @param destination Destination ATA
2630
* @param delegate Delegate authority (signer)
2731
* @param owner Owner of the source ATA (does not sign)
2832
* @param amount Amount to transfer (must be within approved allowance)
2933
* @param confirmOptions Optional confirm options
34+
* @param programId Token program ID (default: LIGHT_TOKEN_PROGRAM_ID)
3035
* @returns Transaction signature
3136
*/
3237
export async function transferDelegatedInterface(
@@ -39,6 +44,7 @@ export async function transferDelegatedInterface(
3944
owner: PublicKey,
4045
amount: number | bigint | BN,
4146
confirmOptions?: ConfirmOptions,
47+
programId: PublicKey = LIGHT_TOKEN_PROGRAM_ID,
4248
): Promise<TransactionSignature> {
4349
assertBetaEnabled();
4450

@@ -50,15 +56,16 @@ export async function transferDelegatedInterface(
5056
destination,
5157
delegate,
5258
amount,
53-
undefined,
59+
programId,
5460
confirmOptions,
5561
{ owner },
5662
);
5763
}
5864

5965
/**
60-
* Build instruction batches for a delegated transfer on a light-token ATA.
66+
* Build instruction batches for a delegated transfer on an ATA.
6167
*
68+
* Supports light-token, SPL, and Token-2022 mints.
6269
* Returns `TransactionInstruction[][]`. Send [0..n-2] in parallel, then [n-1].
6370
*
6471
* @param rpc RPC connection
@@ -69,6 +76,7 @@ export async function transferDelegatedInterface(
6976
* @param owner Owner of the source ATA (for derivation)
7077
* @param destination Destination ATA address
7178
* @param decimals Token decimals
79+
* @param programId Token program ID (default: LIGHT_TOKEN_PROGRAM_ID)
7280
* @returns Instruction batches
7381
*/
7482
export async function createTransferDelegatedInterfaceInstructions(
@@ -80,6 +88,7 @@ export async function createTransferDelegatedInterfaceInstructions(
8088
owner: PublicKey,
8189
destination: PublicKey,
8290
decimals: number,
91+
programId: PublicKey = LIGHT_TOKEN_PROGRAM_ID,
8392
): Promise<TransactionInstruction[][]> {
8493
assertBetaEnabled();
8594

@@ -91,6 +100,6 @@ export async function createTransferDelegatedInterfaceInstructions(
91100
delegate,
92101
destination,
93102
decimals,
94-
{ owner },
103+
{ owner, programId },
95104
);
96105
}

0 commit comments

Comments
 (0)