Skip to content

Commit 1381378

Browse files
author
tilo-14
committed
Bump to beta.12, fix all examples, add CI for toolkits
- Bump @lightprotocol/compressed-token and stateless.js to ^0.23.0-beta.12 - Fix wrap/unwrap examples: replace removed decompressInterface, use TOKEN_PROGRAM_ID - Fix delegate-transfer: use SPL mint + wrap pattern for hot balance - Fix load-ata instruction: import from /unified, fix batching - Fix gasless-transfer: pass recipient owner, not ATA address - Fix gasless-transactions Cargo.toml: update binary path after rename - Add CI jobs for payments toolkit and gasless-transactions TypeScript - Remove dead script entries from typescript-client package.json - Rename send examples to basic-send-action/instruction - Add batch-send-instruction with createLightTokenTransferInstruction - Update READMEs with renamed files and new examples Entire-Checkpoint: 4afa49be1970
1 parent 45e3688 commit 1381378

13 files changed

Lines changed: 226 additions & 106 deletions

File tree

.github/workflows/typescript-tests.yml

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,61 @@ jobs:
5050
- name: Run instructions
5151
working-directory: typescript-client
5252
run: npm run test:instructions
53+
54+
payments-toolkit:
55+
name: Payments Toolkit
56+
runs-on: ubuntu-latest
57+
steps:
58+
- uses: actions/checkout@v4
59+
60+
- name: Setup environment
61+
uses: ./.github/actions/setup
62+
with:
63+
example: toolkits/payments
64+
solana-cli-version: ${{ env.SOLANA_CLI_VERSION }}
65+
photon-indexer: "true"
66+
67+
- name: Install dependencies
68+
working-directory: toolkits/payments
69+
run: npm install
70+
71+
- name: Start test validator
72+
run: |
73+
light test-validator &
74+
for i in $(seq 1 60); do
75+
curl -s http://127.0.0.1:8784/health && break
76+
sleep 2
77+
done
78+
79+
- name: Run tests
80+
working-directory: toolkits/payments
81+
run: npm run test:all
82+
83+
gasless-transactions-ts:
84+
name: Gasless Transactions (TypeScript)
85+
runs-on: ubuntu-latest
86+
steps:
87+
- uses: actions/checkout@v4
88+
89+
- name: Setup environment
90+
uses: ./.github/actions/setup
91+
with:
92+
example: toolkits/gasless-transactions/typescript
93+
solana-cli-version: ${{ env.SOLANA_CLI_VERSION }}
94+
photon-indexer: "true"
95+
96+
- name: Install dependencies
97+
working-directory: toolkits/gasless-transactions/typescript
98+
run: npm install
99+
100+
- name: Start test validator
101+
run: |
102+
light test-validator &
103+
for i in $(seq 1 60); do
104+
curl -s http://127.0.0.1:8784/health && break
105+
sleep 2
106+
done
107+
108+
- name: Run tests
109+
working-directory: toolkits/gasless-transactions/typescript
110+
run: npm run test:all

toolkits/README.md

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@ Stablecoin payment examples using the Light Token interface APIs. Same stablecoi
88
See the [payments README](payments/README.md) for API comparison and setup.
99

1010
**Send payments**
11-
- **[send-action](payments/send/send-action.ts)** — Send tokens. One call handles loading and recipient account creation.
12-
- **[send-instruction](payments/send/send-instruction.ts)** — Same transfer, but returns raw instructions for custom transaction building.
13-
- **[batch-send](payments/send/batch-send.ts)** — Pay multiple recipients in one transaction
11+
- **[basic-send-action](payments/send/basic-send-action.ts)** — Send tokens. One call handles loading and recipient account creation.
12+
- **[basic-send-instruction](payments/send/basic-send-instruction.ts)** — Same transfer, but returns raw instructions for custom transaction building.
13+
- **[batch-send-action](payments/send/batch-send-action.ts)** — Pay multiple recipients sequentially
14+
- **[batch-send-instruction](payments/send/batch-send-instruction.ts)** — Pay multiple recipients in one transaction
1415
- **[payment-with-memo](payments/send/payment-with-memo.ts)** — Attach an invoice ID or payment reference to a transfer
1516
- **[sign-all-transactions](payments/send/sign-all-transactions.ts)** — Sign all transactions with one wallet approval. Shows parallel load optimization.
1617

@@ -29,7 +30,7 @@ See the [payments README](payments/README.md) for API comparison and setup.
2930
- **[delegate-approve](payments/spend-permissions/delegate-approve.ts)** — Let a delegate spend tokens on your behalf
3031
- **[delegate-revoke](payments/spend-permissions/delegate-revoke.ts)** — Revoke delegate access
3132
- **[delegate-check](payments/spend-permissions/delegate-check.ts)** — Check current delegation status and remaining allowance
32-
- **[delegate-full-flow](payments/spend-permissions/delegate-full-flow.ts)**Approve, check, and revoke in one script
33+
- **[delegate-transfer](payments/spend-permissions/delegate-transfer.ts)**Delegate transfers tokens on behalf of owner
3334

3435
### Sign with Privy
3536

@@ -53,6 +54,13 @@ Abstract SOL fees so users never hold SOL. Set your application as the fee payer
5354
- **[TypeScript](gasless-transactions/typescript/)** — Gasless transfer with separate fee payer
5455
- **[Rust](gasless-transactions/rust/)** — Gasless transfer with separate fee payer
5556

57+
### [Nullifier Program](nullifier-program/)
58+
59+
For some use cases, such as sending payments, you might want to prevent your onchain instruction from being executed more than once. The nullifier program utility solves this for you. We also deployed a reference implementation to public networks so you can get started quickly.
60+
- **[TypeScript example](nullifier-program/examples/action-create-nullifier.ts)**
61+
- **[Rust example](nullifier-program/examples/rust/src/main.rs)**
62+
- **[Documentation](https://www.zkcompression.com/compressed-pdas/guides/how-to-create-nullifier-pdas)**
63+
5664
## Documentation
5765

5866
- [Light Token overview](https://www.zkcompression.com/light-token/welcome)

toolkits/gasless-transactions/typescript/gasless-transfer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ console.log("Recipient Address:", recipient.publicKey.toBase58());
5454
mint,
5555
500_000,
5656
sender.publicKey,
57-
recipientAta,
57+
recipient.publicKey,
5858
);
5959

6060
// Send — sponsor pays fees, sender authorizes transfer

toolkits/gasless-transactions/typescript/package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,11 @@
44
"description": "Gasless transactions — abstract SOL fees so users never hold SOL",
55
"type": "module",
66
"scripts": {
7+
"test:all": "tsx gasless-transfer.ts",
78
"gasless-transfer": "tsx gasless-transfer.ts"
89
},
910
"dependencies": {
10-
"@lightprotocol/compressed-token": "^0.23.0-beta.10",
11-
"@lightprotocol/stateless.js": "^0.23.0-beta.10"
11+
"@lightprotocol/compressed-token": "^0.23.0-beta.12",
12+
"@lightprotocol/stateless.js": "^0.23.0-beta.12"
1213
}
1314
}

toolkits/payments/README.md

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,12 @@ Light Token reduces account creation cost by 200x compared to SPL. Transfer cost
2727

2828
### Send payments
2929

30-
| File | Description | Key function |
31-
|:-----|:------------|:-------------|
32-
| [send-action.ts](send/send-action.ts) | Send tokens. One call handles loading and recipient account creation. | `transferInterface` |
33-
| [send-instruction.ts](send/send-instruction.ts) | Same transfer, but returns raw instructions for custom transaction building. | `createTransferInterfaceInstructions` |
34-
| [payment-with-memo.ts](send/payment-with-memo.ts) | Attach an invoice ID or payment reference. Reads it back from transaction logs. | `createTransferInterfaceInstructions`, `sliceLast` |
35-
| [batch-send.ts](send/batch-send.ts) | Pay multiple recipients in one transaction. | `createTransferInterfaceInstructions`, `createAtaInterfaceIdempotent` |
36-
| [sign-all-transactions.ts](send/sign-all-transactions.ts) | Sign all transactions with one wallet approval. Shows parallel load optimization. | `signAllTransactions`, `sliceLast` |
30+
| Example | Description | Action | Instruction |
31+
|:--------|:------------|:-------|:------------|
32+
| Basic send | Send tokens to a recipient. | [action](send/basic-send-action.ts) | [instruction](send/basic-send-instruction.ts) |
33+
| Batch send | Pay multiple recipients in one transaction. | [action](send/batch-send-action.ts) | [instruction](send/batch-send-instruction.ts) |
34+
| Payment with memo | Attach an invoice ID or payment reference. | | [instruction](send/payment-with-memo.ts) |
35+
| Sign all transactions | Sign all transactions with one wallet approval. | | [instruction](send/sign-all-transactions.ts) |
3736
| [verify-address.ts](verify/verify-address.ts) | Confirm a recipient account exists before sending. | `getAssociatedTokenAddressInterface`, `getAtaInterface` |
3837

3938
> For gasless transfers (separate fee payer / sponsor), see the [gasless-transactions](../gasless-transactions/) toolkit.
@@ -81,9 +80,9 @@ light test-validator
8180
Run any script:
8281

8382
```bash
84-
npx tsx send/send-action.ts
83+
npx tsx send/basic-send-action.ts
8584
npx tsx send/payment-with-memo.ts
86-
npx tsx send/batch-send.ts
85+
npx tsx send/batch-send-action.ts
8786
npx tsx spend-permissions/delegate-approve.ts
8887
```
8988

toolkits/payments/package.json

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@
44
"description": "Light Token Payments Toolkit Examples",
55
"type": "module",
66
"scripts": {
7-
"test:all": "tsx send/send-action.ts && tsx send/send-instruction.ts && tsx send/payment-with-memo.ts && tsx send/batch-send.ts && tsx send/sign-all-transactions.ts && tsx receive/receive.ts && tsx spend-permissions/delegate-approve.ts && tsx spend-permissions/delegate-revoke.ts && tsx spend-permissions/delegate-check.ts && tsx spend-permissions/delegate-transfer.ts",
8-
"send-action": "tsx send/send-action.ts",
9-
"send-instruction": "tsx send/send-instruction.ts",
7+
"test:all": "tsx send/basic-send-action.ts && tsx send/basic-send-instruction.ts && tsx send/payment-with-memo.ts && tsx send/batch-send-action.ts && tsx send/batch-send-instruction.ts && tsx send/sign-all-transactions.ts && tsx receive/receive.ts && tsx spend-permissions/delegate-approve.ts && tsx spend-permissions/delegate-revoke.ts && tsx spend-permissions/delegate-check.ts && tsx spend-permissions/delegate-transfer.ts",
8+
"basic-send-action": "tsx send/basic-send-action.ts",
9+
"basic-send-instruction": "tsx send/basic-send-instruction.ts",
1010
"payment-with-memo": "tsx send/payment-with-memo.ts",
11-
"batch-send": "tsx send/batch-send.ts",
11+
"batch-send-action": "tsx send/batch-send-action.ts",
12+
"batch-send-instruction": "tsx send/batch-send-instruction.ts",
1213
"sign-all-transactions": "tsx send/sign-all-transactions.ts",
1314
"receive": "tsx receive/receive.ts",
1415
"get-balance": "tsx verify/get-balance.ts",

typescript-client/actions/delegate-transfer.ts

Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,19 @@ import { Keypair } from "@solana/web3.js";
33
import { createRpc } from "@lightprotocol/stateless.js";
44
import {
55
createMintInterface,
6-
mintToCompressed,
6+
createAtaInterface,
77
getAssociatedTokenAddressInterface,
88
} from "@lightprotocol/compressed-token";
99
import {
1010
approveInterface,
1111
transferInterface,
12+
wrap,
1213
} from "@lightprotocol/compressed-token/unified";
14+
import {
15+
TOKEN_PROGRAM_ID,
16+
createAssociatedTokenAccount,
17+
mintTo,
18+
} from "@solana/spl-token";
1319
import { homedir } from "os";
1420
import { readFileSync } from "fs";
1521

@@ -26,12 +32,41 @@ const payer = Keypair.fromSecretKey(
2632
);
2733

2834
(async function () {
29-
const { mint } = await createMintInterface(rpc, payer, payer, null, 9);
30-
await mintToCompressed(rpc, payer, mint, payer, [
31-
{ recipient: payer.publicKey, amount: 1_000_000_000n },
32-
]);
35+
// Setup: Create SPL mint, fund, wrap into Light ATA (hot balance)
36+
const { mint } = await createMintInterface(
37+
rpc,
38+
payer,
39+
payer,
40+
null,
41+
9,
42+
undefined,
43+
undefined,
44+
TOKEN_PROGRAM_ID
45+
);
46+
const splAta = await createAssociatedTokenAccount(
47+
rpc,
48+
payer,
49+
mint,
50+
payer.publicKey,
51+
undefined,
52+
TOKEN_PROGRAM_ID
53+
);
54+
await mintTo(rpc, payer, mint, splAta, payer, 1_000_000_000);
55+
await createAtaInterface(rpc, payer, mint, payer.publicKey);
56+
const senderAta = getAssociatedTokenAddressInterface(
57+
mint,
58+
payer.publicKey
59+
);
60+
await wrap(
61+
rpc,
62+
payer,
63+
splAta,
64+
senderAta,
65+
payer,
66+
mint,
67+
BigInt(1_000_000_000)
68+
);
3369

34-
const senderAta = getAssociatedTokenAddressInterface(mint, payer.publicKey);
3570
const delegate = Keypair.generate();
3671
const recipient = Keypair.generate();
3772

@@ -57,7 +92,6 @@ const payer = Keypair.fromSecretKey(
5792
delegate,
5893
200_000_000,
5994
undefined,
60-
undefined,
6195
{ owner: payer.publicKey }
6296
);
6397

typescript-client/actions/unwrap.ts

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@ import { createRpc } from "@lightprotocol/stateless.js";
44
import {
55
createMintInterface,
66
createAtaInterface,
7-
mintToInterface,
87
getAssociatedTokenAddressInterface,
98
} from "@lightprotocol/compressed-token";
10-
import { unwrap } from "@lightprotocol/compressed-token/unified";
9+
import { wrap, unwrap } from "@lightprotocol/compressed-token/unified";
1110
import {
11+
TOKEN_PROGRAM_ID,
1212
createAssociatedTokenAccount,
13-
TOKEN_2022_PROGRAM_ID,
13+
mintTo,
1414
} from "@solana/spl-token";
1515
import { homedir } from "os";
1616
import { readFileSync } from "fs";
@@ -28,24 +28,35 @@ const payer = Keypair.fromSecretKey(
2828
);
2929

3030
(async function () {
31-
// Setup: Create and mint tokens to light-token associated token account
32-
const { mint } = await createMintInterface(rpc, payer, payer, null, 9);
33-
await createAtaInterface(rpc, payer, mint, payer.publicKey);
34-
const destination = getAssociatedTokenAddressInterface(
35-
mint,
36-
payer.publicKey
31+
// Setup: Create SPL mint, fund SPL ATA, wrap into Light ATA
32+
const { mint } = await createMintInterface(
33+
rpc,
34+
payer,
35+
payer,
36+
null,
37+
9,
38+
undefined,
39+
undefined,
40+
TOKEN_PROGRAM_ID
3741
);
38-
await mintToInterface(rpc, payer, mint, destination, payer, 1000);
39-
40-
// Unwrap light-token to SPL associated token account
4142
const splAta = await createAssociatedTokenAccount(
4243
rpc,
4344
payer,
4445
mint,
4546
payer.publicKey,
4647
undefined,
47-
TOKEN_2022_PROGRAM_ID
48+
TOKEN_PROGRAM_ID
4849
);
50+
await mintTo(rpc, payer, mint, splAta, payer, 1000);
51+
52+
await createAtaInterface(rpc, payer, mint, payer.publicKey);
53+
const lightTokenAta = getAssociatedTokenAddressInterface(
54+
mint,
55+
payer.publicKey
56+
);
57+
await wrap(rpc, payer, splAta, lightTokenAta, payer, mint, BigInt(1000));
58+
59+
// Unwrap: move tokens back from light-token to SPL ATA
4960
const tx = await unwrap(rpc, payer, splAta, payer, mint, 500);
5061

5162
console.log("Tx:", tx);

typescript-client/actions/wrap.ts

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,13 @@ import { createRpc } from "@lightprotocol/stateless.js";
44
import {
55
createMintInterface,
66
createAtaInterface,
7-
mintToInterface,
8-
decompressInterface,
9-
wrap,
107
getAssociatedTokenAddressInterface,
11-
createAtaInterfaceIdempotent,
128
} from "@lightprotocol/compressed-token";
9+
import { wrap } from "@lightprotocol/compressed-token/unified";
1310
import {
11+
TOKEN_PROGRAM_ID,
1412
createAssociatedTokenAccount,
15-
TOKEN_2022_PROGRAM_ID,
13+
mintTo,
1614
} from "@solana/spl-token";
1715
import { homedir } from "os";
1816
import { readFileSync } from "fs";
@@ -30,30 +28,33 @@ const payer = Keypair.fromSecretKey(
3028
);
3129

3230
(async function () {
33-
// Setup: Get SPL tokens (needed to wrap)
34-
const { mint } = await createMintInterface(rpc, payer, payer, null, 9);
35-
await createAtaInterface(rpc, payer, mint, payer.publicKey);
36-
const destination = getAssociatedTokenAddressInterface(
37-
mint,
38-
payer.publicKey
31+
// Setup: Create SPL mint and fund an SPL ATA
32+
const { mint } = await createMintInterface(
33+
rpc,
34+
payer,
35+
payer,
36+
null,
37+
9,
38+
undefined,
39+
undefined,
40+
TOKEN_PROGRAM_ID
3941
);
40-
await mintToInterface(rpc, payer, mint, destination, payer, 1000);
4142
const splAta = await createAssociatedTokenAccount(
4243
rpc,
4344
payer,
4445
mint,
4546
payer.publicKey,
4647
undefined,
47-
TOKEN_2022_PROGRAM_ID
48+
TOKEN_PROGRAM_ID
4849
);
49-
await decompressInterface(rpc, payer, payer, mint, 1000);
50+
await mintTo(rpc, payer, mint, splAta, payer, 1000);
5051

51-
// Wrap SPL tokens to light-token associated token account
52+
// Create light-token ATA and wrap SPL tokens into it
53+
await createAtaInterface(rpc, payer, mint, payer.publicKey);
5254
const lightTokenAta = getAssociatedTokenAddressInterface(
5355
mint,
5456
payer.publicKey
5557
);
56-
await createAtaInterfaceIdempotent(rpc, payer, mint, payer.publicKey);
5758

5859
const tx = await wrap(rpc, payer, splAta, lightTokenAta, payer, mint, 500);
5960

0 commit comments

Comments
 (0)